Что такое объектный файл

Обновлено: 07.07.2024

Объектный файл представляет собой компьютерный файл , содержащий объектный код , то есть, машинный код выход на ассемблере или компилятор . Код объекта обычно перемещаемый , и обычно не непосредственно исполняемый файл . Существуют различные форматы объектных файлов, и один и тот же машинный код может быть упакован в разные форматы объектных файлов. Объектный файл может также работать как разделяемая библиотека .

Помимо самого объектного кода, объектные файлы могут содержать метаданные, используемые для связывания или отладки, в том числе: информацию для разрешения символьных перекрестных ссылок между различными модулями, информацию о перемещении, информацию о раскручивании стека , комментарии , символы программы , информацию об отладке или профилировании . Другие метаданные могут включать дату и время компиляции, имя и версию компилятора и другую идентифицирующую информацию.

Термин «объектная программа» появился как минимум в 1950-х годах:

Термин в автоматическом программировании для программы на машинном языке, созданной машиной путем перевода исходной программы, написанной программистом, на язык, похожий на алгебраическую нотацию.

Программист генерирует объектный код с помощью компилятора или ассемблера . Так , например, под Linux , то GNU Compiler Collection компилятор будет генерировать файлы с расширением .o которые используют ELF формат. Компиляция в Windows создает файлы с расширением .obj, которые используют формат COFF . Затем компоновщик используется для объединения объектного кода в одну исполняемую программу или библиотеку, при необходимости извлекая предварительно скомпилированные системные библиотеки. Программы JavaScript интерпретируются, в то время как программы Python и Java компилируются в файлы с байт-кодом .

СОДЕРЖАНИЕ

Форматы объектных файлов

Есть много различных форматов объектных файлов; Первоначально у каждого типа компьютера был свой уникальный формат, но с появлением Unix и других переносимых операционных систем некоторые форматы, такие как ELF и COFF , были определены и использовались в различных типах систем. Один и тот же формат можно использовать как для ввода и вывода компоновщика , так и для формата библиотеки и исполняемого файла. Некоторые форматы могут содержать машинный код для разных процессоров, причем правильный код выбирается операционной системой при загрузке программы.

Некоторые системы делают различие между форматами, которые являются непосредственно исполняемыми, и форматами, которые требуют обработки компоновщиком. Например, OS / 360 и ее последователи называют первый формат загрузочным модулем, а второй - объектным модулем . В этом случае файлы имеют совершенно разные форматы.

Дизайн и / или выбор формата объектного файла является ключевой частью общего дизайна системы. Это влияет на производительность линкера и , таким образом , программисту поворот в то время как программа разрабатывается. Если формат используется для исполняемых файлов, дизайн также влияет на время, необходимое для запуска программ , и, следовательно, на скорость отклика для пользователей.

Абсолютные объектные файлы

Многие ранние компьютеры или небольшие микрокомпьютеры поддерживают только абсолютный объектный формат. Программы не могут быть перемещены; они должны быть собраны или скомпилированы для выполнения по определенным заранее определенным адресам. Файл не содержит информации о перемещении или привязке. Эти файлы могут быть загружены в память для чтения / записи или сохранены в постоянной памяти . Например, монитор Motorola 6800 MIKBUG содержит процедуру для чтения абсолютного объектного файла ( формат SREC ) с бумажной ленты . COM-файлы DOS являются более поздним примером абсолютных объектных файлов.

Сегментация

Большинство форматов объектных файлов структурированы как отдельные разделы данных, каждый из которых содержит определенный тип данных. Эти разделы известны как «сегменты» из-за термина « сегмент памяти », который ранее был распространенной формой управления памятью . Когда программа загружается в память загрузчиком , загрузчик выделяет программе различные области памяти. Некоторые из этих областей соответствуют сегментам объектного файла и поэтому обычно известны под одними и теми же именами. Другие, например стек, существуют только во время выполнения. В некоторых случаях перемещение выполняется загрузчиком (или компоновщиком) для указания фактических адресов памяти. Однако для многих программ или архитектур в перемещении нет необходимости, поскольку оно выполняется блоком управления памятью или независимым от позиции кодом . В некоторых системах сегменты объектного файла затем могут быть скопированы (выгружены) в память и выполнены без необходимости дальнейшей обработки. В этих системах это может выполняться лениво , то есть только тогда, когда на сегменты ссылаются во время выполнения, например, через отображаемый в память файл, поддерживаемый объектным файлом.

