Mach-O Inside: BSS Section
1 BSS 起源
BSS( Block Started by Symbol)這個詞最初是 UA-SAP 彙編器( United Aircraft Symbolic Assembly Program)中的一個偽指令,用於為符號預留一塊記憶體空間。該彙編器由美國聯合航空公司於 20 世紀 50 年代中期為 IBM 704 大型機所開發。
後來,BSS 這個詞被作為關鍵字引入了 IBM 709 和 7090/94 機型上的標準彙編器 FAP( Fortran Assembly Program),用於定義符號並且為該符號預留給定數量的未初始化空間。
裡面有 Unix 和 C 語言之父 Dennis Rithcie 對 BSS 這個詞由來的解釋。
2 Macho-O 裡的 __bss
一般對 BSS Section 的介紹會說裡面存放的是 未初始化的全域性變數和 未初始化的區域性靜態變數,但是實際對 Mach-O 目標檔案(.o 檔案)進行檢視,發現情況並不是這樣。
假設有
a.h
和
a.m
檔案,
a.h
裡面宣告瞭一個函式
test()
,程式碼如下:
void test();
a.m
裡面定義了 2 個全域性變數和 2 個靜態變數:
global_init_var
全域性變數初始化為 84,
global_uninit_var
全域性變數未進行初始化。
static_init_var
靜態變數初始化為 85,
static_uninit_var
靜態變數未進行初始化。
// 1. 初始化全域性變數int global_init_var = 84;// 2. 未初始化全域性變數int global_uninit_var;void test(void) {// 3. 初始化靜態變數static int static_init_var = 85;// 4. 未初始化靜態變數static int static_uninit_var;// 5. 列印所有變數之和printf("%d", global_init_var + global_uninit_var + static_init_var + static_uninit_var);}
建立一個 iOS 工程,將
a.h
和
a.m
檔案拖入到工程,並且進行編譯。編譯成功之後在工程 DevivedData 目錄下找到
a.o
檔案,並將這個檔案拖入到 MachOView 工具中進行檢視:
上圖右側
Size
欄位代表 __bss Section 在虛擬記憶體中所佔用的大小,其值為 4 位元組,剛好是一個
int
型別的大小,表明為初始化的全域性變數
global_uninit_var
和未初始化的靜態變數
static_uninit_var
只有一個位於 __bss Section 中。
offset
欄位代表在 Macho-O 目標檔案 a.o 中,__bss Section 距離 a.0 目標檔案的起始位置偏移量為 0,而在目標檔案 a.o 的起始位置是檔案頭 Header,檔案頭和 __bss Section 不可能重合,所以這表明 __bss Section 在 Mach-O 檔案裡面不會佔用任何磁碟空間,只有在虛擬記憶體中,才會為 __bss Section 分配指定的空間。
flags
欄位值為
S_ZEROFILL
,這表明當在虛擬記憶體裡為 __bss Section 分配空間時,這個空間會全部被初始化為 0。
透過檢視
a.o
的符號表,可以發現未初始化的全域性
global_uninit_var
變數位於 __DATA Segment 的 __common Section 中:
只有未初始化的區域性靜態變數
static_uninit_var
位於 __DATA Segment 的 __bss Section:
同樣可以透過 MachOView 檢視 __data Section Header,可以看到這個 Section 在虛擬記憶體中佔用的大小為 8 個位元組,剛好是 2 個
int
型別的大小。同時,這個 Section 位於距離 Mach-O 目標檔案 a.o 起始位置 1944 位元組處:
使用 MachOView 檢視這個 Section 如下:
上圖右側
pFile
欄位代表當前 Section 在 Mach-O 檔案中的偏移量,其值是 16 進位制 0x798,換算成 10 進位制剛好是 1944,整好複合 __data Section Header 中的偏移量
offset
。
在
Data LO
欄位儲存了 8 個位元組的資料,每 4 個位元組代表一個整數。由於 ARM 位元組序列是小端在前(Little-Endian),這兩個整數的值應該是 0x00000054 和 0x00000055,換算成 10 進位制就是 84 和 85,正好是全域性變數
global_init_var
和
static_init_var
的值。
3 Mach-O 裡的 __common
上面提到未初始化的全域性變數
global_uninit_var
並不位於 __bss Section,而是位於 __common Section。
透過 MachOView 檢視 __common Section Header 如下圖所示:
上圖右側
size
欄位、
offset
欄位與
S_ZEROFILL
代表的意義與 __bss Section Header 中的一樣,從
offset
的值為 0 可知,__common Section 在 Macho-O 目標檔案 a.o 中也不佔用空間,只會在虛擬記憶體中為其分配大小為 4 位元組的空間,並且全部初始化為 0。
為什麼要把未初始化的全域性變數和未初始化的靜態變數分開放置?
這和具體的語言與編譯器的實現有關,有的編譯器會將未初始化的全域性變數和未初始化的靜態變數一起放在 __bss Section,有的編譯器會像這樣分開放置。
4 初始化值為 0
如果全域性變數和靜態變數初始化值為 0,效果和未初始化一樣。因為對於未初始化的全域性變數和靜態變數,當載入到虛擬記憶體之後,也會被初始化為 0,所以會有這樣的最佳化。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70034822/viewspace-2991665/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Mach-O Inside: 命令列工具集 otool objdump od 與 dwarfdumpMacIDE命令列OBJ
- Mach-OMac
- Mach-O、dyldMac
- Mach-O 探究Mac
- 資料段data、bss、rodata
- oracle全文索引之SECTION GROUP_6_PATH_SECTION_GROUPOracle索引
- oracle全文索引之SECTION GROUP_5_AUTO_SECTION_GROUPOracle索引
- oracle全文索引之SECTION GROUP_4_XML_SECTION_GROUPOracle索引XML
- oracle全文索引之SECTION GROUP_3_HTML_SECTION_GROUPOracle索引HTML
- oracle全文索引之SECTION GROUP_2_BASIC_SECTION_GROUPOracle索引
- oracle全文索引之SECTION GROUP_1_NULL_SECTION_GROUPOracle索引Null
- 分析Mach-O檔案Mac
- 解析Mach-o檔案Mac
- dyld 載入 Mach-OMac
- HTML <section> 標籤HTML
- 程式段.text, data (initialized), bss, stack, heapZed
- iOS 逆向 - Mach-O檔案iOSMac
- 探祕 Mach-O 檔案Mac
- 趣探 Mach-O:FishHook 解析MacHook
- <section>與<article> 區別
- Oracle AWR Top SQL sectionOracleSQL
- Wi-Fi BSS和ESS的區別
- Mach-O檔案周邊二三事Mac
- Mach-O 可執行檔案Mac
- 趣探 Mach-O:符號解析Mac符號
- mach-o 檔案分析(解析類)Mac
- artice與section的區別
- 【Basic Abstract Algebra】Exercises of Section 1.1
- 【Basic Abstract Algebra】Exercises for Section 1.2
- Full postback triggered by LinkButton inside GridView inside UpdatePanelIDEView
- 趣探 Mach-O:檔案格式分析Mac
- GCD Inside: GCD 宏GCIDE
- 什麼是BSS/OSS,及區別和聯絡
- Wireless LAN: WAP, BSS, BSSID, SSID, ESS, & ESSID
- Chapter1 入門/Section 1.2APT
- PE教程5: Section Table(節表)
- A Proof of Golden Section of Fibonacci SequenceGo
- iOS 如何獲取 Mach-O 的 UUIDiOSMacUI