12/02/2018

ltrace

1. ltrace 의 기능 

대부분 Ubuntu에 기본으로 설치가 되어있는 것으로 보이며, 동적라이브러리를 추적할때 사용한다고 한다. 
주목적은 shared library 추적이며, dlopen시 마다 이를 hooking해서 추적한다. 

ltrace의 기능소개 
  https://en.wikipedia.org/wiki/Ltrace

  • 기본설치 
$ sudo apt install ltrace

  • 기본사용법
$ ltrace --help
Usage: ltrace [option ...] [command [arg ...]]
Trace library calls of a given program.

  -a, --align=COLUMN  align return values in a secific column.
  -A MAXELTS          maximum number of array elements to print.
  -b, --no-signals    don't print signals.
  -c                  count time and calls, and report a summary on exit.
  -C, --demangle      decode low-level symbol names into user-level names.
  -D, --debug=MASK    enable debugging (see -Dh or --debug=help).
  -Dh, --debug=help   show help on debugging.
  -e FILTER           modify which library calls to trace.
  -f                  trace children (fork() and clone()).
  -F, --config=FILE   load alternate configuration file (may be repeated).
  -h, --help          display this help and exit.
  -i                  print instruction pointer at time of library call.
  -l, --library=LIBRARY_PATTERN only trace symbols implemented by this library.
  -L                  do NOT display library calls.
  -n, --indent=NR     indent output by NR spaces for each call level nesting.
  -o, --output=FILENAME write the trace output to file with given name.
  -p PID              attach to the process with the process ID pid.
  -r                  print relative timestamps.
  -s STRSIZE          specify the maximum string size to print.
  -S                  trace system calls as well as library calls.
  -t, -tt, -ttt       print absolute timestamps.
  -T                  show the time spent inside each call.
  -u USERNAME         run command with the userid, groupid of username.
  -V, --version       output version information and exit.
  -x FILTER           modify which static functions to trace.

Report bugs to ltrace-devel@lists.alioth.debian.org

  • 현재 동작 중인 Process 기본분석 
/proc의 기본정보를 이용하여 ELF 정보를 비롯하여 Map 정보등 세세한 정보를 얻을 수 있다

$ ps -aux   //현재 동작 중인 Process 확인 
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
....
systemd+     713  0.0  0.0  90456  6336 ?        Ssl   5월21   0:01 /lib/systemd/systemd-timesyncd
...
$ sudo cat /proc/713/maps  // 보고자하는 PID의 MAP 확인 (사용되어지는 공유 Library 확인)
...
7fe6e9dfa000-7fe6e9dfc000 rw-p 00000000 00:00 0
7fe6e9dfc000-7fe6e9e24000 r--p 00000000 08:15 2367775                    /usr/lib/x86_64-linux-gnu/libseccomp.so.2.4.3
7fe6e9e24000-7fe6e9e2f000 r-xp 00028000 08:15 2367775                    /usr/lib/x86_64-linux-gnu/libseccomp.so.2.4.3
7fe6e9e2f000-7fe6e9e33000 r--p 00033000 08:15 2367775                    /usr/lib/x86_64-linux-gnu/libseccomp.so.2.4.3
7fe6e9e33000-7fe6e9e4e000 r--p 00036000 08:15 2367775                    /usr/lib/x86_64-linux-gnu/libseccomp.so.2.4.3
7fe6e9e4e000-7fe6e9e4f000 rw-p 00051000 08:15 2367775                    /usr/lib/x86_64-linux-gnu/libseccomp.so.2.4.3
7fe6e9e4f000-7fe6e9e52000 r--p 00000000 08:15 2361499                    /usr/lib/x86_64-linux-gnu/librt-2.31.so
7fe6e9e52000-7fe6e9e56000 r-xp 00003000 08:15 2361499                    /usr/lib/x86_64-linux-gnu/librt-2.31.so
......

$ sudo cat /proc/713/status  // Process 상태확인 
Name:   systemd-timesyn
Umask:  0022
State:  S (sleeping)
Tgid:   713
Ngid:   0
Pid:    713
PPid:   1
TracerPid:      0
Uid:    102     102     102     102
Gid:    104     104     104     104
FDSize: 64
Groups: 104
NStgid: 713
NSpid:  713
NSpgid: 713

$ sudo readelf -h /proc/713/exe    // 실행중인 파일 ELF의 포맷확인 및 기본정보확인
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
.....

$ sudo readelf -s /proc/713/exe    // 실행중인 파일의 ELF에서 symbol table 확인   

Symbol table '.dynsym' contains 108 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND getegid@GLIBC_2.2.5 (2)
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __errno_location@GLIBC_2.2.5 (2)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND config_parse_sec@SD_SHARED (3)
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sendto@GLIBC_2.2.5 (2)
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND bind@GLIBC_2.2.5 (2)
     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sd_event_loop@SD_SHARED (3)
     7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND socket@GLIBC_2.2.5 (2)
     8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND recvmsg@GLIBC_2.2.5 (2)
     9: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND log_assert_failed_unreach@SD_SHARED (3)
..........

  • ltrace 기본사용법 
우선 ps로 CPU를 가장 많이 사용하는 PID를 사용하여 각 상태를 확인을 하자. 
아래와 같이 너무 많이 호출되어지기 때문에 특정함수만 검색하고 싶다면 상위 -e 옵션추가

$ ps -aux    //CPU를 가장 많이 이용하는 PID 찾기 
......

$ sudo ltrace -p 2025 -i     //ltrace로 pid 추적 timestamp 이용 
[0x138e9a5] __errno_location()                                                                                                   = 0x7afe3648
[0x138e9a5] __errno_location( unfinished ...
[0x138e31c] clock_gettime(1, 0x7afdfd30, 0x7afdfd30, 0x7b10b5ce)                                                                 = 0
[0x138e9a5] ... __errno_location resumed )                                                                                     = 0x7fbd7afe46c8
......

$ sudo ltrace -p 7026 -t     //ltrace로 pid 추적 timestamp 이용 
13:42:24 __errno_location( unfinished ...
13:42:24 __errno_location( unfinished ...
13:42:24 ... __errno_location resumed )                                                                                        = 0x482ea648
13:42:24 ... __errno_location resumed )                                                                                        = 0x7fd2482eb6c8
13:42:24 clock_gettime(1, 0x482e6d30, 0x482e6d30, 0x484125ce unfinished ...
13:42:24 clock_gettime(1, 0x7ffec722d690, 0x7ffec722d690, 0x7fd2484125ce unfinished ...
13:42:24 ... clock_gettime resumed )                                                                                           = 0
13:42:24 ... clock_gettime resumed )
..............


참고자료 
  https://jiming.tistory.com/237
 
debugfs
  https://m.blog.naver.com/PostView.nhn?blogId=dudwo567890&logNo=130156521971&proxyReferer=https%3A%2F%2Fwww.google.com%2F