应用调试之strace

 strace是个功能强大的Linux调试分析诊断工具,可用于跟踪程序执行时进程系统调用(system call)和所接收的信号,尤其是针对源码不可读或源码无法再编译的程序。

在Linux系统中,用户程序运行在一个沙箱(sandbox)里,用户进程不能直接访问计算机硬件设备。当进程需要访问硬件设备(如读取磁盘文件或接收网络数据等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可跟踪进程产生的系统调用,包括参数、返回值和执行所消耗的时间。若strace没有任何输出,并不代表此时进程发生阻塞;也可能程序进程正在自己的沙箱里执行某些不需要与系统其它部分发生通信的事情。strace从内核接收信息,且无需以任何特殊方式来构建内核。

当然它还可以做更多的事情:

strace可以过筛选出特定的系统调用。

strace可以记录系统调用的次数,时间,成功和失败的次数。

strace可以跟踪发给进程的信号。

strace可以通过pid附加到任何正在运行的进程上。

strace类似其他Unix系统上的truss,或者Sun's Dtrace

对于成熟的服务器或者桌面系统,strace是已经集成好的一个应用,对于从零开发的嵌入式系统,需要构建者自己来编译这个工具。恰好我们就是自己构建的内核,所以应用程序都需要自己构建。

strace 源码下载链接 https://github.com/strace/strace

我这里直接从Ubuntu上使用 git 下载,Windows下下载再传输到Ubuntu上不能使用(有一些文件被破坏了)。

./bootstrap
./configure --host=arm-linux-gnueabihf CC=arm-linux-gnueabihf-gcc
make
cp strace ./../../rootfs/bin/

 

下面我们以一个简单的例子为例来使用一下这个工具

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
 
int main(void)
{
    int fd = 0;
    char buf[] = "You're a good man!\n";
    int len = 0;
    
    /*
     * 创建一个文件
     */
    fd = open("file.txt", O_RDWR);
    if(fd < 0) {
        perror("open fail\n");
        exit(1);
    }   
    
    /*
     * 写入一段字符串
     */
    len = strlen(buf);
    if(write(fd, buf, len) < len) {
        perror("write fail\n");
        exit(1);
    }   
 
    /*
     * 关闭文件
     */
    close(fd);
 
    return 0;
}
 

关于这个工具的使用,我们可以直接使用帮助文档。

Usage: strace [-ACdffhiqqrtttTvVwxxyyzZ] [-I N] [-b execve] [-e EXPR]...
              [-a COLUMN] [-o FILE] [-s STRSIZE] [-X FORMAT] [-O OVERHEAD]
              [-S SORTBY] [-P PATH]... [-p PID]... [-U COLUMNS] [--seccomp-bpf]
              { -p PID | [-DDD] [-E VAR=VAL]... [-u USERNAME] PROG [ARGS] }
   or: strace -c[dfwzZ] [-I N] [-b execve] [-e EXPR]... [-O OVERHEAD]
              [-S SORTBY] [-P PATH]... [-p PID]... [-U COLUMNS] [--seccomp-bpf]
              { -p PID | [-DDD] [-E VAR=VAL]... [-u USERNAME] PROG [ARGS] }

General:
  -e EXPR        a qualifying expression: OPTION=[!]all or OPTION=[!]VAL1[,VAL2]...
     options:    trace, abbrev, verbose, raw, signal, read, write, fault,
                 inject, status, quiet, kvm, decode-fds

Startup:
  -E VAR=VAL, --env=VAR=VAL
                 put VAR=VAL in the environment for command
  -E VAR, --env=VAR
                 remove VAR from the environment for command
  -p PID, --attach=PID
                 trace process with process id PID, may be repeated
  -u USERNAME, --user=USERNAME
                 run command as USERNAME handling setuid and/or setgid

Tracing:
  -b execve, --detach-on=execve
                 detach on execve syscall
  -D, --daemonize[=grandchild]
                 run tracer process as a grandchild, not as a parent
  -DD, --daemonize=pgroup
                 run tracer process in a separate process group
  -DDD, --daemonize=session
                 run tracer process in a separate session
  -f, --follow-forks
                 follow forks
  -ff, --follow-forks --output-separately
                 follow forks with output into separate files
  -I INTERRUPTIBLE, --interruptible=INTERRUPTIBLE
     1, anywhere:   no signals are blocked
     2, waiting:    fatal signals are blocked while decoding syscall (default)
     3, never:      fatal signals are always blocked (default if '-o FILE PROG')
     4, never_tstp: fatal signals and SIGTSTP (^Z) are always blocked
                    (useful to make 'strace -o FILE PROG' not stop on ^Z)

Filtering:
  -e trace=[!]{[?]SYSCALL[@64|@32|@x32]|[?]/REGEX|GROUP|all|none},
  --trace=[!]{[?]SYSCALL[@64|@32|@x32]|[?]/REGEX|GROUP|all|none}
                 trace only specified syscalls.
     groups:     %clock, %creds, %desc, %file, %fstat, %fstatfs %ipc, %lstat,
                 %memory, %net, %process, %pure, %signal, %stat, %%stat,
                 %statfs, %%statfs
  -e signal=SET, --signal=SET
                 trace only the specified set of signals
                 print only the signals from SET
  -e status=SET, --status=SET
                 print only system calls with the return statuses in SET
     statuses:   successful, failed, unfinished, unavailable, detached
  -P PATH, --trace-path=PATH
                 trace accesses to PATH
  -z, --successful-only
                 print only syscalls that returned without an error code
  -Z, --failed-only
                 print only syscalls that returned with an error code

Output format:
  -a COLUMN, --columns=COLUMN
                 alignment COLUMN for printing syscall results (default 40)
  -e abbrev=SET, --abbrev=SET
                 abbreviate output for the syscalls in SET
  -e verbose=SET, --verbose=SET
                 dereference structures for the syscall in SET
  -e raw=SET, --raw=SET
                 print undecoded arguments for the syscalls in SET
  -e read=SET, --read=SET
                 dump the data read from the file descriptors in SET
  -e write=SET, --write=SET
                 dump the data written to the file descriptors in SET
  -e quiet=SET, --quiet=SET
                 suppress various informational messages
     messages:   attach, exit, path-resolution, personality, thread-execve
  -e kvm=vcpu, --kvm=vcpu
                 print exit reason of kvm vcpu
  -e decode-fds=SET, --decode-fds=SET
                 what kinds of file descriptor information details to decode
     details:    dev (device major/minor for block/char device files)
                 path (file path),
                 pidfd (associated PID for pidfds),
                 socket (protocol-specific information for socket descriptors)
  -i, --instruction-pointer
                 print instruction pointer at time of syscall
  -n, --syscall-number
                 print syscall number
  -o FILE, --output=FILE
                 send trace output to FILE instead of stderr
  -A, --output-append-mode
                 open the file provided in the -o option in append mode
  --output-separately
                 output into separate files (by appending pid to file names)
  -q, --quiet=attach,personality
                 suppress messages about attaching, detaching, etc.
  -qq, --quiet=attach,personality,exit
                 suppress messages about process exit status as well.
  -qqq, --quiet=all
                 suppress all suppressible messages.
  -r, --relative-timestamps[=PRECISION]
                 print relative timestamp
     precision:  one of s, ms, us, ns; default is microseconds
  -s STRSIZE, --string-limit=STRSIZE
                 limit length of print strings to STRSIZE chars (default 32)
  --absolute-timestamps=[[format:]FORMAT[,[precision:]PRECISION]]
                 set the format of absolute timestamps
     format:     none, time, or unix; default is time
     precision:  one of s, ms, us, ns; default is seconds
  -t, --absolute-timestamps[=time]
                 print absolute timestamp
  -tt, --absolute-timestamps=[time,]us
                 print absolute timestamp with usecs
  -ttt, --absolute-timestamps=unix,us
                 print absolute UNIX time with usecs
  -T, --syscall-times[=PRECISION]
                 print time spent in each syscall
     precision:  one of s, ms, us, ns; default is microseconds
  -v, --no-abbrev
                 verbose mode: print entities unabbreviated
  -x, --strings-in-hex=non-ascii
                 print non-ascii strings in hex
  -xx, --strings-in-hex[=all]
                 print all strings in hex
  -X FORMAT, --const-print-style=FORMAT
                 set the FORMAT for printing of named constants and flags
     formats:    raw, abbrev, verbose
  -y, --decode-fds[=path]
                 print paths associated with file descriptor arguments
  -yy, --decode-fds=all
                 print all available information associated with file
                 descriptors in addition to paths

Statistics:
  -c, --summary-only
                 count time, calls, and errors for each syscall and report
                 summary
  -C, --summary  like -c, but also print the regular output
  -O OVERHEAD[UNIT], --summary-syscall-overhead=OVERHEAD[UNIT]
                 set overhead for tracing syscalls to OVERHEAD UNITs
     units:      one of s, ms, us, ns; default is microseconds
  -S SORTBY, --summary-sort-by=SORTBY
                 sort syscall counts by: time, min-time, max-time, avg-time,
                 calls, errors, name, nothing (default time)
  -U COLUMNS, --summary-columns=COLUMNS
                 show specific columns in the summary report: comma-separated
                 list of time-percent, total-time, min-time, max-time, 
                 avg-time, calls, errors, name
                 (default time-percent,total-time,avg-time,calls,errors,name)
  -w, --summary-wall-clock
                 summarise syscall latency (default is system time)

Tampering:
  -e inject=SET[:error=ERRNO|:retval=VALUE][:signal=SIG][:syscall=SYSCALL]
            [:delay_enter=DELAY][:delay_exit=DELAY][:when=WHEN],
  --inject=SET[:error=ERRNO|:retval=VALUE][:signal=SIG][:syscall=SYSCALL]
           [:delay_enter=DELAY][:delay_exit=DELAY][:when=WHEN]
                 perform syscall tampering for the syscalls in SET
     delay:      microseconds or NUMBER{s|ms|us|ns}
     when:       FIRST[..LAST][+[STEP]]
  -e fault=SET[:error=ERRNO][:when=WHEN], --fault=SET[:error=ERRNO][:when=WHEN]
                 synonym for -e inject with default ERRNO set to ENOSYS.

Miscellaneous:
  -d, --debug    enable debug output to stderr
  -h, --help     print help message
  --seccomp-bpf  enable seccomp-bpf filtering
  -V, --version  print version
[root@IMX6ULL]#

可以看到,这个工具的用法非常多,这里我们以最简单的一种用法为例来说一下它的使用。

-o + file,表示把这个程序的结果输出到file文件中。

可以看一下我们上面这个应用程序中,系统调用的一些输出结果。

[root@IMX6ULLwork]#cat log1.txt 
execve("./test", ["./test"], 0x7ea3fd68 /* 17 vars */) = 0
brk(NULL)                               = 0x18fe000
uname({sysname="Linux", nodename="IMX6ULL", ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76f04000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("libc.so.6", O_RDONLY|O_CLOEXEC)   = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/neon/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/neon", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/vfp", 0x7ebe5418)  = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l", 0x7ebe5418)      = -1 ENOENT (No such file or directory)
open("/lib/tls/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/neon/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/tls/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/neon", 0x7ebe5418)     = -1 ENOENT (No such file or directory)
open("/lib/tls/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/vfp", 0x7ebe5418)      = -1 ENOENT (No such file or directory)
open("/lib/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls", 0x7ebe5418)          = -1 ENOENT (No such file or directory)
open("/lib/v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/neon/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/neon", 0x7ebe5418)     = -1 ENOENT (No such file or directory)
open("/lib/v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/vfp", 0x7ebe5418)      = -1 ENOENT (No such file or directory)
open("/lib/v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l", 0x7ebe5418)          = -1 ENOENT (No such file or directory)
open("/lib/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/neon/vfp", 0x7ebe5418)     = -1 ENOENT (No such file or directory)
open("/lib/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/neon", 0x7ebe5418)         = -1 ENOENT (No such file or directory)
open("/lib/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/vfp", 0x7ebe5418)          = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0]d\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=8802547, ...}) = 0
mmap2(NULL, 976272, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x76def000
mprotect(0x76ec8000, 65536, PROT_NONE)  = 0
mmap2(0x76ed8000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd9000) = 0x76ed8000
mmap2(0x76edb000, 9616, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x76edb000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76f03000
set_tls(0x76f034c0)                     = 0
mprotect(0x76ed8000, 8192, PROT_READ)   = 0
mprotect(0x76f05000, 4096, PROT_READ)   = 0
open("file.txt", O_RDWR)                = 3
write(3, "You're a good man!\n", 19)    = 19
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
[root@IMX6ULLwork]#

可以看到,我们这个app中系统调用的顺序,以及输出输出的参数。

比如open的返回值为3,表示文件描述符标号是3.

write返回值19,表示成功写入19个字符。

新创建的文件权限为063440,这个权限可以通过下表查看。

 

也可c参数,来查看各个系统调用在整个应用中的占用时间百分比,已经具体时间。

[root@IMX6ULLwork]#strace -c -o log1.txt ./test
[root@IMX6ULLwork]#cat log1.txt 
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         1           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0        33        31 open
  0.00    0.000000           0         2           close
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1         1 access
  0.00    0.000000           0         1           brk
  0.00    0.000000           0         1           uname
  0.00    0.000000           0         3           mprotect
  0.00    0.000000           0         5           mmap2
  0.00    0.000000           0        15        15 stat64
  0.00    0.000000           0         1           fstat64
  0.00    0.000000           0         1           set_tls
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000           0        66        47 total
[root@IMX6ULLwork]#

一般通过strace + -c参数,可以判断程序的具体性能,以便确定是否需要优化,以及优化的目标。

也可以查看某个shell命令的调用方式,比如

strace cat log1.txt 
[root@IMX6ULLwork]#strace cat log1.txt 
execve("/bin/cat", ["cat", "log1.txt"], 0x7efccd74 /* 17 vars */) = 0
brk(NULL)                               = 0x1b43000
uname({sysname="Linux", nodename="IMX6ULL", ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76fad000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("libm.so.6", O_RDONLY|O_CLOEXEC)   = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/neon/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/neon", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/vfp", 0x7ee97418)  = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l", 0x7ee97418)      = -1 ENOENT (No such file or directory)
open("/lib/tls/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/neon/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/tls/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/neon", 0x7ee97418)     = -1 ENOENT (No such file or directory)
open("/lib/tls/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/vfp", 0x7ee97418)      = -1 ENOENT (No such file or directory)
open("/lib/tls/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls", 0x7ee97418)          = -1 ENOENT (No such file or directory)
open("/lib/v7l/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/neon/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/v7l/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/neon", 0x7ee97418)     = -1 ENOENT (No such file or directory)
open("/lib/v7l/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/vfp", 0x7ee97418)      = -1 ENOENT (No such file or directory)
open("/lib/v7l/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l", 0x7ee97418)          = -1 ENOENT (No such file or directory)
open("/lib/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/neon/vfp", 0x7ee97418)     = -1 ENOENT (No such file or directory)
open("/lib/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/neon", 0x7ee97418)         = -1 ENOENT (No such file or directory)
open("/lib/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/vfp", 0x7ee97418)          = -1 ENOENT (No such file or directory)
open("/lib/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0h<\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1510945, ...}) = 0
mmap2(NULL, 471184, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x76f13000
mprotect(0x76f76000, 61440, PROT_NONE)  = 0
mmap2(0x76f85000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x62000) = 0x76f85000
close(3)                                = 0
open("tls/v7l/neon/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0@%\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=307572, ...}) = 0
mmap2(NULL, 133044, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x76ef2000
mprotect(0x76eff000, 65536, PROT_NONE)  = 0
mmap2(0x76f0f000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd000) = 0x76f0f000
mmap2(0x76f11000, 6068, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x76f11000
close(3)                                = 0
open("tls/v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("libc.so.6", O_RDONLY|O_CLOEXEC)   = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0]d\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=8802547, ...}) = 0
mmap2(NULL, 976272, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x76e03000
mprotect(0x76edc000, 65536, PROT_NONE)  = 0
mmap2(0x76eec000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd9000) = 0x76eec000
mmap2(0x76eef000, 9616, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x76eef000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76fac000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76fab000
set_tls(0x76fab4c0)                     = 0
mprotect(0x76eec000, 8192, PROT_READ)   = 0
mprotect(0x76f0f000, 4096, PROT_READ)   = 0
mprotect(0x76f85000, 4096, PROT_READ)   = 0
mprotect(0x76fae000, 4096, PROT_READ)   = 0
getuid32()                              = 0
open("log1.txt", O_RDONLY|O_LARGEFILE)  = 3
sendfile64(1, 3, NULL, 16777216% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         1           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0        33        31 open
  0.00    0.000000           0         2           close
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1         1 access
  0.00    0.000000           0         1           brk
  0.00    0.000000           0         1           uname
  0.00    0.000000           0         3           mprotect
  0.00    0.000000           0         5           mmap2
  0.00    0.000000           0        15        15 stat64
  0.00    0.000000           0         1           fstat64
  0.00    0.000000           0         1           set_tls
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000           0        66        47 total
)        = 999
sendfile64(1, 3, NULL, 16777216)        = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
[root@IMX6ULLwork]#

当然 本节只是简单的说一下这个工具的使用,后面章节项目应用程序部分,会直接使用这个工具来做调试。

参考文章

Linux Hook 笔记

Linux Ptrace 详解

使用ptrace跟踪进程

[Pthread] Linux上程序调试的基石(一)--ptrace

[Pthread] Linux程序调试的基石(二)--Inside GDB

上一篇:【Linux】虚拟磁盘挂载错误,不能进入系统(fsck.ext3:no such file directory)


下一篇:Linux常见错误码声明