讨论-Ttext之前,先简单介绍一下工具:
readelf -h 读取ELF可执行文件头
readelf -S 查看ELF文件Section 信息
objdump -d 看目标文件汇编代码
以典型的bootloader为例,我们分析-Ttext的实际作用。
首先来看具体的两条命令
编译 $(CC) $(CFLAGS) -DKERNEL_START=$(TEXT_START) -c mbr_start.S -o $(OBJDIR)/mbr_start.o
链接 $(LD) -Ttext=0x7c00 -o $(OBJDIR)/mbr $(OBJDIR)/mbr_start.o $(OBJDIR)/mbr.o
第一行编译mbr_start.S并传入参数KERNEL_START,生成目标文件mbr_start.o;第二行,连接mbr_start.o和mbr.o生成mbr,并将程序重定向到0x7c00处。
即,-Ttext是连接时将初始地址重定向为0x7c00(若不注明此,则程序的起始地址为0)。比如,在mbr_start.S文件中函数inb()的编译完成后在mbr_start.o中的偏移地址是0x006b,则在连接时指定-Ttext=0x7c00,连接之后其地址为0x7c6b, 其他函数调用此函数时,也就会调用地址0x7c6b,而不会是0x006b。
那这个编译连接参数的意义是什么?比如bootloader, x86平台上,BIOS加载bootloader到0x7c00, 然后从0x7c00开始执行,那么你的bootloader则就需要在编译的时候指明-Ttext=0x7c00使得bootloader程序在以0x7c00为起始的地址空间内,否则程序运行时将因为地址空间紊乱无法正常运行。举例说明如下。
比如编译完,mbr_start.o, mbr.o
mbr_start.o: file format elf32-i386
Disassembly of section .text:
00000000 <_start>:
0: 31 c0 xor %eax,%eax
2: 8e d8 mov %eax,%ds
4: 31 db xor %ebx,%ebx
6: 31 c9 xor %ecx,%ecx
8: 31 d2 xor %edx,%edx
a: b8 01 e8 cd 15 mov $0x15cde801,%eax
f: 66 81 e3 ff ff and $0xffff,%bx
14: 00 00 add %al,(%eax)
...(省略)
0000005a <pm32>:
5a: bc 00 7c 00 00 mov $0x7c00,%esp
5f: 68 00 00 10 00 push $0x100000
64: e8 fc ff ff ff call 65 <pm32+0xb>
69: ff e0 jmp *%eax
0000006b <inb>:
6b: 29 c0 sub %eax,%eax
6d: 66 8b 54 24 04 mov 0x4(%esp),%dx
72: ec in (%dx),%al
73: c3 ret
...(省略)
000000b0 <gdtdscr>:
b0: 27 daa
b1: 00 88 00 00 00 00 add %cl,0x0(%eax)
...
mbr.o: file format elf32-i386
Disassembly of section .text:
00000000 <read_mbr>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 57 push %edi
4: 56 push %esi
5: 53 push