Во время различных этапов компиляции в C или C++, я знаю, что объектный файл сгенерирован (т.е. any_name.o файл). Что содержит этот.o файл? Я не могу открыть его, так как это - двоичный файл.
Кто-либо мог помочь мне? Главным образом зависит содержание объектного файла от компилятора, который мы используем на Unix?
Объектные файлы могут содержать кучу всего:
Компоновщик превращает кучу объектных файлов в исполняемый файл, сопоставляя все импорты и экспорты и изменяя скомпилированный код так, чтобы вызывались нужные функции.
Существует несколько стандартизованных форматов (COFF, ELF в Unix), в основном это варианты тех же форматов, которые используются для исполняемых файлов, но отсутствует некоторая информация. Эта недостающая информация будет дополнена при связывании.
Форматы файлов объектов в основном содержат ту же информацию:
Когда объекты будут связаны вместе части кода, которые относятся к внешние символы будут заменены фактическими значениями (ну, это все еще упрощено, есть последняя часть, которая будет выполняться во время загрузки при запуске программы, но это идея).
Объектный файл может также содержать дополнительную информацию о символах, которая строго необходима для разрешения импорта и экспорта (полезно для отладки). Эту информацию можно удалить с помощью команды strip.
Для подобных вещей используйте команду file. Это ELF объектный файл в современной системе Linux. Например, если он скомпилирован для 32-битного x86.
ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
В отличие от этого, динамически подключаемый исполняемый файл может выглядеть так:
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
Для просмотра заголовков, включая имена секций, вы можете использовать:
objdump -x any_name.o
Для дизассемблирования:
objdump -d any_name.o
Объектный файл - это скомпилированный исходный текст.
Это означает, что это машинный код, который зависит от целевой платформы (вы можете компилировать под Unix на Windows, если очень хотите) и используемого компилятора. Разные компиляторы будут создавать разный машинный код из одного и того же исходного файла.
Сначала прочтите вики-страницу . Вы можете использовать objdump , чтобы изучить такой файл :)
В среде компиляции GNU вы можете посмотреть с помощью objdump как в исполняемом файле, так и в объектном.
Как видите, объект содержит только код функций, объявленных/ссылающихся в скомпилированном файле (файл содержит только функцию main с вызовом scanf и вызовом printf).
$ objdump -t scanf_sample.o
scanf_sample.o: file format pe-i386
SYMBOL TABLE:
[ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x00000000 scanf_sample.c
File
[ 2](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _main
[ 3](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text
AUX scnlen 0x91 nreloc 9 nlnno 0
[ 5](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 7](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 9](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .rdata
AUX scnlen 0x54 nreloc 0 nlnno 0
[ 11](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x00000000 ___main
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[ 13](sec 0)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __alloca
[ 14](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _memset
[ 15](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _scanf
[ 16](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _printf
Если использовать objdump на исполняемом файле, то можно увидеть гораздо больше функций (помимо тех, что находятся внутри объекта). Это доказывает, что объектный файл содержит только функции, определенные в исходном файле, со ссылками на другие функции. Эти ссылки будут устранены на этапе компоновки.
Подробнее о линковке, компиляции и объектах.
Во-первых, бинарные файлы можно открывать! Не бойтесь этого, вам нужны только правильные инструменты! Для бинарных данных текстовый редактор, конечно, не подходит; подходящим инструментом может быть шестнадцатеричный редактор, или продвинутый редактор типа emacs, или инструмент, который вместо того, чтобы просто "выводить" байты в их "шестнадцатеричном" представлении и предоставлять вам возможность самостоятельно интерпретировать данные, знает этот конкретный формат и "интерпретирует" данные правильно, на каком-то уровне (например, GIMP интерпретирует данные в "шестнадцатеричном" формате). например, GIMP интерпретирует PNG файл как изображение и показывает его, PNG анализатор "разложит" данные внутри PNG секций, показывая вам флаги в определенных байтах, ...и т.д.).
В вашем случае общий ответ таков: объектный файл содержит ваш скомпилированный код (и данные), плюс все дополнительные сведения, необходимые компоновщику, и, в конечном счете, многое другое.
Как эти сведения "организованы" и в чем состоит это "в конечном итоге больше", зависит от конкретного объектного формата. Некоторые ссылки в Википедии, перечисляющие некоторые из возможностей: this, this, this, this ...
Каждый из них может иметь свои инструменты для анализа содержимого; например, readelf
для ELF, objdump
для нескольких форматов (попробуйте objdump -i
) в зависимости от того, как он был скомпилирован.
Файл содержит двоичные данные, которые необходимо прогнать через компоновщик для создания исполняемого файла. По сути, это набор инструкций машинного кода с именованными секциями (соответствующими вашим функциям). Из статьи Википедии 'Объектный файл':
В информатике объектный файл - это организованная коллекция отдельных именованных последовательностей машинного кода[цитата необходима]. Каждая последовательность, или объект, обычно содержит инструкции для главной машины по выполнения некоторой задачи, возможно сопровождаемые соответствующими данными и метаданными (например, информация о перемещении информация о перемещении, информация о разворачивании стека информация о перемещении, комментарии, программные символы, отладка или профилирование информация). Компоновщик обычно используется для создания исполняемого файла или библиотеки путем объединения частей объектных файлов.