Некоторые начинающие вопросы о файлах elf, заголовках разделов и как они работают в целом, когда мы запускаем приложение - PullRequest
1 голос
/ 17 февраля 2020

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

Когда вы пишете приложение C и компилируете его (например, с помощью g cc), оно переводится в машинные инструкции. которые представляют код и данные. Результатом вызова компилятора является файл elf. Файл elf содержит (помимо прочего) заголовок раздела, который в основном представляет собой серию Elf64_Shdr каждый для каждого раздела, который содержит ваше скомпилированное приложение. Таким образом, в основном раздел - это просто некоторые машинные инструкции, которые представляют либо код, либо данные и некоторую информацию о них, например, где он (адрес первой инструкции) и как долго он (размер), является ли он записываемым или читаемым (некоторые flags), et c. Правильно ли я понимаю разделы и заголовок раздела?

Когда мы запускаем команду make и передаем ей файл elf, компоновщик входит в игру и просматривает все созданные разделы компилятором, по их именам и атрибутам и группирует их в «сегменты», следуя правилам файла сценария ld, и создает исполняемый файл, который мы можем запустить общий раздел с указанным c именем. Это правильно?

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

Спасибо, что прочитали и помогли мне прояснить мои сомнения, спасибо.

1 Ответ

0 голосов
/ 19 февраля 2020

В вашем описании несколько неточностей, и неясно, неточны ли вы в понимании процесса обработки или в описании их.

Когда вы пишете C приложение, и вы компилируете его (скажем, с помощью g cc), оно переводится в машинные инструкции, которые представляют код и данные.

Это не совсем точно: между машинными инструкциями есть разница "и" машинный код ".

Когда вы компилируете файл .c, некоторые компиляторы преобразуют его в машинные инструкции (сборка), а затем передают его ассемблеру для получения машинного кода (G CC делает который). Другие компиляторы имеют встроенный ассемблер и фактически пропускают этап генерации сборки (это делает Clang).

Результат вызова компилятора - файл elf.

On некоторые , но не все системы, результатом компиляции является перемещаемый файл ELF. Другие системы создают объектные файлы в другом формате, например, XCOFF или Mach-O.

Файл elf содержит (среди прочего) заголовок раздела, который в основном представляет собой серию Elf64_Shdr для каждого раздела. Ваше скомпилированное приложение содержит.

Приложение еще не создано, поэтому это неточно. Кроме того, Elf64_Shdr относится только к 64-битным платформам ELF; на 32-битных машинах это Elf32_Ehdr.

Когда мы запускаем команду make

Команда make не имеет ничего , имеющего отношение к что-нибудь. Он просто вызывает компилятор и компоновщик (или другие инструменты) в зависимости от ситуации. Вы можете заменить его сценарием оболочки или просто набрать команды вручную.

и передать ему файл эльфа

Шаг ссылки включает один или больше (обычно больше) перемещаемых ELF объектных файлов, архивных библиотек и динамических c библиотек.

компоновщик входит в игру и просматривает все разделы, созданные компилятором, на их присваивает имена и атрибуты и группирует их в «сегменты» в соответствии с правилами файла сценария ld

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

Ваше описание упрощает работу компоновщика. Компоновщик намного сложнее и выполняет разрешение перемещения, о котором вы не упомянули, и много других задач.

и создает исполняемый файл, который мы можем запустить.

Обычно true.

Вы можете попросить компоновщика объединить несколько перемещаемых объектных файлов в объединенный объектный файл (с ld -r foo.o bar.o -o combined.o), и в этом случае результат будет не быть исполняемым файлом.

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

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

False. lot больше для связывания, чем группирование разделов вместе.

Затем, когда мы фактически запускаем созданный исполняемый файл, загрузчик входит в игру

Загрузчик вступает в игру только для динамически связанных исполняемых файлов. Полностью исполняемые c исполняемые файлы не имеют загрузчика и запускаются непосредственно самим ядром.

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

В основном правильно. Некоторые части образа памяти вообще не берутся с диска (например, локальное хранилище потока и содержимое объединенных .bss разделов)

...