基本含義
__builtin_return_address(0)返回當前函數(shù)的返回地址
__builtin_return_address(1)返回當前函數(shù)的調(diào)用函數(shù)的返回地址
__builtin_return_address(2)返回當前函數(shù)的調(diào)用函數(shù)的調(diào)用函數(shù)的返回地址
編譯出來的實際效果
void tt3(){
LOGD("tt3 called %p",__builtin_return_address(0));
LOGD("tt3 called %p",__builtin_return_address(1));
LOGD("tt3 called %p",__builtin_return_address(2));
}
void tt2(){
LOGD("tt2 called %p",__builtin_return_address(0));
LOGD("tt2 called %p",__builtin_return_address(1));
tt3();
}
void tt1(){
LOGD("tt1 called 0 %p",__builtin_return_address(0));
tt2();
}
由此可見就是使用 FP 串聯(lián)了整個函數(shù)調(diào)用堆棧,上述的 函數(shù)(__builtin_return_address) 也就是通過串聯(lián)起來的 [FP,#0x4] 操作完成了對上一級 LR 的查找
由此可以可以配合 dobby 對函數(shù)hook并打印出 lr 調(diào)用鏈
int level=4;
u_long lr0,lr1,lr2,lr3,lr4;
[&]()->void {
// 調(diào)用這個 registerLR 本身也會觸發(fā)一次函數(shù)調(diào)用 會有一個lr,故從1開始
switch (level) {
case 1:
lr0 = reinterpret_cast<u_long>(__builtin_return_address(1));
LOGD("LR -> %p",(void*)(lr0-soAddr));
break;
case 2:
lr1 = reinterpret_cast<u_long>(__builtin_return_address(1));
lr0 = reinterpret_cast<u_long>(__builtin_return_address(2));
LOGD("LR -> %p %p",(void*)(lr0-soAddr),(void*)(lr1-soAddr));
break;
case 3:
lr2 = reinterpret_cast<u_long>(__builtin_return_address(1));
lr1 = reinterpret_cast<u_long>(__builtin_return_address(2));
lr0 = reinterpret_cast<u_long>(__builtin_return_address(3));
LOGD("LR -> %p %p %p",(void*)(lr0-soAddr),(void*)(lr1-soAddr),(void*)(lr2-soAddr));
break;
case 4:
lr3 = reinterpret_cast<u_long>(__builtin_return_address(1));
lr2 = reinterpret_cast<u_long>(__builtin_return_address(2));
lr1 = reinterpret_cast<u_long>(__builtin_return_address(3));
lr0 = reinterpret_cast<u_long>(__builtin_return_address(4));
LOGD("LR -> %p %p %p %p",(void*)(lr0-soAddr),(void*)(lr1-soAddr),(void*)(lr2-soAddr),(void*)(lr3-soAddr));
break;
case 5:
lr4 = reinterpret_cast<u_long>(__builtin_return_address(1));
lr3 = reinterpret_cast<u_long>(__builtin_return_address(2));
lr2 = reinterpret_cast<u_long>(__builtin_return_address(3));
lr1 = reinterpret_cast<u_long>(__builtin_return_address(4));
lr0 = reinterpret_cast<u_long>(__builtin_return_address(5));
LOGD("LR -> %p %p %p %p %p",(void*)(lr0-soAddr),(void*)(lr1-soAddr),(void*)(lr2-soAddr),(void*)(lr3-soAddr),(void*)(lr4-soAddr));
break;
}
}();
這個寫法比較簡陋了哼拔,也算是偷懶借用內(nèi)建函數(shù)(__builtin_return_address)完成了棧的回溯,當然也可以稍微麻煩一點热鞍,dobby 配合 asm內(nèi)嵌匯編 完成每一個函數(shù)棧的拆解诵叁,本質(zhì)都是用到了 FP 串聯(lián)起了整個函數(shù)調(diào)用鏈這樣一個大思路