使用gnu链接器更改入口点

我有一个带有_start标签的程序集文件,作为.text段中的第一个东西。 我希望这个标签成为我申请的切入点。

每当我将此文件与另一个具有main函数的文件一起传递时,无论如何,该main函数最终都成为我的应用程序的入口点。

我正在使用GNU链接器并尝试了-e _start标志,同时更改了输入文件顺序。 只要存在一个main函数,它就会成为入口点。如果我重命名main函数,它工作正常,我的_start标签成为入口点。

编辑:似乎是因为编译器的-O2标志。

屁股

 .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 : 4000b0: 31 c0 xor %eax,%eax 4000b2: c3 retq 00000000004000b3 : 4000b3: e9 f8 ff ff ff jmpq 4000b0  

有任何想法吗?

看来您的问题确实是如何在生成的可执行文件中将所有其他函数放在特定函数之前?

首先,这样做只在某些情况下才有价值。 ELF可执行文件具有在ELF头中编码的入口点。 可执行文件中入口点的放置不相关。

一个特殊情况是非多引导兼容内核,其中自定义引导加载程序加载由GCC生成并转换为二进制输出的内核。 查看您的问题历史记录表明,引导加载程序/内核开发可能符合您的要求。


使用GCC时,您不能假设生成的代码将按您想要的顺序排列。 正如您所发现的那样,选项(如优化)可能会相互重新排序函数或完全消除一些函数。

将函数放在ELF可执行文件中的一种方法是将其放入其自己的部分,然后创建一个链接描述文件以首先定位该部分。 应该与C一起使用的示例链接描述文件link.ld将是:

 /*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应该在main之前显示函数_start

 test: file format elf32-i386 Disassembly of section .text: 00400000 <_start>: 400000: e9 0b 00 00 00 jmp 400010 
400005: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%eax,%eax,1) 40000c: 00 00 00 40000f: 90 nop 00400010
: 400010: 31 c0 xor %eax,%eax 400012: c3 ret