我有一个_start
标签的汇编文件作为.text
细分中的第一件事。我希望这个标签成为我申请的切入点。
每当我将此文件与另一个具有名为main
的函数的文件一起传递时,无论如何,main
函数最终都会成为我的应用程序的入口点。
我正在使用GNU链接器并尝试了-e _start
标志,同时更改了输入文件顺序。只要存在main
函数,它就会成为入口点。如果我重命名main
函数,它工作正常,我的_start
标签成为入口点。
编辑:似乎是因为编译器的-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>
有什么想法吗?
答案 0 :(得分:5)
看来您的问题确实是如何在生成的可执行文件中将所有其他函数放在特定函数之前?
首先,这样做只在某些情况下有价值。 ELF 可执行文件的入口点编码在 ELF 标头中。可执行文件中的入口点的放置是不相关的。
一个特殊情况是非兼容mulitboot的内核,其中自定义引导加载程序加载由 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
应在_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