Типы данных, поддерживаемые типичными форматами объектных файлов:

  • Заголовок (описательная и контрольная информация)
  • Сегмент кода («текстовый сегмент», исполняемый код)
  • Сегмент данных (инициализированные статические переменные )
  • Сегмент данных только для чтения ( родата, инициализированные статические константы )
  • Сегмент BSS (неинициализированные статические данные, как переменные, так и константы)
  • Внешние определения и ссылки для ссылки
  • Информация о переезде
  • Динамическая компоновка информации
  • Отладочная информация

Сегменты в разных объектных файлах могут быть объединены компоновщиком в соответствии с правилами, указанными при определении сегментов. Существуют соглашения для сегментов, совместно используемых объектными файлами; например, в DOS существуют разные модели памяти, которые определяют имена специальных сегментов и то, могут ли они быть объединены.

Отладочная информация может быть либо неотъемлемой частью формата файла объекта, как и в COFF , или полунезависимое формат , который может быть использован с несколькими форматами объектов, таких как уколов или DWARF .

Проект GNU «s Binary библиотека Descriptor File (библиотека BFD) обеспечивает общий API для манипуляции объектных файлов в различных форматах.

Сегодня мы рассмотрим структуру абстрактного объектного файла. То есть, фактически результат работы компилятора. Именно эта информация и попадает на вход компоновщика.

Рассматривать будем некий абстрактный формат для не менее абстрактной машины. По той простой причине, что кроме привычных всем x86 процессоров существует и множество других архитектур, включая великое множество микроконтроллеров. Да и компиляторы бывают разные, для не менее разных языков высокого уровня.

Еще раз отмечу, что в данном цикле статей рассматриваются, причем очень упрощенно, лишь самые общие моменты связанные с объектными файлами и работой компоновщика.

не является строго обязательной к прочтению, но все таки рекомендуется с ней познакомится, если вы этого еще не сделали.

Объектный файл состоит из записей различного типа и различной длины. В общем и целом, можно выделить такие типы записей:

  • Определения. Сюда относятся определения программных секций, символов, и прочих сущностей.
  • Машинный код. Это то, во что превратилась программа на языке высокого уровня.
  • Корректировки и перемещения. Это инструкции для компоновщика по изменению машинного кода и работе с определенными в других файлах и библиотеках сущностями.

Именно записи этих типов мы сегодня будем рассматривать. Все прочие типы, например, информация для отладчика, номера строк, различная текстовая и служебная информация, сегодня остаются "за кадром".

Определения программных секций

В предыдущей статье я рассказывал, что программные секции используются компилятором для размещения кода и данных. Ни одна процедура, ни одна переменная, не могут быть размещены вне программной секции.

Программная секция имеет несколько атрибутов:

  • Имя секции . Фактически, это произвольный текст с ограничением на длину. Практически, компиляторы используют свои внутренние соглашения для именования секций. Например, секции с машинным кодом могут именоваться "TEXT" или "имя_функции_CODE". Зачастую программист может определить и свои собственные секции с любым именем.
  • Тип данных . Секция, как область памяти, могут содержать информацию разного типа. Наиболее известное деление это код и данные. Со строгой точки зрения невозможно прочитать или модифицировать информацию в секции кода при выполнении программы. И невозможно передать управление в секцию данных. Дополнительно можно определить секцию констант, которая отличается от секции данных тем, что запись в нее не возможна. А для микроконтроллеров может иметь смысл выделить секцию данных для энергонезависимой памяти.
  • Тип размещения и объединения . Одноименные секции из разных файлов можно размещать последовательно, друг за другом. Общий размер итоговой секции будет равен сумме размеров одноименных секций из всех файлов. А можно размещать с одного и того же адреса, накладывая одну на другую. И размер итоговой секции будет равен размеру наибольшей секции из всех файлов. При этом размещение объектов в секциях обычно идет в направлении увеличения адресов. Но есть еще и стек, в котором объекты размещаются в направлении уменьшения адресов.
  • Адрес размещения секции . Если необходимо разместить секцию по строго определенному адресу в памяти машины, то используют специальный тип размещения - абсолютный. Для других типов размещения этот атрибут заполняется не компилятором, а компоновщиков. Мы рассмотрим это в следующей статье.
  • Размер секции . Имеется ввиду размер секции в данном объектном файле. Этот размер вычисляется компилятором.

