대부분 Ubuntu에 기본으로 설치가 되어있는 것으로 보이며, 동적라이브러리를 추적할때 사용한다고 한다.
주목적은 shared library 추적이며, dlopen시 마다 이를 hooking해서 추적한다.
ltrace의 기능소개
https://en.wikipedia.org/wiki/Ltrace
debugfs
https://m.blog.naver.com/PostView.nhn?blogId=dudwo567890&logNo=130156521971&proxyReferer=https%3A%2F%2Fwww.google.com%2F
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/237debugfs
https://m.blog.naver.com/PostView.nhn?blogId=dudwo567890&logNo=130156521971&proxyReferer=https%3A%2F%2Fwww.google.com%2F