函数地址查找
1.准备test.m文件
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.查看代码段。终端使用如下命令:
objdump --macho -d test
4.查看.o文件的代码段:终端使用如下命令:
//将test.m生成目标文件test
clang -c test.m -o test.o
objdump --macho -d test.o
- 编译是按照文件声明的顺序编译的,即:_text、_text1、_main
e8固定机器码,代表callq指令C框函数_text地址等于A框偏移量加B框偏移量_text1函数的偏移量都是0,但是往上面看能够看到,_test1偏移量是10,所以,当前函数调用的地址并不是真实的地址。链接的时候还会分配虚拟内存地址,链接的时候要告诉编译器将真实的地址拿过来覆盖这些占位的00 00 00 00,_test1放到重定位符号表里
5.查看需要重定位的符号:
objdump --macho --reloc test.o
_test1的地址是49,对比就能找到占位地址位置
在编译成目标文件的时候,没有分配真实的虚拟内存地址,用了临时变量占位,把需要重新定位的函数放到重定位符号表里
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
globle变量地址查找
c7 05 是movl指令
21的十进制就是15
21地址就是0x100003f99+0x4067 就是 0x100008000
查看macho所有内容
objdump --macho -s test
红框后面Oa就是代码中的
int global = 10;