Теперь мы можем представить запись объектного файла о программной секции примерно в таком виде:

Возможный вид записи о программной секции в объектном файле. Иллюстрация моя Возможный вид записи о программной секции в объектном файле. Иллюстрация моя

У программных секция могут быть и другие атрибуты, например, выравнивание по границам слов или двойных слов. Я не буду в данном цикле статей рассматривать эти атрибуты.

Определения символов

Символы, с точки зрения компоновщика, это и переменные, и процедуры. Нет никакой разницы между именем процедуры и именем переменной или другого агрегата данных, важны лишь размер и адрес размещения. На уровне компоновщика, подчеркиваю еще раз. Все дополнительные синтаксические и семантические смыслы остаются на уровне компилятора.

И это является очень наглядной демонстрацией семантического разрыва между языком высокого уровня и машиной. При этом компоновщик работает немного выше уровня машины, но гораздо ниже уровня языка высокого уровня.

Каждый символ размещается, еще компилятором, в одной из программных секций. Адрес размещения символа отсчитывается от начала программной секции внутри данного конкретного объектного файла. Причем символ должен именно определяться, размещаться, а не просто описываться в исходном файле, который и был преобразован компилятором в объектный.

И вот тут возникает несколько интересных моментов. Во первых, какие именно символы должны попадать в объектный файл в виде определений?

Локальные переменные, которые размещаются в стеке, не требуют внимания со стороны компоновщика. С их обработкой отлично справляется компилятор, поэтому дополнительная информация в объектном файле о таких переменных отсутствует. Параметры передаваемые функции, как и возвращаемое значение, тоже размещаются в стеке. И тоже не требуют внимания компоновщика.

Глобальные переменные, которые в языке С определяются вне функций, доступны из других объектных файлов. А значит, информация о них должна быть в объектном файле. И компоновщик будет этой информацией пользоваться.

А вот что можно сказать о переменных с модификатором static? Нужна ли информация о них в объектном файле? Если нужна, то о каких именно, определенных только вне функций, или об определенных и внутри функций? Ведь эти переменные из других объектных файлов не доступны.

Нужна, обязательно нужна! Вспомните, что компилятор не знает, как и по каким адресам будут размещаться программные секции, а переменные static, не смотря на ограничения области видимости, должны существовать все время выполнения программы. Они размещаются не в стеке, не относительно указателя стека, а в области данных программы, в одной из секций данных. И в момент компиляции полный адрес такой переменной неизвестен. Уточнить этот адрес может только компоновщик.

Попадают в объектный в виде записей определения символов и все процедуры, не только глобальные, но и локальные. Исключением могут являться локальные метки, переходы на которые выполняются только командами относительного перехода.

Во вторых, возникает вопрос с формой определения сложных агрегатов данных. С простой переменной проблем нет, а что делать с массивами, структурами, объединениями? Давайте немного подробнее рассмотрим этот вопрос.

Итак, компилятор размещает агрегат данных задав его начальный адрес (относительно начального адреса программной секции) и указав размер. Но агрегат имеет и внутреннюю структуру. Например, у структуры есть поля

которые и сами могут быть агрегатами данных

person.name[20]

Как поступать в подобных случаях? Ведь обращение к person.age требует обращения по адресу равному адресу размещения person плюс смещение до поля age внутри person. А если person определена в другом файле, то даже начальный адрес внутри программной секции будет неизвестен.

