最近在看《CSAPP》這本神書,其中看到了第七章鏈接中的可重定位目標文件,自己動手在ubuntu16.04上試了一試,發現有很多都做了一些改動,在此記錄
1.源程序
main.c
static int a = 1;
int buf[2] = {1,2};
void swap();
int main()
{
a = 2;
swap();
return 0;
}
swap.c
extern int buf[];
int *p0 = &buf[0];
static int* p1;
static int p3 = 1;
void swap()
{
int temp;
p1 = &buf[1];
temp = *p0;
*p0 = *p1;
*p1 = temp;
}
我現在要看的就是代碼中的每個符號定義以及引用在經過編譯彙編後分別位於.o文件的哪個節中
2.編譯與彙編
分別執行
gcc -c main.c
與
gcc -c swap.c
得到main.o與swap.o
3.以swap.o爲例,查看各個節
首先 ,ELF文件的結構
Section
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 00003c 00 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 000258 000090 18 I 11 1 8
[ 3] .data PROGBITS 0000000000000000 000080 00000c 00 WA 0 0 8
[ 4] .rela.data RELA 0000000000000000 0002e8 000018 18 I 11 3 8
[ 5] .bss NOBITS 0000000000000000 000090 000008 00 WA 0 0 8
[ 6] .comment PROGBITS 0000000000000000 000090 000036 01 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 0000000000000000 0000c6 000000 00 0 0 1
[ 8] .eh_frame PROGBITS 0000000000000000 0000c8 000038 00 A 0 0 8
[ 9] .rela.eh_frame RELA 0000000000000000 000300 000018 18 I 11 8 8
[10] .shstrtab STRTAB 0000000000000000 000318 00005e 00 0 0 1
[11] .symtab SYMTAB 0000000000000000 000100 000138 18 12 10 8
[12] .strtab STRTAB 0000000000000000 000238 00001a 00 0 0 1
查看符號表
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 swap.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l O .bss 0000000000000008 p1
0000000000000008 l O .data 0000000000000004 p3
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 g O .data 0000000000000008 p0
0000000000000000 *UND* 0000000000000000 buf
0000000000000000 g F .text 000000000000003c swap
可以看到,buf由於是外部變量在這裏僅僅是一個重定位項(這一點與CSAPP給的課後題目答案非常不一樣,CSAPP給出的是buf在.data節這是不對的),p0,p3由於顯示初始化了所以在.data節
同時, readelf -a swap.o可以得到重定位節中的相關信息
重定位節 '.rela.text' 位於偏移量 0x258 含有 6 個條目:
偏移量 信息 類型 符號值 符號名稱 + 加數
000000000007 000400000002 R_X86_64_PC32 0000000000000000 .bss - 8
00000000000b 000b0000000b R_X86_64_32S 0000000000000000 buf + 4
000000000012 000a00000002 R_X86_64_PC32 0000000000000000 p0 - 4
00000000001e 000a00000002 R_X86_64_PC32 0000000000000000 p0 - 4
000000000025 000400000002 R_X86_64_PC32 0000000000000000 .bss - 4
000000000030 000400000002 R_X86_64_PC32 0000000000000000 .bss - 4
重定位節 '.rela.data' 位於偏移量 0x2e8 含有 1 個條目:
偏移量 信息 類型 符號值 符號名稱 + 加數
000000000000 000b00000001 R_X86_64_64 0000000000000000 buf + 0
重定位節 '.rela.eh_frame' 位於偏移量 0x300 含有 1 個條目:
偏移量 信息 類型 符號值 符號名稱 + 加數
000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0
swap.c中與外部符號有關的部分:
extern int buf[];
int *p0 = &buf[0];
p0與buf需要在鏈接的時候進行重定位