2010-11-24 3 views
4

Я читал спецификацию ELF и не могу понять, откуда взялась точка входа в программу и адрес _start.В файле ELF, как определить адрес для _start?

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

Может ли кто-нибудь уточнить?

ответ

2

Символ _start может быть определен в любом объектном файле. Обычно он генерируется автоматически (он соответствует main в C). Вы можете создать его самостоятельно, например, в исходном файле ассемблера:

.globl _start 
_start: 
    // assembly here 

Когда компоновщик обработает все объектные файлы он выглядит для _start символа и помещает его значение в e_entry поле elf header. Загрузчик берет адрес из этого поля и делает ему вызов после того, как он закончил загрузку всех разделов в памяти и готов выполнить этот файл.

+0

Как правило, `_start` на самом деле не является` главным ', по крайней мере, с помощью функций GCC/glibc: `_start` вызывает инициализацию, затем` main`, затем `exit() `со значением, возвращаемым` main`. – ysdx 2016-02-12 00:35:38

0

Я не уверен, но попробуйте эту ссылку http://www.docstoc.com/docs/23942105/UNIX-ELF-File-Format на странице 8 показано, где находится точка входа, если она выполнена. В принципе вам нужно рассчитать смещение, и вы его получили. Удостоверьтесь, что вы помните маленькую сущность x86 (я предполагаю, что вы ее используете) и переупорядочиваете, если вы читаете пошаговое редактирование: или, может быть, я не уверен в этом, если честно.

+0

Похоже, что связанный документ находится за платной линией ... – Calmarius 2013-08-16 19:44:26

1

Возьмите взгляд на сценарии компоновки ld использует:

ld -verbose 

Формат документированы: https://sourceware.org/binutils/docs-2.25/ld/Scripts.html

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

На Binutils 2.24 Ubuntu 14.04 64-бит, он содержит строку:

ENTRY(_start) 

который устанавливает точку входа в _start символ (идет в заголовок ELF, как указано с помощью КТС)

И затем:

. = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS; 

, который задает адрес первых заголовков к 0x400000 + SIZEOF_HEADERS.

Я изменил этот адрес 0x800000, прошел мой собственный сценарий с ld -T, и она работала: readelf -s говорит, что _start находится по этому адресу.

Другой способ изменить это - использовать опцию -Ttext-segment=0x800000.

Причина использования 0x400000 = 4Mb = getconf PAGE_SIZE начнется в начале второй страницы, как спросил у: Why is the ELF execution entry point virtual address of the form 0x80xxxxx and not zero 0x0?

в вопросе описывается, как установить _start из командной строки: Why is the ELF entry point 0x8048000 not changeable with the "ld -e" option?

SIZEOF_HEADERS представляет собой размер заголовков программ ELF +, которые находятся в начале файла ELF. Эти данные загружаются в самом начале виртуального пространства памяти Linux (TODO, почему?). В минимальном мире приветствия x86-64 с двумя заголовками программ стоит 0xb0, так что символ _start приходит на 0x4000b0.