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

时间:2021-08-25 13:16:25

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.

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

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

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

7 个解决方案

#1


6  

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

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

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

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

#2


4  

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

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

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).

每个目标文件在.debug_info部分中都有一个DW_TAG_compile_unit条目。此条目包含对“从中派生编译单元的主源文件”的引用,但不包含对象文件的名称。 DWARF标准包含可以为每个编译单元存储的属性列表(第3.1.1节,第44页,pdf第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>

#3


1  

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

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

#4


1  

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

您也可以使用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 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).

awk仅用于提取相关信息(如果您不使用,您将获得可执行文件和对象中的完整调试信息)。

#5


1  

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

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

And then use gdb info sources as described here:

然后使用gdb信息源,如下所述:

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:

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

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

现在,您可以自己构建程序包,并将哪个.o文件解析为可执行文件。

I hope that helps.

我希望有所帮助。

#6


0  

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:

我没有足够的声誉来添加评论,但是为了扩展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}'

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).

这将输出源文件的完整路径(在我的情况下为.cpp文件),这些文件很可能与目标文件紧密匹配(取决于您的构建系统)。

#7


0  

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

类似于Mikels的答案,但使用了一种不同的工具(可能)为您提供更清晰的输出。

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:

在过去,我有幸使用名为DIVA的调试信息分析工具。它是免费和开源的,你可以在这里找到它:

https://github.com/SNSystems/DIVA

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.

虽然DIVA无法找到链接的对象文件以生成可执行文件,但您可以使用它来查找编译单元。

I quickly threw together a small example as follows

我迅速将一个小例子拼凑如下

a.cpp

a.cpp

int a() {
  return 1;
}

a.h

int a();

b.cpp

b.cpp

int b() {
  return 2;
}

b.h

b.h

int b();

c.cpp

c.cpp

#include "a.h"
#include "b.h"

int main() {
  return a + b;
}

Compiled them with clang using the following options

使用以下选项使用clang编译它们

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

run DIVA on test.elf with the following options:

使用以下选项在test.elf上运行DIVA:

$ diva --show-none test.elf

Which should produce the following output

哪个应产生以下输出

{InputFile} "test.elf"
   {CompileUnit} "a.cpp"
   {CompileUnit} "b.cpp"
   {CompileUnit} "c.cpp"

#1


6  

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

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

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

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

#2


4  

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

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

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).

每个目标文件在.debug_info部分中都有一个DW_TAG_compile_unit条目。此条目包含对“从中派生编译单元的主源文件”的引用,但不包含对象文件的名称。 DWARF标准包含可以为每个编译单元存储的属性列表(第3.1.1节,第44页,pdf第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>

#3


1  

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

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

#4


1  

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

您也可以使用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 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).

awk仅用于提取相关信息(如果您不使用,您将获得可执行文件和对象中的完整调试信息)。

#5


1  

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

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

And then use gdb info sources as described here:

然后使用gdb信息源,如下所述:

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:

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

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

现在,您可以自己构建程序包,并将哪个.o文件解析为可执行文件。

I hope that helps.

我希望有所帮助。

#6


0  

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:

我没有足够的声誉来添加评论,但是为了扩展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}'

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).

这将输出源文件的完整路径(在我的情况下为.cpp文件),这些文件很可能与目标文件紧密匹配(取决于您的构建系统)。

#7


0  

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

类似于Mikels的答案,但使用了一种不同的工具(可能)为您提供更清晰的输出。

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:

在过去,我有幸使用名为DIVA的调试信息分析工具。它是免费和开源的,你可以在这里找到它:

https://github.com/SNSystems/DIVA

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.

虽然DIVA无法找到链接的对象文件以生成可执行文件,但您可以使用它来查找编译单元。

I quickly threw together a small example as follows

我迅速将一个小例子拼凑如下

a.cpp

a.cpp

int a() {
  return 1;
}

a.h

int a();

b.cpp

b.cpp

int b() {
  return 2;
}

b.h

b.h

int b();

c.cpp

c.cpp

#include "a.h"
#include "b.h"

int main() {
  return a + b;
}

Compiled them with clang using the following options

使用以下选项使用clang编译它们

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

run DIVA on test.elf with the following options:

使用以下选项在test.elf上运行DIVA:

$ diva --show-none test.elf

Which should produce the following output

哪个应产生以下输出

{InputFile} "test.elf"
   {CompileUnit} "a.cpp"
   {CompileUnit} "b.cpp"
   {CompileUnit} "c.cpp"