Linux 中可执行文件中的目标文件

发布于 2024-07-18 11:53:06 字数 138 浏览 8 评论 0原文

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

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

Is there a way to find the object files from which the current executable is generated in Linux (RHEL to be specific). I understand that one can use "nm" to find the exported symbols, "ldd" to find dependent shared object.

But I could not find command to find out the name of object (.o) files of which executable is composed of. Is it possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

淡淡绿茶香 2024-07-25 11:53:06

DWARF 调试信息中不存储目标文件的原始名称。

每个目标文件的 .debug_info 部分中都有一个 DW_TAG_compile_unit 条目。 此条目包含对“主要源文件
从中导出编译单元”,但不是目标文件的名称。 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>

The original names of the object files are not stored in the DWARF debugging information.

Each object file has a DW_TAG_compile_unit entry in the .debug_info section. This entry contains a reference to the "primary source file
from which the compilation unit was derived", but not the name of the object file. The DWARF standard contains a list of the attributes that can be stored for each compilation unit (section 3.1.1, page number 44, pdf page 58).

You can view the information that is stored with the following command:

$ readelf --debug-dump=info --dwarf-depth=1 hw

Output:

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>
高冷爸爸 2024-07-25 11:53:06

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

如果没有编译,没有调试信息。 你运气不好。

If it has been compiled with debugging infomation yes. Use gdb (man gdb) to find the infomation.

If it hasnt been compiled without debug infomation. You are out of luck.

つ低調成傷 2024-07-25 11:53:06

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

You can also use objdump (as long as the executable and objects were compiled with debugging information):

# 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 is used just to extract the relevant info (if you don't use, you'll get the full debug info in the executable and objects).

不羁少年 2024-07-25 11:53:06

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

In addition to nullptr, "shared object" refers to other shared libraries (linked), not to original objects (not linked)

望笑 2024-07-25 11:53:06

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

然后使用 gdb infosource,如下所述:

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

现在您可以自己构建包,并剖析其中 < code>.o 文件生成可执行文件。

我希望这有帮助。

An object file translates to an executable after linking. If the linking is shared, then you can get that via shared libraries ( ldd ). However if the linking is static, then there is only way i.e. via debug info. You can install debuginfo packages in RHEL (or Fedora for that matter). Here are the instructions

And then use gdb info sources as described here:

This would give you a list of Source Files. But to actually get the object files, you need to look deeper into the build tools (rpmbuild). And to actually run rpmbuild you would need the Source RPM package, which you can obtain using the instructions listed here:

Now you can build the package yourselves, and dissect which .o file resulted into the executable.

I hope that helps.

玩世 2024-07-25 11:53:06

我没有足够的声誉来添加评论,但要扩展 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在我的例子中,文件)可能与目标文件非常匹配(取决于您的构建系统)。

I don't have enough reputation to add a comment, but to expand on the suggestion by Mikel Rychliski to use readelf, you can use awk to extract the paths of the source files:

readelf --debug-dump=info --dwarf-depth=1 hw exe_to_examine | awk '/DW_AT_name/ {file=$8} /DW_AT_comp_dir/ {print $8 "/" file}'

This outputs the full paths to the source files (.cpp files in my case) which are likely to be a close match to the object files (depending on your build system).

优雅的叶子 2024-07-25 11:53:06

与 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"

similar to Mikels answer but using a different tool that (may) give you a cleaner output.

In the past I've had the pleasure of working on a debug information analyzer tool called DIVA. It's free and open source and you can find it here:

https://github.com/SNSystems/DIVA

Whilst it's not possible with DIVA to find what object files were linked to produce your executable, you can use it to find out the compile units.

I quickly threw together a small example as follows

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;
}

Compiled them with clang using the following options

$ clang a.cpp b.cpp c.cpp -o test.elf -g -O0

run DIVA on test.elf with the following options:

$ diva --show-none test.elf

Which should produce the following output

{InputFile} "test.elf"
   {CompileUnit} "a.cpp"
   {CompileUnit} "b.cpp"
   {CompileUnit} "c.cpp"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文