Linux中可执行文件中的对象文件

时间:2009-04-30 11:21:43

标签: linux executable object-files

有没有办法找到在Linux中生成当前可执行文件的目标文件(特定于RHEL)。据我所知,可以使用“nm”查找导出的符号,“ldd”查找依赖的共享对象。

但是我找不到命令来查找由哪个可执行文件组成的对象(.o)文件的名称。有可能吗?

7 个答案:

答案 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"