Здесь возможны различные варианты, но основных два. Первый вариант, компилятор размещает в программной секции не структуру, а отдельные поля структуры, как независимые переменные. Особых сложностей при этом не возникает, все равно с точки зрения машины семантической сущности "структура" не существует. Равно как и сущности, например, "объект класса". Машина, процессор, оперирует лишь с ячейками памяти.

Да, в природе существуют машины с более высокими уровнями абстракции, когда единицей информации может быть не ячейка памяти, а структурированная область памяти. Но эти машины являются экзотическими (во всяком случае, для большинства читателей) и мы их не рассматриваем.

Таким образом, вся высокоуровневая семантика остается на уровне компилятора, а компоновщик работает с обычными переменными в ячейках памяти.

Второй вариант, когда агрегат данных рассматривается как специальная виртуальная программная секция. Такая секция не размещается компоновщиком в памяти, она размещается компилятором внутри одной из реальных программных секций. А для компоновщика появляются два вида адресов: адреса обычные и адреса относительные. Первые относятся к адресам в программных секциях, а вторые к адресам в виртуальных программных секциях.

Это более гибкий способ, но он порождает новые проблемы. Поскольку, например, структура может включать в себя другие структуры в виде полей, то глубина вложенности может оказаться большой. А компоновщику надо будет с этой вложенностью разбираться. При том, для большинства процессоров такая детализация просто излишня.

Поэтому я буду рассматривать лишь вариант размещения полей структур как отдельных переменных. Для нас это будет достаточным. Теперь мы модем составить список основных атрибутов символов:

Я читаю о библиотеках в C, но я еще не нашел объяснения о том, что такое объектный файл. В чем реальная разница между любым другим скомпилированным файлом и объектным файлом?
Я был бы рад, если бы кто-нибудь объяснил на человеческом языке.

объектный файл является реальным выходом из фазы компиляции. Это в основном машинный код, но есть информация, которая позволяет компоновщику видеть, какие символы в нем, а также символы, необходимые для работы. (Для справки, "символы" в основном имена глобальных объектов, функций и т. д.)

компоновщик берет все эти объектные файлы и объединяет их в один исполняемый файл (предполагая, что он может, т. е. что нет дубликатов или неопределенных символов). Большое компиляторы сделайте это для вас (читайте: они запускают компоновщик самостоятельно), если вы не скажете им "просто скомпилировать", используя параметры командной строки. ( -c является общей опцией" просто компилировать; не связывать".)

объектный файл-это сам скомпилированный файл. Между ними нет никакой разницы.

исполняемый файл формируется путем связывания объектные файлы.

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

этот низкоуровневый машинный код является двоичным представлением инструкций, которые вы также можете написать непосредственно используя язык ассемблера, а затем обработайте код языка ассемблера (представленный на английском языке) на машинный язык (представленный на Hex) с помощью ассемблера.

вот типичный поток высокого уровня для этого процесса для кода на языке высокого уровня, таком как C

--> проходит через pre-processor

--> чтобы дать оптимизированный код, все еще в C

--> проходит через компилятор

--> для того чтобы дать агрегат код

--> проходит через ассемблер

--> дать код на машинном языке, который хранится в объектных файлах

--> проходит через Linker

--> чтобы получить исполняемый файл.

этот поток может иметь некоторые варианты, например, большинство компиляторов могут непосредственно генерировать код машинного языка, не проходя через ассемблер. Точно так же они могут сделать предварительную обработку для вас. Тем не менее, приятно разбить избирателей на лучшее понимание.

есть 3 вида объектных файлов.

перемещаемые объектные файлы

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

если у вас a.c исходный файл, чтобы создать его объектный файл с помощью GCC, вы должны запустить: gcc a.c -c

полный процесс будет: препроцессор (cpp) будет работать над a.c. Его выход (все еще источник) будет подаваться в компилятор (СС1). Его выход (сборка) будет подаваться в ассемблер (as), который будет производить relocatable object file . Этот файл содержит объектный код и ссылку (и может отлаживать, если -g был использован) метаданные, и не является непосредственно исполняемым.

