Объектные файлы в исполняемом файле в Linux - PullRequest
8 голосов
/ 30 апреля 2009

Есть ли способ найти объектные файлы, из которых генерируется текущий исполняемый файл в Linux (RHEL, если быть точным). Я понимаю, что можно использовать «nm», чтобы найти экспортируемые символы, «ldd», чтобы найти зависимый общий объект.

Но я не смог найти команду, чтобы узнать имя файла объекта (.o), из которого состоит исполняемый файл. Возможно ли это?

Ответы [ 7 ]

6 голосов
/ 30 апреля 2009

Если он был скомпилирован с отладочной информацией, то да. Используйте gdb (man gdb), чтобы найти информацию.

Если он не был скомпилирован без отладочной информации. Вам не повезло.

5 голосов
/ 13 апреля 2016

Исходные имена объектных файлов не сохраняются в отладочной информации DWARF.

Каждый объектный файл имеет запись DW_TAG_compile_unit в разделе .debug_info. Эта запись содержит ссылку на «первичный исходный файл из которого был получен модуль компиляции », но не имя объектного файла. Стандарт DWARF содержит список атрибутов, которые можно сохранить для каждого модуля компиляции (раздел 3.1.1, номер страницы 44 , стр. 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>
1 голос
/ 18 июня 2018

У меня недостаточно репутации, чтобы добавить комментарий, но чтобы расширить предложение Микеля Рихлиски о применении 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), которые, вероятно, близко соответствуют объектным файлам (в зависимости от вашей системы сборки).

1 голос
/ 13 апреля 2016

Объектный файл преобразуется в исполняемый файл после компоновки. Если ссылка является общей, то вы можете получить ее через общие библиотеки (ldd). Однако, если связь статическая, то есть единственный способ, то есть через отладочную информацию. Вы можете установить пакеты debuginfo в RHEL (или в этом отношении в Fedora). Вот инструкция

А затем используйте gdb info sources, как описано здесь:

Это даст вам список исходных файлов. Но чтобы получить объектные файлы, вам нужно глубже изучить инструменты сборки (rpmbuild). А для реального запуска rpmbuild вам понадобится пакет RPM с исходным кодом, который вы можете получить, следуя инструкциям, перечисленным здесь:

Теперь вы можете собрать пакет самостоятельно и проанализировать, какой файл .o получился в исполняемом файле.

Надеюсь, это поможет.

1 голос
/ 09 апреля 2016

Вы также можете использовать 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 используется только для извлечения соответствующей информации (если вы не используете, вы получите полную отладочную информацию в исполняемом файле и объектах).

1 голос
/ 08 мая 2009

В дополнение к nullptr, «общий объект» относится к другим общим библиотекам (связанным), а не к исходным объектам (не связанным)

0 голосов
/ 05 июля 2018

аналогичен ответу Микелса, но использует другой инструмент, который (может) даст вам более чистый результат.

В прошлом я имел удовольствие работать с инструментом для анализа отладочной информации под названием DIVA. Это бесплатный и открытый исходный код, и вы можете найти его здесь:

https://github.com/SNSystems/DIVA

Хотя с DIVA невозможно найти, какие объектные файлы были связаны для создания вашего исполняемого файла, вы можете использовать его для определения модулей компиляции.

Я быстро собрал небольшой пример следующим образом

a.cpp

int a() {
  return 1;
}

хиджры

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

запустить DIVA на test.elf со следующими параметрами:

$ diva --show-none test.elf

Который должен выдавать следующий вывод

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