目錄
- 虛擬地址空間(虛擬記憶體)佈局
- 編譯與連結
- 例子原始碼
- 看看obj檔案的組成格式
- 主要的段
- 全部的段
- 組成格式:頭資訊+段
- 一些概念和命令的總結
- 概念
- 命令
虛擬地址空間(虛擬記憶體)佈局
-
bss段節省的是檔案的空間,不是虛擬地址空間
-
指令段和資料段在程式執行起來後是不變的,不可伸縮
-
從0地址開始到0x08048000的128M地址空間,禁止訪問,比如這種操作:
char *p = NULL; ... strlen(p); // 訪問出錯
編譯與連結
下圖說明了編譯與連結的核心步驟,後面會用一個例子來說明其中的關鍵資訊
連結器,只對global 符號處理,不對local 符號處理
例子原始碼
int g_data1 = 10;
int g_data2 = 0;
int g_data3;
static int g_data4 = 11;
static int g_data5 = 0;
static int g_data6;
int main()
{
int a = 12;
int b = 0;
int c;
static int d = 13;
static int e = 0;
static int f;
return 0;
}
PS:上面的原始碼哪些是指令,哪些是資料?紅色的是資料,綠色的是指令
區域性變數、函式屬於指令
全域性變數、靜態區域性變數屬於資料
看看obj檔案的組成格式
主要的段
gcc -c main.c
得到main.o
檔案,使用objdump -h main.o
看看obj檔案的段:
VMA:
虛擬地址
LMA:
載入地址
VMA
和LMA
此時都是0,說明編譯步驟不給符號分配記憶體地址,符號解析完成後才會分配(連結時)
File off
:地址偏移
Algn
:對齊位元組
結合ELF header
、File off
和Algn
可以算出每個段在虛擬地址空間佔的大小,這裡也可以發現.bss段不佔檔案空間(虛擬地址空間需要佔,否則符號放哪裡呢)
全部的段
readelf -S main.o
可以檢視所有的段
組成格式:頭資訊+段
file main.o
檢視檔案屬性,obj檔案為可重定位的檔案,不可執行
readelf -h main.o
顯示obj檔案開始的檔案頭資訊
- 結合前面的段,加上這裡的ELF Header,可以看出obj檔案的組成格式:
一些概念和命令的總結
概念
- CPU的位數是一次效能載入的最長的整數寬度,ALU的寬度,資料匯流排的條數
- 虛擬記憶體(虛擬地址空間)的大小 =2^CPU位數