项目场景:
有时候需要使用ltrace追踪用户空间调用,但是我发现Ubuntu-18.04是可以的,Ubuntu-20.04和22.04不行,研究了下找到了原因,只需要更改简单的配置就行了。
问题描述
ltrace在大于Ubuntu-18.04版本上无法追踪,不能正常显示。
测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int print (char *str) {
printf("%s\n", str);
}
main () {
char *tmp;
tmp=malloc(100);
strcat(tmp, "testing");
print(tmp);
free(tmp);
exit(0);
}
编译:
gcc test.c -o test
查看:
scanelf -a ./test
TYPE PAX PERM ENDIAN STK/REL/PTL TEXTREL RPATH BIND FILE
ET_DYN PeMRxS 0755 LE RW- R-- RW- - - NOW ./test
执行:
ltrace ./test
结果:
testing
+++ exited (status 0) +++
原因分析:
链接的默认选项有关系,ltrace只支持-z lazy的链接选项,不支持-z now的链接选项。
解决方案:
实测在>Ubuntu-18.04版本发行版上指定-z lazy即可。不需要更改源代码。
编译:
gcc test.c -z lazy -o test
查看:
scanelf -a ./test
TYPE PAX PERM ENDIAN STK/REL/PTL TEXTREL RPATH BIND FILE
ET_DYN PeMRxS 0755 LE RW- R-- RW- - - LAZY ./test
测试:
ltrace ./test
结果:
malloc(100) = 0x562957bf52a0
strlen("") = 0
puts("testing"testing
) = 8
free(0x562957bf52a0) = <void>
exit(0 <no return ...>
+++ exited (status 0) +++
总结:
轻松化解,没有多余的操作。
如果你想同时追踪下系统调用,只需要加一个-S
选项。同时显示用户空间调用和内核空间调用。
测试:
ltrace -S ./test
结果:
SYS_brk(0) = 0x55d4399e3000
SYS_arch_prctl(0x3001, 0x7ffd84c20610, 0x7efe7d9a1420, 1) = -22
SYS_mmap(0, 8192, 3, 34) = 0x7efe7d980000
SYS_access("/etc/ld.so.preload", 04) = -2
SYS_openat(0xffffff9c, 0x7efe7d9b021b, 0x80000, 0) = 3
SYS_newfstatat(3, 0x7efe7d9b0ee9, 0x7ffd84c1f760, 4096) = 0
SYS_mmap(0, 0x611b, 1, 2) = 0x7efe7d979000
SYS_close(3) = 0
SYS_openat(0xffffff9c, 0x7efe7d980140, 0x80000, 0) = 3
SYS_read(3, "\177ELF\002\001\001\003", 832) = 832
SYS_pread(3, 0x7ffd84c1f5a0, 784, 64) = 784
SYS_pread(3, 0x7ffd84c1f560, 48, 848) = 48
SYS_pread(3, 0x7ffd84c1f510, 68, 896) = 68
SYS_newfstatat(3, 0x7efe7d9b0ee9, 0x7ffd84c1f830, 4096) = 0
SYS_pread(3, 0x7ffd84c1f470, 784, 64) = 784
SYS_mmap(0, 0x227e50, 1, 2050) = 0x7efe7d751000
SYS_mmap(0x7efe7d779000, 0x195000, 5, 2066) = 0x7efe7d779000
SYS_mmap(0x7efe7d90e000, 0x58000, 1, 2066) = 0x7efe7d90e000
SYS_mmap(0x7efe7d966000, 0x6000, 3, 2066) = 0x7efe7d966000
SYS_mmap(0x7efe7d96c000, 0xce50, 3, 50) = 0x7efe7d96c000
SYS_close(3) = 0
SYS_mmap(0, 0x3000, 3, 34) = 0x7efe7d74e000
SYS_arch_prctl(4098, 0x7efe7d74e740, 0xffff8101828b0eb0, 34) = 0
SYS_set_tid_address(0x7efe7d74ea10, 0x7efe7d74e740, 0x7efe7d9bd0d8, 34) = 1434
SYS_set_robust_list(0x7efe7d74ea20, 24, 0x7efe7d9bd0d8, 34) = 0
SYS_334(0x7efe7d74f0e0, 32, 0, 0x53053053) = 0
SYS_mprotect(0x7efe7d966000, 16384, 1) = 0
SYS_mprotect(0x55d438c79000, 4096, 1) = 0
SYS_mprotect(0x7efe7d9ba000, 8192, 1) = 0
SYS_prlimit64(0, 3, 0, 0x7ffd84c20370) = 0
SYS_munmap(0x7efe7d979000, 24859) = 0
malloc(100 <unfinished ...>
SYS_318(0x7efe7d9714d8, 8, 1, 0x7efe7d757e58) = 8
SYS_brk(0) = 0x55d4399e3000
SYS_brk(0x55d439a04000) = 0x55d439a04000
<... malloc resumed> ) = 0x55d4399e32a0
strlen("") = 0
puts("testing" <unfinished ...>
SYS_newfstatat(1, 0x7efe7d92946f, 0x7ffd84c20500, 4096) = 0
SYS_write(1, "testing\n", 8testing
) = 8
<... puts resumed> ) = 8
free(0x55d4399e32a0) = <void>
exit(0 <unfinished ...>
SYS_exit_group(0 <no return ...>
+++ exited (status 0) +++
其它的场景,大家自行脑补。