2017-02-17 5 views
0

У меня есть файл сборки с меткой _start как первое, что есть в сегменте .text. Я бы хотел, чтобы этот ярлык был точкой входа моего приложения.Изменить точку входа с помощью gnu linker

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

Я использую компоновщик GNU и попробовал флаг -e _start, а также изменил порядок ввода файлов. До тех пор, пока существует функция main, она станет точкой входа. Если я переименую функцию main, она отлично работает, и моя метка _start станет точкой входа.

EDIT: Похоже, что это из-за -O2 флаг для компилятора.

as.s

.text 
.global _start 
_start: 
jmp main 

main.c

int main(){ 
    return 0; 
} 

Вкомпилировать

gcc -O2 -c as.s -o as.o 
gcc -O2 -c main.c -o main.o 
ld -e _start as.o main.o -o test 

Выход

00000000004000b0 <main>: 
    4000b0: 31 c0     xor %eax,%eax 
    4000b2: c3      retq 

00000000004000b3 <_start>: 
    4000b3: e9 f8 ff ff ff   jmpq 4000b0 <main> 

Любые идеи?

+3

Вы забыли опубликовать любые доказательства, а также информацию о версии или окружении, а также [mcve]. Я тестировал, он работает нормально. – Jester

+0

Вы понимаете, что только потому, что 'main' доходит до' _start', это не точка входа, верно? Точка входа указана в поле заголовка ELF. – Jester

+0

Вид. Мне нужно, чтобы метка _start была в начале исполняемой области. Кажется, что он отлично работает с '-O1' и' -O0'. – user2725580

ответ

4

Возможно, ваш вопрос действительно Как разместить конкретную функцию перед всеми остальными в сгенерированном исполняемом файле?

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

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


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

Один из способов поставить функцию в ELF исполняемый файл должен поместить его в свой раздел, а затем создать скрипт компоновщика, чтобы сначала разместить этот раздел.Пример компоновщик скрипт link.ld, который должен работать с C будет:

/*OUTPUT_FORMAT("elf32-i386");*/ 
OUTPUT_FORMAT("elf64-x86-64"); 

ENTRY(_start); 

SECTIONS 
{ 
    /* This should be your memory offset (VMA) where the code and data 
    * will be loaded. In Linux this is 0x400000, multiboot loader is 
    * 0x100000 etc */ 
    . = 0x400000; 

    /* Place special section .text.prologue before everything else */ 
    .text : { 
     *(.text.prologue); 
     *(.text*); 
    } 

    /* Output the data sections */ 
    .data : { 
     *(.data*); 
    } 

    .rodata : { 
     *(.rodata*); 
    } 

    /* The BSS section for uniitialized data */ 
    .bss : { 
     __bss_start = .; 
     *(COMMON); 
     *(.bss); 
     . = ALIGN(4); 
     __bss_end = .; 
    } 

    /* Size of the BSS section in case it is needed */ 
    __bss_size = ((__bss_end)-(__bss_start)); 

    /* Remove the note that may be placed before the code by LD */ 
    /DISCARD/ : { 
     *(.note.gnu.build-id); 
    } 
} 

Этот сценарий явно помещает все, что в разделе .text.prologue перед любым другим кодом. Нам просто нужно разместить _start в этом разделе. Файл as.s может быть изменен, чтобы сделать это:

.global _start 

# Start a special section called .text.prologue making it 
# allocatable and executable 
.section .text.prologue, "ax" 

_start: 
jmp main 

.text 
# All other regular code in the normal .text section 

Вы бы собрать, собрать и соединить их так:

gcc -O2 -c main.c -o main.o 
gcc -O2 -c as.s -o as.o 
ld -Tlink.ld main.o as.o -o test 

objdump -D test должен показать функцию _start перед тем main:

test:  file format elf32-i386 


Disassembly of section .text: 

00400000 <_start>: 
    400000:  e9 0b 00 00 00   jmp 400010 <main> 
    400005:  66 2e 0f 1f 84 00 00 nopw %cs:0x0(%eax,%eax,1) 
    40000c:  00 00 00 
    40000f:  90      nop 

00400010 <main>: 
    400010:  31 c0     xor %eax,%eax 
    400012:  c3      ret 
Смежные вопросы