有没有办法找到在Linux中生成当前可执行文件的目标文件(特定于RHEL)。据我所知,可以使用“nm”查找导出的符号,“ldd”查找依赖的共享对象。
但是我找不到命令来查找由哪个可执行文件组成的对象(.o)文件的名称。有可能吗?
答案 0 :(得分:6)
如果已经编译了调试信息是。使用gdb(man gdb)查找信息。
如果没有调试信息而没有编译。你运气不好。
答案 1 :(得分:5)
目标文件的原始名称不存储在DWARF调试信息中。
每个目标文件在DW_TAG_compile_unit
部分都有.debug_info
条目。此条目包含对"主要源文件的引用
从中导出编译单元",但不是目标文件的名称。 The DWARF standard包含可以为每个编译单元存储的属性列表(第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>
答案 2 :(得分:1)
除了nullptr之外,“共享对象”指的是其他共享库(链接),而不是原始对象(未链接)
答案 3 :(得分:1)
您也可以使用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
仅用于提取相关信息(如果您不使用,您将在可执行文件和对象中获得完整的调试信息)。
答案 4 :(得分:1)
目标文件在链接后转换为可执行文件。如果链接是共享的,那么您可以通过共享库(ldd
)获取链接。但是,如果链接是静态的,那么只有通过调试信息的方式。您可以在RHEL(或Fedora)中安装debuginfo软件包。以下是说明
然后使用gdb info sources
,如下所述:
这将为您提供源文件列表。但要实际获取目标文件,您需要深入了解构建工具(rpmbuild
)。要实际运行rpmbuild,您需要使用Source RPM软件包,您可以使用此处列出的说明获取该软件包:
现在您可以自己构建软件包,并将.o
文件分析到可执行文件中。
我希望有所帮助。
答案 5 :(得分:1)
我没有足够的声誉来添加评论,但是为了扩展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文件),这些文件可能与目标文件非常匹配(取决于您的构建系统)。
答案 6 :(得分:0)
类似于Mikels的答案,但是使用的是(可能)为您提供更清晰输出的另一种工具。
过去,我很高兴使用称为DIVA的调试信息分析器工具。它是免费和开源的,您可以在这里找到它:
https://github.com/SNSystems/DIVA
虽然DIVA无法找到链接了哪些对象文件以生成可执行文件,但是您可以使用它来查找编译单元。
我很快将一个小例子总结如下
a.cpp
int a() {
return 1;
}
a.h
int a();
b.cpp
int b() {
return 2;
}
b.h
int b();
c.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"