Jon*_*art 4 elf ld linker-scripts
我正在使用binutils-2.21.53.0.1-6.fc16.x86_64.
我有一个小的目标文件,hello.o只有足够的"东西"来包含所有部分的内容:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
000000000000005d 0000000000000000 AX 0 0 4
[ 2] .rela.text RELA 0000000000000000 00000808
0000000000000060 0000000000000018 15 1 8
[ 3] .data PROGBITS 0000000000000000 000000a0
0000000000000000 0000000000000000 WA 0 0 4
[ 4] .bss NOBITS 0000000000000000 000000a0
0000000000000053 0000000000000000 WA 0 0 32
[ 5] .rodata PROGBITS 0000000000000000 000000a0
000000000000000f 0000000000000000 A 0 0 1
[ 6] .data.rel.local PROGBITS 0000000000000000 000000b0
0000000000000008 0000000000000000 WA 0 0 8
[ 7] .rela.data.rel.lo RELA 0000000000000000 00000868
0000000000000018 0000000000000018 15 6 8
[ 8] .data.rel PROGBITS 0000000000000000 000000b8
0000000000000008 0000000000000000 WA 0 0 8
[ 9] .rela.data.rel RELA 0000000000000000 00000880
0000000000000018 0000000000000018 15 8 8
[10] .comment PROGBITS 0000000000000000 000000c0
000000000000002d 0000000000000001 MS 0 0 1
[11] .note.GNU-stack PROGBITS 0000000000000000 000000ed
0000000000000000 0000000000000000 0 0 1
[12] .eh_frame PROGBITS 0000000000000000 000000f0
0000000000000058 0000000000000000 A 0 0 8
[13] .rela.eh_frame RELA 0000000000000000 00000898
0000000000000030 0000000000000018 15 12 8
[14] .shstrtab STRTAB 0000000000000000 00000148
0000000000000085 0000000000000000 0 0 1
[15] .symtab SYMTAB 0000000000000000 00000610
00000000000001b0 0000000000000018 16 11 8
[16] .strtab STRTAB 0000000000000000 000007c0
0000000000000045 0000000000000000 0 0 1
Run Code Online (Sandbox Code Playgroud)
如果我使用-pie且没有链接器脚本,则结果如预期:
$ ld -pie -Map hello_pie.map -o hello_pie.elf hello.o
$ ll hello_pie.elf
-rwxrwx---. 1 jreinhart jreinhart 3453 Mar 13 23:44 hello_pie.elf
Run Code Online (Sandbox Code Playgroud)
但是,如果我包含任何类型的链接描述文件,则输出大小会爆炸:
$ cat 1.ld
SECTIONS
{
}
$ ld -T 1.ld -pie -Map hello_pie.map -o hello_pie.elf hello.o
$ ll hello_pie.elf
-rwxrwx---. 1 jreinhart jreinhart 2100070 Mar 13 23:45 hello_pie.elf
Run Code Online (Sandbox Code Playgroud)
如你所见,这个文件变得庞大.
请注意,这似乎是因为该.text部分坚持从文件中的偏移量0x200000开始:
$ readelf -l -S hello_pie.elf
There are 19 section headers, starting at offset 0x200400:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00200000 <--- Why?
000000000000005d 0000000000000000 AX 0 0 4
[ 2] .rodata PROGBITS 000000000000005d 0020005d
000000000000000f 0000000000000000 A 0 0 1
[ 3] .eh_frame PROGBITS 0000000000000070 00200070
0000000000000058 0000000000000000 A 0 0 8
[ 4] .interp PROGBITS 00000000000000c8 002000c8
000000000000000f 0000000000000000 A 0 0 1
[ 5] .dynsym DYNSYM 00000000000000d8 002000d8
0000000000000078 0000000000000018 A 6 2 8
[ 6] .dynstr STRTAB 0000000000000150 00200150
0000000000000014 0000000000000000 A 0 0 1
[ 7] .hash HASH 0000000000000168 00200168
0000000000000028 0000000000000004 A 5 0 8
[ 8] .rela.dyn RELA 0000000000000190 00200190
0000000000000078 0000000000000018 A 5 0 8
[ 9] .data.rel.local PROGBITS 0000000000000208 00200208
0000000000000008 0000000000000000 WA 0 0 8
[10] .data.rel PROGBITS 0000000000000210 00200210
0000000000000008 0000000000000000 WA 0 0 8
[11] .dynamic DYNAMIC 0000000000000218 00200218
00000000000000f0 0000000000000010 WA 6 0 8
[12] .got PROGBITS 0000000000000308 00200308
0000000000000018 0000000000000008 WA 0 0 8
[13] .got.plt PROGBITS 0000000000000320 00200320
0000000000000018 0000000000000008 WA 0 0 8
[14] .bss NOBITS 0000000000000340 00200338
0000000000000053 0000000000000000 WA 0 0 32
[15] .comment PROGBITS 0000000000000000 00200338
000000000000002c 0000000000000001 MS 0 0 1
[16] .shstrtab STRTAB 0000000000000000 00200364
000000000000009a 0000000000000000 0 0 1
[17] .symtab SYMTAB 0000000000000000 002008c0
0000000000000258 0000000000000018 18 19 8
[18] .strtab STRTAB 0000000000000000 00200b18
000000000000004e 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Elf file type is DYN (Shared object file)
Entry point 0x0
There are 5 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000200040 0x0000000000000000
0x0000000000000118 0x0000000000000118 R E 8
INTERP 0x00000000002000c8 0x00000000000000c8 0x00000000000000c8
0x000000000000000f 0x000000000000000f R 1
[Requesting program interpreter: /lib/ld64.so.1]
LOAD --> 0x0000000000200000 0x0000000000000000 0x0000000000000000
0x0000000000000338 0x0000000000000393 RWE 200000
DYNAMIC 0x0000000000200218 0x0000000000000218 0x0000000000000218
0x00000000000000f0 0x00000000000000f0 RW 8
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 8
Run Code Online (Sandbox Code Playgroud)
无论我的链接器脚本的内容如何,都会发生这种情况.有什么想法发生了什么?
在学习链接器脚本时,我今天遇到了同样的问题.SIZEOF_HEADERS是解决它的灵丹妙药.这是我构建我正在链接的对象的简单源文件:
.section .text
.global _start
_start:
mov $1, %eax
mov $8, %ebx
int $0x80
Run Code Online (Sandbox Code Playgroud)
使用以下链接描述文件,我得到一个2+ MB的可执行文件:
SECTIONS
{
. = 0x400000;
.text : { *(.text) }
}
Run Code Online (Sandbox Code Playgroud)
如果我添加+ SIZEOF_HEADERS,如下所示,我得到一个568字节的可执行文件:
SECTIONS
{
. = 0x400000 + SIZEOF_HEADERS;
.text : { *(.text) }
}
Run Code Online (Sandbox Code Playgroud)
根据LD文档,此函数返回输出文件头的大小.手动设置偏移量以包括标头大小也会产生568字节的可执行文件:
SECTIONS
{
. = 0x400078;
.text : { *(.text) }
}
Run Code Online (Sandbox Code Playgroud)
如果我进一步向下移动.text,可执行文件就会开始扩展.以下产生一个65984字节的可执行文件:
SECTIONS
{
. = 0x410000;
.text : { *(.text) }
}
Run Code Online (Sandbox Code Playgroud)
所以基本上,据我所知,看来:
默认情况下,ld页面对齐输入节.由于您的内核强制执行超级页面(页面为2MB = 0x200000字节),因此您的.text部分将在偏移量0x200000处对齐.这似乎是一个错误,ld因为它应该使用偏移量0x0000000(请参阅下面的编辑以获得可能的解释)
为了防止这种创建更大文件的对齐,您可以使用--nmagic标志ld来防止它对.text部分进行页面对齐,尽管它有副作用(它还禁用链接到共享库).但要小心将其他部分(.data,.rodata...)与2M页面对齐,因为它们不能与.text位于同一页面中,因为所有这些部分都需要不同的访问位.
编辑:考虑一下,我们都期望访问虚拟地址0x00000000来生成异常(segfault).为此,我看到两种可能性:要么内核映射没有访问权限的页面(r/w/x),要么(更有可能)它根本不映射任何内容(没有页面映射=> segfault),链接器必须知道这个......这可以解释为什么ld会跳过地址为零的第一页.这是TBC.
| 归档时间: |
|
| 查看次数: |
2775 次 |
| 最近记录: |