общие объектные файлы

специальный тип перемещаемого объектного файла, который может быть загружен динамически во время загрузки или во время выполнения. Общие библиотеки-это объекты такого рода.

исполняемый объект файлы

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

результат запуска компоновщика над несколькими relocatable object files это executable object file . Компоновщик объединяет все входные объектные файлы из командной строки слева направо, объединяя все входные секции одного типа (например, .data ) к тому же типу выходной секции. Он использует symbol resolution и relocation .

бонус:

когда связывание против static library , функции, на которые ссылаются во входных объектах, копируются в конечный исполняемый файл. С dynamic libraries , вместо этого создается таблица символов, которая позволит динамическую связь с функциями/глобалами библиотеки. Таким образом, результатом является частично исполняемый объектный файл, так как он зависит от библиотеки. (проще говоря, если библиотека исчезла, файл больше не может выполняться).

процесс соединения можно сделать следующим образом: ld a.o -o myexecutable

в команда: gcc a.c -o myexecutable вызовет все команды, упомянутые в пункте 1 и в пункте 3 (cpp - > cc1 - > as - > ld 1 )

1: на самом деле это collect2, который является оболочкой над ld.

объектный файл-это то, что вы получаете при компиляции одного (или нескольких) исходных файлов.

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

объектные файлы обычно содержат собственный код, информацию компоновщика, отладочные символы и т. д.

объектный код-это коды, которые зависят от функций, символов, текста для запуска машины. Просто как старый телекс машин которые требовали teletyping посылают сигналы другим телекс машина. Таким же образом процессор требует двоичного кода для запуска машины. Объектный файл похож на двоичный код, но не связан. Связывание создает дополнительные файлы, так что пользователь не должен иметь компилятор языка Си. Пользователь может напрямую открыть exe-файл, как только объектный файл связан с некоторым компилятором, таким как c язык, или vb etc.

Обье́ктный мо́дуль (также — объектный файл, англ. object file ) — файл с промежуточным представлением отдельного модуля программы, полученный в результате обработки исходного кода компилятором. Объектный файл содержит в себе особым образом подготовленный код (часто называемый бинарным), который может быть объединён с другими объектными файлами при помощи редактора связей (компоновщика) для получения готового исполнимого модуля либо библиотеки.

Объектные файлы представляют собой блоки машинного кода и данных, с неопределенными адресами ссылок на данные и процедуры в других объектных модулях, а также список своих процедур и данных. Компоновщик собирает код и данные каждого объектного модуля в итоговую программу, вычисляет и заполняет адреса перекрестных ссылок между модулями. Также в процессе компоновки происходит связывание программы со статическими и динамическими библиотеками (являющихся архивами объектных файлов).

См. также

Wikimedia Foundation . 2010 .

Смотреть что такое "Объектный файл" в других словарях:

Объектный Си — Objective C Класс языка: объектно ориентированный, мультипарадигмальный: рефлексивно ориентированный Появился в: 1986 г. Автор(ы): Типизация данных: строгая полиморфная, статическая Основные реализации: Apple gcc Испытал … Википедия

Список расширений имени файла/A — / * A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Примечание: Поскольку расширение имени файла может быть любым, представленный список не является полным … Википедия

Метаобъектный компилятор — Эта статья предлагается к удалению. Пояснение причин и соответствующее обсуждение вы можете найти на странице Википедия:К удалению/25 июня 2012. Пока процесс обсуждения … Википедия

D (язык программирования) — У этого термина существуют и другие значения, см. D. D Семантика: мультипарадигменный: императивное, объектно ориентированное, обобщённое программирование Тип исполнения: компилятор Появился в: 1999 Автор(ы) … Википедия

Компиляция — в программировании перевод программы с языка высокого уровня в машинный язык. Результатом компиляции является объектный файл с необходимыми внешними ссылками для компоновщика. См. также: Трансляторы Финансовый словарь Финам … Финансовый словарь

Читайте также: