我有一个静态链接的二进制文件,我正在尝试缩小它的大小。我不明白为什么它会发出动态部分,而且我认为它不应该这样做。
我认为 -fpic -fPIC 应该摆脱所有重定位,但还剩下一些。 start.s 包含
call main
但它位于同一段内,因此也不应该在那里重定位。
我的Makefile:
hello: start.s hello.c Makefile
gcc -o hello -nostartfiles -nostdlib -Wl,--no-dynamic-linker -fpic -fPIC -fno-asynchronous-unwind-tables -s start.s hello.c
strip -R .comment hello
objdump -x
的结果
hello: file format elf64-x86-64
hello
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000001000
Program Header:
LOAD off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**12
filesz 0x0000000000000261 memsz 0x0000000000000261 flags r--
LOAD off 0x0000000000001000 vaddr 0x0000000000001000 paddr 0x0000000000001000 align 2**12
filesz 0x00000000000000bb memsz 0x00000000000000bb flags r-x
LOAD off 0x0000000000002000 vaddr 0x0000000000002000 paddr 0x0000000000002000 align 2**12
filesz 0x0000000000000010 memsz 0x0000000000000010 flags r--
LOAD off 0x0000000000002f30 vaddr 0x0000000000003f30 paddr 0x0000000000003f30 align 2**12
filesz 0x00000000000000d0 memsz 0x00000000000000d0 flags rw-
DYNAMIC off 0x0000000000002f30 vaddr 0x0000000000003f30 paddr 0x0000000000003f30 align 2**3
filesz 0x00000000000000d0 memsz 0x00000000000000d0 flags rw-
NOTE off 0x0000000000000200 vaddr 0x0000000000000200 paddr 0x0000000000000200 align 2**2
filesz 0x0000000000000024 memsz 0x0000000000000024 flags r--
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
RELRO off 0x0000000000002f30 vaddr 0x0000000000003f30 paddr 0x0000000000003f30 align 2**0
filesz 0x00000000000000d0 memsz 0x00000000000000d0 flags r--
Dynamic Section:
GNU_HASH 0x0000000000000228
STRTAB 0x0000000000000260
SYMTAB 0x0000000000000248
STRSZ 0x0000000000000001
SYMENT 0x0000000000000018
DEBUG 0x0000000000000000
FLAGS_1 0x0000000008000000
Sections:
Idx Name Size VMA LMA File off Algn
0 .note.gnu.build-id 00000024 0000000000000200 0000000000000200 00000200 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .gnu.hash 0000001c 0000000000000228 0000000000000228 00000228 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .dynsym 00000018 0000000000000248 0000000000000248 00000248 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynstr 00000001 0000000000000260 0000000000000260 00000260 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .text 000000bb 0000000000001000 0000000000001000 00001000 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
5 .rodata 0000000f 0000000000002000 0000000000002000 00002000 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .eh_frame 00000000 0000000000002010 0000000000002010 00002010 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .dynamic 000000d0 0000000000003f30 0000000000003f30 00002f30 2**3
CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
no symbols
经过几个小时的研究,我得到了一个可行的答案。这个
ld
脚本有效。
SECTIONS {
# . = 0x10000;
. = 0;
.text : { *(.text) *(.rodata) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.data : ALIGN(4096) { *(.data) }
.bss : ALIGN(4096) { *(.bss) }
/DISCARD/ : { *(.dynsym) *(.dynstr) *(.dynamic) *(.gnu.hash) }
/DISCARD/ : { *(.comment) }
}
构建命令是
gcc -o hello -Wl,-T,merge.ld -Wl,--no-dynamic-linker -fpic -fno-asynchronous-unwind-tables -pie -nostartfiles -nostdlib -s start.s hello.c
如果全局变量中有任何初始化的指针,这将会爆炸。为什么?因为我们是可搬迁的,而且我们没有任何搬迁,所以实际上没有办法表达这一点。
const char *message = "Hello, World";
是毒药。
const char message[] = "Hello, World";
还好。
如果您需要初始化全局指针才能工作;通过将
. = 0;
更改为 . = 0x10000;
行并从构建指令中删除 -fpic -fpie
来放弃 ASLR。