Linux 运行ltrace时没有输出

Linux 运行ltrace时没有输出,linux,ubuntu,shared-libraries,ltrace,Linux,Ubuntu,Shared Libraries,Ltrace,正如标题所说,ltrace在我的系统上不能正常工作。 它在大多数情况下不显示输出,如 $ltrace ls [usual ls output] +++ exited (status 0) +++ $gcc hello.c $ltrace ./a.out Hello world! +++ exited (status 0) +++ 我使用的是最新的ltrace版本(来自package0.7.3-5.1ubuntu4),我甚至尝试从源代码重新编译,没有任何区别。 我正在使用Ubuntu16.10

正如标题所说,ltrace在我的系统上不能正常工作。 它在大多数情况下不显示输出,如

$ltrace ls
[usual ls output]
+++ exited (status 0) +++

$gcc hello.c
$ltrace ./a.out
Hello world!
+++ exited (status 0) +++
我使用的是最新的ltrace版本(来自package
0.7.3-5.1ubuntu4
),我甚至尝试从源代码重新编译,没有任何区别。 我正在使用Ubuntu
16.10
,内核
4.8.0-42-generic
。gcc版本为
6.2.0

奇怪的是,从互联网下载的二进制文件似乎可以正常工作,正确地显示了库调用


我错过了什么?有人能重现这个问题吗?

这可能与现在使用
-z
编译二进制文件有关。我创建了一个快速测试程序(我使用的是Ubuntu 16.04):

如果我使用
gcc-O2 test.c-o test
编译它,那么ltrace可以工作:

$ ltrace ./test 
__libc_start_main(0x400430, 1, 0x7ffc12326528, 0x400550 <unfinished ...>
write(0, "hello\n", 6hello
)                                                              = 6
+++ exited (status 0) +++
您可以使用Ubuntu上的
pax-utils
包中的
scanelf
检查二进制文件是否是这样编译的:

$ scanelf -a test*
 TYPE    PAX   PERM ENDIAN STK/REL/PTL TEXTREL RPATH BIND FILE 
ET_EXEC PeMRxS 0775 LE RW- R-- RW-    -      -   LAZY test 
ET_EXEC PeMRxS 0775 LE RW- R-- RW-    -      -   NOW test2
请注意,
LAZY
(ltrace起作用)与现在的
(ltrace不起作用)相比

这里还有一点讨论(但没有解决方案):


简短的回答是
ltrace
由于被跟踪二进制文件的对象文件类型和位置独立的可执行文件,其行为不符合预期。如果正在跟踪的二进制文件具有
ET_EXEC
对象文件类型且没有位置独立的可执行文件,则
ltrace
将能够拦截并记录动态库调用

有关二进制文件的对象文件类型(
ET_EXEC
ET_DYN
等),请参阅(0x10偏移)

为了验证这一点,我将使用与前面答案相同的
test.c
程序:

#包括
int main(){
写入(0,“hello\n”,6);
返回0;
}
我的系统符合
/etc/os发行版

NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
默认
gcc-v
(版本和配置):

现在使用
gcc test.c-o test
编译,我们有:

$ ltrace ./test
hello
+++ exited (status 0) +++
$ ltrace ./test
write(0, "hello\n", 6hello
)                                                            = 6
+++ exited (status 0) +++
使用
readelf-h./test | grep Type
检查二进制文件的对象文件类型:

  Type:                              DYN (Shared object file)
  Type:                              EXEC (Executable file)
使用强化检查检查检查位置独立可执行文件。/test|grep Position

 Position Independent Executable: yes
 Position Independent Executable: no, normal executable!
然而,使用
gcc-no pie test.c-o test进行编译时,我们有:

$ ltrace ./test
hello
+++ exited (status 0) +++
$ ltrace ./test
write(0, "hello\n", 6hello
)                                                            = 6
+++ exited (status 0) +++
使用
readelf-h./test | grep Type
检查二进制文件的对象文件类型:

  Type:                              DYN (Shared object file)
  Type:                              EXEC (Executable file)
使用强化检查检查检查位置独立可执行文件。/test|grep Position

 Position Independent Executable: yes
 Position Independent Executable: no, normal executable!

希望这有助于澄清
ltrace
的行为及其与跟踪的二进制文件的对象文件类型和位置无关的可执行文件的关系。

我可以在16.10上复制,其中gcc已配置为默认生成饼图可执行文件。根据它的变更日志,ltrace从0.7.0开始就支持PIE可执行文件,所以我不确定0.7.3版为什么不工作。解决方法是使用
--无饼图
编译程序,尽管这会降低安全性一点(ASLR仍将对共享库启用,但不会对可执行文件启用)。@MarkPlotnick我尝试使用
--无饼图
编译程序,不幸的是<代码>--运气不好
:)还是一样的问题。即使成功了,我仍然不明白为什么没有追踪到/bin/ls&Co。既然您能够复制,我就在ltrace-devel邮件列表上发布了,让我们看看是否有人能解决这个奇怪的问题。@MarkPlotnick我错了<代码>--没有饼
单独给我错误
重新定位R_X86_64_32。创建共享对象时不能使用rodata;用-fPIC
重新编译,所以我想我应该按照建议用
-fPIC
重新编译。。。太糟糕了,这仍然会产生馅饼。所以,我想你的解释是对的,我用命令
强化检查
检查了所有无法追踪的二进制文件;这似乎不仅仅与GCC6有关,因为我试图使用GCC5编译,但没有选项(生成了饼图)。此外,我也不确定我的系统二进制文件是如何编译的。在我看来,这与
relro
无关,实际上只是
now
lazy
之间的区别。我可以确认@JosephSible说的话,这与现在的
vs
lazy
有关。感谢您关注@JosephSible和SkullTech。我只是习惯于同时使用“now”和“relro”,因为你使用“now”的主要原因是你可以使用“relro”。我不想单独尝试它们,我只是注意到这也可能是其他原因:一些可执行文件似乎最终成为了一个共享库
ltrace
evince
上不工作,而在
eog
上工作
scanelf
ENVICE
ETDYN
eof
ETEXEC
。顺便说一句,
file
也表示
evice
是ELF共享对象,而不是ELF可执行文件。这就是说,
evince
也被链接到
NOW
@Hibou57 ltrace上,在
etdyn
可执行文件上使用
lazy
工作正常。