1.準備test.m
文件markdown
void test(){
}
void test1(){
}
int global = 10;
int main(){
global = 21;
global = 20;
test();
test1();
return 0;
}
複製代碼
2.生成可執行文件。終端使用以下命令:函數
//將test.m生成可執行文件test
clang test.m -o test
複製代碼
3.查看代碼段。終端使用以下命令:ui
objdump --macho -d test
複製代碼
4.查看.o文件的代碼段:終端使用以下命令:spa
//將test.m生成目標文件test
clang -c test.m -o test.o
複製代碼
objdump --macho -d test.o
複製代碼
e8
固定機器碼,表明callq
指令C
框函數_text
地址等於A
框偏移量加B
框偏移量_text1
函數的偏移量都是0,可是往上面看可以看到,_test1
偏移量是10,因此,當前函數調用的地址並非真實的地址。連接的時候還會分配虛擬內存地址,連接的時候要告訴編譯器將真實的地址拿過來覆蓋這些佔位的00 00 00 00
,_test1
放到重定位符號表裏5.查看須要重定位的符號:3d
objdump --macho --reloc test.o
複製代碼
_test1
的地址是49,對比就能找到佔位地址位置code
在編譯成目標文件的時候,沒有分配真實的虛擬內存地址,用了臨時變量佔位,把須要從新定位的函數放到重定位符號表裏orm
6.生成可執行文件並查看:圖片
clang test.m -o test
複製代碼
objdump --macho -d test
複製代碼
iOS是小端模式,這裏最高位就是ff,因此爲負,ff是補碼,須要變成原碼,全部的1取反後爲0,因此這裏直接看b8。內存
b8目前是補碼,求原碼編譯器
b8(補碼)二進制表示:10111000
反碼(補碼-1): 10110111
原碼(反碼取反): 01001000
當前算出的原碼16進制就是0x48
由於高位是ff,爲負 _test
地址就等於0x100003FA8
加上負的0x48
等於0x100003F60
c7 05 是movl指令
21的十進制就是15
21地址就是0x100003f99
+0x4067
就是 0x100008000
查看macho全部內容
objdump --macho -s test
複製代碼
紅框後面Oa就是代碼中的
int global = 10;