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的用法

root@bm1684:/data/chw/bm_det_track# strace -h
usage: strace [-CdffhiqrtttTvVwxxy] [-I n] [-e expr]...
              [-a column] [-o file] [-s strsize] [-P path]...
              -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]
   or: strace -c[dfw] [-I n] [-e expr]... [-O overhead] [-S sortby]
              -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]

Output format:
  -a column      alignment COLUMN for printing syscall results (default 40)
  -i             print instruction pointer at time of syscall
  -o file        send trace output to FILE instead of stderr
  -q             suppress messages about attaching, detaching, etc.
  -r             print relative timestamp
  -s strsize     limit length of print strings to STRSIZE chars (default 32)
  -t             print absolute timestamp
  -tt            print absolute timestamp with usecs
  -T             print time spent in each syscall
  -x             print non-ascii strings in hex
  -xx            print all strings in hex
  -y             print paths associated with file descriptor arguments
  -yy            print protocol specific information associated with socket file descriptors

Statistics:
  -c             count time, calls, and errors for each syscall and report summary
  -C             like -c but also print regular output
  -O overhead    set overhead for tracing syscalls to OVERHEAD usecs
  -S sortby      sort syscall counts by: time, calls, name, nothing (default time)
  -w             summarise syscall latency (default is system time)

Filtering:
  -e expr        a qualifying expression: option=[!]all or option=[!]val1[,val2]...
     options:    trace, abbrev, verbose, raw, signal, read, write, fault
  -P path        trace accesses to path

Tracing:
  -b execve      detach on execve syscall
  -D             run tracer process as a detached grandchild, not as parent
  -f             follow forks
  -ff            follow forks with output into separate files
  -I interruptible
     1:          no signals are blocked
     2:          fatal signals are blocked while decoding syscall (default)
     3:          fatal signals are always blocked (default if '-o FILE PROG')
     4:          fatal signals and SIGTSTP (^Z) are always blocked
                 (useful to make 'strace -o FILE PROG' not stop on ^Z)

Startup:
  -E var         remove var from the environment for command
  -E var=val     put var=val in the environment for command
  -p pid         trace process with process id PID, may be repeated
  -u username    run command as username handling setuid and/or setgid

Miscellaneous:
  -d             enable debug output to stderr
  -v             verbose mode: print unabbreviated argv, stat, termios, etc. args
  -h             print help message
  -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

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

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

stmdb	sp!, {r4, r5}			@ push fifth and sixth args
tst	ip, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
bne	__sys_trace

cmp	scno, #NR_syscalls		@ check upper syscall limit
adr	lr, ret_fast_syscall		@ return address
ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine

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

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

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈 洪 伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值