1. 程式人生 > >C程式中各個段的含義

C程式中各個段的含義

首先應該知道幾個檢視段資訊的指令:
readelf -S file 檢視各個段的名稱,地址,大小等資訊
objdump -s file 檢視各個段的二進位制和字元格式內容
hexdump -C file 檢視整個二進位制檔案的二進位制和字元格式內容
(1).text 程式的正文段,一般為本檔案中的函式指令
(2).data 程式的資料段,一般靜態變數和初始化的全域性變數定義在此
(3).bss 也是程式的資料段,一般包括未初始化的全域性變數
(4).interp 此程式在載入時所需要使用的動態聯結器的位置

Contents of section .interp:
 400200
2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux- 400210 7838362d 36342e73 6f2e3200 x86-64.so.2.

說明當前程式需要載入時,使用到/lib64/ld-linux-x86-64.so.2這個動態連結器
(5).rodata 只讀資料,比如說C++中的const變數,字串常量,比如說程式中有這麼一段:

printf("in main.c a=%d\n", a);
printf("in main.c &a=%p\n", &a);

對應.rodata的內容:

Contents of
section .rodata: 4007a0 01000200 696e206d 61696e2e 6320613d ....in main.c a= 4007b0 25640a00 696e206d 61696e2e 63202661 %d..in main.c &a 4007c0 3d25700a 00 =%p..

(6).symtab 符號表資訊(readelf -s file),可以看出各個符號的地址
(7).strtab 字串表資訊,一般和符號表中符號對應的字串對應
(8).rela.text 一般中間物件檔案會有這個段,因為text段引用了其他外部函式
(9).got 用於動態連結,儲存程式碼段中引用動態連結庫中資料的地址,一般在執行時確定
(10).got.plt 類似於.got,儲存程式碼段中引用動態連結庫中函式的地址,一般在執行時確定
(11).plt 用於動態連結時的延遲繫結,執行時,當遇到動態連結庫中的函式或資料時,會跳到這個段內,用於解析地址
(12).rela.dyn 用於檢視.got段和資料段(一般是.bss)需要修正的符號
(13).rela.plt 用於檢視需要修正.got.plt中的資料
針對(12)(13)舉個例子:
有兩個檔案a.c b.c,a.c編譯成動態連結庫,b.c為主程式:

//a.c
int a = 2;
void foo(void)
{
    a++;
    return;
}
//b.c
#include <stdio.h>
extern int a;
extern void foo(void);
int main(void)
{
    a = a+1;
    foo();
    return 0;
}

按上面的要求進行編譯,分別檢視a.so和b的。rela.dyn和rela.plt內容

$ readelf -r a.so
Relocation section '.rela.dyn' at offset 0x3e0 contains 9 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000002008b0  000500000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
0000002008b8  000800000006 R_X86_64_GLOB_DAT 0000000000200900 a + 0
$ readelf -r b
Relocation section '.rela.dyn' at offset 0x4b0 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600a00  000500000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000600a40  000800000005 R_X86_64_COPY     0000000000600a40 a + 0

Relocation section '.rela.plt' at offset 0x4e0 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600a20  000400000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main + 0
000000600a28  000600000007 R_X86_64_JUMP_SLO 0000000000000000 foo + 0

從上面的資訊可以看出,對於a.so變數a位於.got段,對於b來說,變數a也需要重定向,位於.bss段,在.rela.dyn中說明此符號需要重定位,並且b引用了foo這個動態連結庫函式,在.rela.plt中給出資訊需要在.got.plt中重定位。
(14).dynsym段,類似於.symtab,也是一個符號表,但是這個符號表只記錄與動態連結有關的符號
(15).dynstr段,類似於.strtab,記錄動態連結符號的字串表
(16).hash段,由於動態連結的時候需要快速查詢,因此使用了一個雜湊表,用來記錄符號的地址。
(17).dynamic 是和記錄動態連結屬性的一些資訊,比如說:動態連結重定位表的位置,.got的位置,.got.plt的位置等。