Skip to content

LV020-strace

在linux中有一个调试代码的神器,就是strace命令,这一节就来看一下如何编译它的源码,将它移植到我们的开发板上来吧。

一、strace简介

1. 简介

trace是一个可用于诊断、调试和教学的Linux用户空间跟踪器。我们用它来监控用户空间进程和内核的交互,比如系统调用、信号传递、进程状态变更等。可用来追踪调试程序,能够与其他命令搭配使用。

Linux系统管理员可以在不需要源代码的情况下即可跟踪系统的调用。strace可以显示有关进程的系统调用的信息,这可以帮助确定一个程序使用的哪个函数,当然在系统出现问题时可以使用 strace定位系统调用过程中失败的原因,这是定位系统问题的很好的方法。

2. 源码获取

源码那肯定要到官网去找啦:strace

image-20260106194736242

我们打开对应的github仓库,找自己想要移植的版本就可以了。另外也可以来这里下载源码Index of /files/ (strace.io),这里可能会更快一些:

image-20260106194804653

这里我直接下了当前的最新版本,也就是6.8版本:

image-20260106194841541

然后就是在ubuntu下解压(我这里用的是ubuntu16.04):

shell
xz -d strace-6.8.tar.xz
tar -xvf strace-6.8.tar

# 其实吧,用下面这一个其实就够了
tar -xvf strace-6.8.tar.xz

解压后我们会得到以下文件:

image-20240410075634200

二、移植strace

1. 编译strace源码

我们要移植到linux开发板上,使用的是arm架构,所以要用交叉编译工具来进行编译,我使用的交叉编译工具版本信息如下:

shell
hk@vm:~/5ALPHA/strace-6.8$ arm-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/home/hk/2software/gcc-linaro-4.9.4/bin/../libexec/gcc/arm-linux-gnueabihf/4.9.4/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: /home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/snapshots/gcc-linaro-4.9-2017.01/configure SHELL=/bin/bash --with-mpc=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu --with-mpfr=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu --with-gmp=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu --with-gnu-as --with-gnu-ld --disable-libmudflap --enable-lto --enable-objc-gc --enable-shared --without-included-gettext --enable-nls --disable-sjlj-exceptions --enable-gnu-unique-object --enable-linker-build-id --disable-libstdcxx-pch --enable-c99 --enable-clocale=gnu --enable-libstdcxx-debug --enable-long-long --with-cloog=no --with-ppl=no --with-isl=no --disable-multilib --with-float=hard --with-mode=thumb --with-tune=cortex-a9 --with-arch=armv7-a --with-fpu=vfpv3-d16 --enable-threads=posix --enable-multiarch --enable-libstdcxx-time=yes --with-build-sysroot=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/sysroots/arm-linux-gnueabihf --with-sysroot=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu/arm-linux-gnueabihf/libc --enable-checking=release --disable-bootstrap --enable-languages=c,c++,fortran,lto --build=x86_64-unknown-linux-gnu --host=x86_64-unknown-linux-gnu --target=arm-linux-gnueabihf --prefix=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu
Thread model: posix
gcc version 4.9.4 (Linaro GCC 4.9-2017.01)

编译源码的命令如下:

shell
cd ~/5ALPHA/strace-6.8
mkdir output
#   --host:主机使用的交叉前缀名
# --prefix:编译输出目录,绝对路径,这个不指定的话,好像有问题,它不在自己源码目录下,而是直接输出到ubuntu的根目录中了
#       CC:GCC交叉编译器
#       LD:GCC交叉链接工具 
./configure --host=arm-linux-gnueabihf \
				CC=arm-linux-gnueabihf-gcc \
				LD=arm-linux-gnueabihf-ld \
				--prefix=/home/hk/5ALPHA/strace-6.8/output #/usr/strace_arm
	
make
make install

上面没啥意外的话应该是没啥意外的,就是没明白哪个--prefix参数,不指定吧,没有root权限又会报错,指定吧,又没有输出在那个目录,难道是做中间缓存目录用的?最后生成的可执行文件在starce源码目录下的bin目录中:

image-20240424073454263

我们可以使用file命令来看一下它是不是我们要的格式:

image-20240424073540065

2. 怎么放到开发板中去?

啊,这里有点头大,我之前自己学习的时候是从nfs加载根文件系统,所以直接在ubuntu中拷贝到对应的目录中去就可以了,做这个命令移植学习的时候环境没得了,就只能全部烧录一遍啦,我们首先把这个编译出来的strace命令放到根文件系统中去。我这里直接先使用正点原子官方出厂的固件来搞,防止出现缺失库的情况,毕竟现在重点是学习命令的使用,后面出现了什么问题再在笔记中补充。

2.1 重新压缩根文件系统

在烧写工具的固件中有根文件系统,在这里:

image-20240424074331649

这个压缩包是.tar.bz2格式,我不知道为什么解压缩会有问题,可能是使用的是winrar的原因?我后来索性就把file目录全部拷贝到ubuntu中,使用tar命令来重新搞啦。解压命令如下:

shell
tar -xvf rootfs.tar.bz2

解压完后,把strace命令放在根文件系统的bin目录下:

image-20240424074806204

放好后,我们重新压缩:

shell
cd .. #回到上一级再压缩
sudo tar -cjf rootfs.tar.bz2 filesystem/* # 不加sudo的话,可能有些步骤要报错
image-20240424075503496

加上sudo之后就正常了。但是这里可能会有问题,就是这样压缩出来,解压后,我们会得到一个filesystem目录,目录里面才是根文件系统,这对于我们后面烧写的时候是一个很大的bug,可能会出现找不到根文件系统相关目录的bug,我后面通过ubuntu使用脚本烧写系统到SD卡的时候就是这样的:

image-20240424230416176

应该直接在filesystem目录下进行压缩:

shell
sudo tar -cjf rootfs.tar.bz2 ./*

2.2 烧写到SD卡?

这一步我们就可以直接在ubuntu中进行了,可以参考《10-开发平台/05-IMX6ULL/LV015-固化系统.md》笔记中的《2. 烧写系统到TF卡》一小节,这里就不赘述了。这个过程会非常慢,耐心等一下吧。

2.3 启动开发板测试

我们按照对应章节的笔记烧写完毕后,从sd卡启动系统,然后我们看一下根文件系统中的文件:

shell
ls /bin/str*
image-20240424231950807

3. 基本测试

我们使用以下命令来查看strace的帮助说明:

shell
strace -v

然后就会看到如下打印信息:

shell
root@ATK-IMX6U:~# strace -v
strace: must have PROG [ARGS] or -p PID
Try 'strace -h' for more information.
root@ATK-IMX6U:~# 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 ip:port pairs 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
  -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

这其实也是说明了我们移植的strace命令是可以正常使用的。