有没有办法找到在 Linux 中生成当前可执行文件的目标文件(具体是 RHEL)。我知道可以使用“nm”来查找导出的符号,“ldd”来查找依赖的共享对象。
但是我找不到命令来找出可执行文件组成的对象(.o)文件的名称。可能吗?
有没有办法找到在 Linux 中生成当前可执行文件的目标文件(具体是 RHEL)。我知道可以使用“nm”来查找导出的符号,“ldd”来查找依赖的共享对象。
但是我找不到命令来找出可执行文件组成的对象(.o)文件的名称。可能吗?
目标文件的原始名称不存储在 DWARF 调试信息中。
每个目标文件在该部分中都有一个DW_TAG_compile_unit
条目。.debug_info
此条目包含对“派生编译单元的主要源文件”的引用,但不包含目标文件的名称。DWARF 标准包含可以为每个编译单元存储的属性列表(第 3.1.1 节,第 44 页,pdf 第 58 页)。
您可以使用以下命令查看存储的信息:
$ readelf --debug-dump=info --dwarf-depth=1 hw
输出:
Contents of the .debug_info section:
<some compilation units removed>
Compilation Unit @ offset 0x133:
Length: 0x8b (32-bit)
Version: 4
Abbrev Offset: 0x64
Pointer Size: 4
<0><13e>: Abbrev Number: 1 (DW_TAG_compile_unit)
<13f> DW_AT_producer : (indirect string, offset: 0x131): GNU C11 5.3.0 -mtune=generic -march=pentiumpro -g
<143> DW_AT_language : 12 (ANSI C99)
<144> DW_AT_name : (indirect string, offset: 0x163): hw.c
<148> DW_AT_comp_dir : (indirect string, offset: 0x168): /home/mikel/src/hw
<14c> DW_AT_low_pc : 0x80483db
<150> DW_AT_high_pc : 0x2e
<154> DW_AT_stmt_list : 0xea
<1><158>: ...
<some compilation units removed>
如果它已经用调试信息编译过,是的。使用 gdb (man gdb) 查找信息。
如果它没有在没有调试信息的情况下编译。你运气不好。
您还可以使用objdump
(只要可执行文件和对象是使用调试信息编译的):
# gcc -g -c -o /tmp/some_object.o /tmp/some_object.c
# gcc -g -o /tmp/file /tmp/file.c /tmp/some_object.o
# objdump -g /tmp/file | awk 'BEGIN{out=0} /Directory Table/{out=1} /Line Number Statements/{out=0} {if(out){print $0}}'
The Directory Table (offset 0x1b):
1 /tmp
The File Name Table (offset 0x21):
Entry Dir Time Size Name
1 1 0 0 file.c
The Directory Table (offset 0x5a):
1 /tmp
The File Name Table (offset 0x60):
Entry Dir Time Size Name
1 1 0 0 some_object.c
awk
仅用于提取相关信息(如果不使用,您将在可执行文件和对象中获得完整的调试信息)。
除了 nullptr,“共享对象”是指其他共享库(链接),而不是原始对象(未链接)
目标文件在链接后转换为可执行文件。如果链接是共享的,那么您可以通过共享库 ( ldd
) 获得它。但是,如果链接是静态的,那么只有通过调试信息的方式。您可以在 RHEL(或 Fedora)中安装 debuginfo 包。这是说明
然后按照此处所述使用 gdb info sources
:
这将为您提供源文件列表。但要真正获得目标文件,您需要深入了解构建工具 ( rpmbuild
)。要实际运行 rpmbuild,您需要 Source RPM 包,您可以使用此处列出的说明获取该包:
现在您可以自己构建包,并剖析.o
生成可执行文件的文件。
我希望这会有所帮助。
我没有足够的声誉来添加评论,但要扩展 Mikel Rychliski 使用 readelf 的建议,您可以使用 awk 提取源文件的路径:
readelf --debug-dump=info --dwarf-depth=1 hw exe_to_examine | awk '/DW_AT_name/ {file=$8} /DW_AT_comp_dir/ {print $8 "/" file}'
这会输出源文件(在我的情况下为 .cpp 文件)的完整路径,这些文件可能与目标文件非常匹配(取决于您的构建系统)。
类似于 Mikels 的答案,但使用不同的工具(可能)为您提供更清晰的输出。
过去,我有幸使用名为 DIVA 的调试信息分析工具。它是免费和开源的,你可以在这里找到它:
https://github.com/SNSystems/DIVA
虽然 DIVA 无法找到链接到哪些目标文件以生成可执行文件,但您可以使用它来找出编译单元。
我赶紧整理了一个小例子如下
a.cpp
int a() {
return 1;
}
啊
int a();
b.cpp
int b() {
return 2;
}
bh
int b();
cpp
#include "a.h"
#include "b.h"
int main() {
return a + b;
}
使用以下选项使用 clang 编译它们
$ clang a.cpp b.cpp c.cpp -o test.elf -g -O0
使用以下选项在 test.elf 上运行 DIVA:
$ diva --show-none test.elf
应该产生以下输出
{InputFile} "test.elf"
{CompileUnit} "a.cpp"
{CompileUnit} "b.cpp"
{CompileUnit} "c.cpp"