8

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

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

4

7 回答 7

7

目标文件的原始名称不存储在 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>
于 2016-04-13T14:45:10.220 回答
6

如果它已经用调试信息编译过,是的。使用 gdb (man gdb) 查找信息。

如果它没有在没有调试信息的情况下编译。你运气不好。

于 2009-04-30T11:39:06.977 回答
3

您还可以使用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仅用于提取相关信息(如果不使用,您将在可执行文件和对象中获得完整的调试信息)。

于 2016-04-09T12:14:13.393 回答
1

除了 nullptr,“共享对象”是指其他共享库(链接),而不是原始对象(未链接)

于 2009-05-08T14:30:04.277 回答
1

目标文件在链接后转换为可执行文件。如果链接是共享的,那么您可以通过共享库 ( ldd) 获得它。但是,如果链接是静态的,那么只有通过调试信息的方式。您可以在 RHEL(或 Fedora)中安装 debuginfo 包。这是说明

然后按照此处所述使用 gdb info sources

这将为您提供源文件列表。但要真正获得目标文件,您需要深入了解构建工具 ( rpmbuild)。要实际运行 rpmbuild,您需要 Source RPM 包,您可以使用此处列出的说明获取该包:

现在您可以自己构建包,并剖析.o生成可执行文件的文件。

我希望这会有所帮助。

于 2016-04-13T20:37:04.027 回答
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 文件)的完整路径,这些文件可能与目标文件非常匹配(取决于您的构建系统)。

于 2018-06-18T08:54:37.923 回答
0

类似于 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"
于 2018-07-05T17:53:33.777 回答