Возможно, ваш вопрос действительно Как разместить конкретную функцию перед всеми остальными в сгенерированном исполняемом файле?
Первое, что делает это, имеет значение только при определенных обстоятельствах. Исполняемый файл 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
Вы забыли опубликовать любые доказательства, а также информацию о версии или окружении, а также [mcve]. Я тестировал, он работает нормально. – Jester
Вы понимаете, что только потому, что 'main' доходит до' _start', это не точка входа, верно? Точка входа указана в поле заголовка ELF. – Jester
Вид. Мне нужно, чтобы метка _start была в начале исполняемой области. Кажется, что он отлично работает с '-O1' и' -O0'. – user2725580