• Linux应用调试之使用strace命令跟踪系统调用


    目录

    1 strace介绍

    2 strace移植

    3 使用strace调试程序

    3.1 strace的用法

    3.2 strace输出结果分析

    3.3 strace使用体验

    3.4 使用strace调试程序

    3.5 strace命令的原理


    1 strace介绍

    2 strace移植

    3 使用strace调试程序

    3.1 strace的用法

    运行strace -h可以看到strace的用法

    1. root@bm1684:/data/chw/bm_det_track# strace -h
    2. usage: strace [-CdffhiqrtttTvVwxxy] [-I n] [-e expr]...
    3. [-a column] [-o file] [-s strsize] [-P path]...
    4. -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]
    5. or: strace -c[dfw] [-I n] [-e expr]... [-O overhead] [-S sortby]
    6. -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]
    7. Output format:
    8. -a column alignment COLUMN for printing syscall results (default 40)
    9. -i print instruction pointer at time of syscall
    10. -o file send trace output to FILE instead of stderr
    11. -q suppress messages about attaching, detaching, etc.
    12. -r print relative timestamp
    13. -s strsize limit length of print strings to STRSIZE chars (default 32)
    14. -t print absolute timestamp
    15. -tt print absolute timestamp with usecs
    16. -T print time spent in each syscall
    17. -x print non-ascii strings in hex
    18. -xx print all strings in hex
    19. -y print paths associated with file descriptor arguments
    20. -yy print protocol specific information associated with socket file descriptors
    21. Statistics:
    22. -c count time, calls, and errors for each syscall and report summary
    23. -C like -c but also print regular output
    24. -O overhead set overhead for tracing syscalls to OVERHEAD usecs
    25. -S sortby sort syscall counts by: time, calls, name, nothing (default time)
    26. -w summarise syscall latency (default is system time)
    27. Filtering:
    28. -e expr a qualifying expression: option=[!]all or option=[!]val1[,val2]...
    29. options: trace, abbrev, verbose, raw, signal, read, write, fault
    30. -P path trace accesses to path
    31. Tracing:
    32. -b execve detach on execve syscall
    33. -D run tracer process as a detached grandchild, not as parent
    34. -f follow forks
    35. -ff follow forks with output into separate files
    36. -I interruptible
    37. 1: no signals are blocked
    38. 2: fatal signals are blocked while decoding syscall (default)
    39. 3: fatal signals are always blocked (default if '-o FILE PROG')
    40. 4: fatal signals and SIGTSTP (^Z) are always blocked
    41. (useful to make 'strace -o FILE PROG' not stop on ^Z)
    42. Startup:
    43. -E var remove var from the environment for command
    44. -E var=val put var=val in the environment for command
    45. -p pid trace process with process id PID, may be repeated
    46. -u username run command as username handling setuid and/or setgid
    47. Miscellaneous:
    48. -d enable debug output to stderr
    49. -v verbose mode: print unabbreviated argv, stat, termios, etc. args
    50. -h print help message
    51. -V print version

    3.2 strace输出结果分析

    3.3 strace使用体验

    我们使用strace跟踪我们前面的驱动测试程序

    strace -o log.txt ./firstdrvtest on

    得到

    前面首先是打开一大堆库,倒数第三行的open是打开这个文件,返回文件描述符3,倒数第二行是把中间的数写到文件fd为3的文件中,写的长度是4个字节。

    我们可以看到,strace可以打印出来我们的应用程序调用了哪些系统调用。

    3.4 使用strace调试程序

    如果我们用busybox-1.20,那么我们卸载驱动程序的时候可能会报错,我们用strace来看一下。

     然后编译选项里面加上交叉编译前缀,然后使用默认的配置,直接make

     编译过程中遇到了一些错误,为了省事直接把报错的命令不编译了,配置项里面把报错的项去掉,编译完之后替换掉之前的busybox.

     然后重启开发板,然后装卸、卸载驱动,报错了

     我们用strace命令看一下

    strace -o log.txt rmmod first_drv

    报错没有这么目录,那我们就创建这个目录,

     还是报错,那继续strace

    那么继续创建目录,错误消失

    3.5 strace命令的原理

    strace是一个父进程,它会创建一个子进程,子进程就就是对应的应用程序,

     我们应用层的open函数本质上就是执行了一个swi指令,然后发生异常进入内核态,

     我们到entry-common.S中看一下,然后在entry-common.S中搜索vector_swi

    1. ENTRY(vector_swi)
    2. sub sp, sp, #S_FRAME_SIZE
    3. stmia sp, {r0 - r12} @ Calling r0 - r12
    4. add r8, sp, #S_PC
    5. stmdb r8, {sp, lr}^ @ Calling sp, lr
    6. mrs r8, spsr @ called from non-FIQ mode, so ok.
    7. str lr, [sp, #S_PC] @ Save calling PC
    8. str r8, [sp, #S_PSR] @ Save CPSR
    9. str r0, [sp, #S_OLD_R0] @ Save OLD_R0
    10. zero_fp

    先是保存现场,然后往下看有这个

    1. stmdb sp!, {r4, r5} @ push fifth and sixth args
    2. tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
    3. bne __sys_trace
    4. cmp scno, #NR_syscalls @ check upper syscall limit
    5. adr lr, ret_fast_syscall @ return address
    6. ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine

    里面有个tst ip,测试应用程序是否被跟踪,如果被跟踪就bne __sys_trace

    1. /*
    2. * This is the really slow path. We're going to be doing
    3. * context switches, and waiting for our parent to respond.
    4. */
    5. __sys_trace:
    6. mov r2, scno
    7. add r1, sp, #S_OFF
    8. mov r0, #0 @ trace entry [IP = 0]
    9. bl syscall_trace

    然后子进程给父进程发一个信号,然后等待父进程,父进程记录了一些东西之后,然后子进程再继续跑。

  • 相关阅读:
    26.XML
    托管海外服务器有哪些要求?
    设置小数点后2位,随机保存财富txt,生成随机富翁数
    【设计大赛】基于RT-Thread和RA6M4实现samba服务的移动网盘
    【python基础】编写/运行hello world项目
    Mongodb数据库
    Qt开发技术:Q3D图表开发笔记(一):Q3DScatter三维散点图介绍、Demo以及代码详解
    大厂sql真题讲解(黑马)
    19.支持向量机-优化目标和大间距直观理解
    插入排序和冒泡排序
  • 原文地址:https://blog.csdn.net/u013171226/article/details/126358375