链接器作为一个程序可以精细的控制其的连接过程,学习过段的合并过程,在学习一下如何控制,以写一个比较小的玩具程序作为学习主线。

前置

系统调用号

本次实验用的write

root@L:/usr/include/x86_64-linux-gnu/asm# cat unistd_64.h
#ifndef _ASM_UNISTD_64_H
#define _ASM_UNISTD_64_H

#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3

demo

因为程序结束后会ret到非法地址,我也不想去给他写exit了,知道怎么会是就行了

char* str = "Hello world!\n\t";

void print() {
__asm__(
"movq $13,%rdx\n\t"
"movq $1,%rdi\n\t"
"movq (str),%rsi\n\t"
"movq $1,%rax\n\t"
"syscall\n\t"
);
}

void main() {
while(1)
print();

}
root@L:/home/l/c++# gcc -nostdlib -fno-exceptions -fno-unwind-tables -fno-stack-protector -fno-common -c minihello.c -o min.o
root@L:/home/l/c++# ld -static -e main -o min min.o
root@L:/home/l/c++# ./min
Hello world!
Segmentation fault
root@L:/home/l/c++# ./minds
Hello world!
Segmentation fault

链接脚本

ENTRY(main)
SECTIONS
{
mintext : {*(.text) *(.data) *(.rodata)}
/DISCARD/ : {*(.comment) *(.strtab)}
}

差异对比

可以看出合并之后少了好几个段

root@L:/home/l/c++# readelf -S minds
There are 8 section headers, starting at offset 0x11b8:

Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .note.gnu.pr[...] NOTE 0000000000000000 00001000
0000000000000020 0000000000000000 A 0 0 8
[ 2] .eh_frame PROGBITS 0000000000000020 00001020
0000000000000058 0000000000000000 A 0 0 8
[ 3] mintext PROGBITS 0000000000000078 00001078
000000000000004e 0000000000000000 WAX 0 0 1
[ 4] .data.rel.local PROGBITS 00000000000000c8 000010c8
0000000000000008 0000000000000000 WA 0 0 8
[ 5] .symtab SYMTAB 0000000000000000 000010d0
0000000000000078 0000000000000018 6 2 8
[ 6] .strtab STRTAB 0000000000000000 00001148
000000000000001c 0000000000000000 0 0 1
[ 7] .shstrtab STRTAB 0000000000000000 00001164
0000000000000050 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), l (large), p (processor specific)
root@L:/home/l/c++# readelf -S min.o
There are 16 section headers, starting at offset 0x310:

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
000000000000003f 0000000000000000 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 00000208
0000000000000030 0000000000000018 I 13 1 8
[ 3] .data PROGBITS 0000000000000000 0000007f
0000000000000000 0000000000000000 WA 0 0 1
[ 4] .bss NOBITS 0000000000000000 0000007f
0000000000000000 0000000000000000 WA 0 0 1
[ 5] .rodata PROGBITS 0000000000000000 0000007f
000000000000000f 0000000000000000 A 0 0 1
[ 6] .data.rel.local PROGBITS 0000000000000000 00000090
0000000000000008 0000000000000000 WA 0 0 8
[ 7] .rela.data.r[...] RELA 0000000000000000 00000238
0000000000000018 0000000000000018 I 13 6 8
[ 8] .comment PROGBITS 0000000000000000 00000098
000000000000002c 0000000000000001 MS 0 0 1
[ 9] .note.GNU-stack PROGBITS 0000000000000000 000000c4
0000000000000000 0000000000000000 0 0 1
[10] .note.gnu.pr[...] NOTE 0000000000000000 000000c8
0000000000000020 0000000000000000 A 0 0 8
[11] .eh_frame PROGBITS 0000000000000000 000000e8
0000000000000058 0000000000000000 A 0 0 8
[12] .rela.eh_frame RELA 0000000000000000 00000250
0000000000000030 0000000000000018 I 13 11 8
[13] .symtab SYMTAB 0000000000000000 00000140
00000000000000a8 0000000000000018 14 4 8
[14] .strtab STRTAB 0000000000000000 000001e8
000000000000001c 0000000000000000 0 0 1
[15] .shstrtab STRTAB 0000000000000000 00000280
0000000000000089 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), l (large), p (processor specific)