因为任何一条指令与它需要访问的模块内部数据之间的相对位置是固定的,只需要相对于当前指令加上固定的偏移量就可以访问模块内部数据了。
现有C代码如下:
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
LOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
对应的汇编代码:
以
binder_loop(bs, svcmgr_handler);
为例:
将bs和svcmgr_handler作为参数存入寄存器,然后跳转到binder_loop函数地址执行,其中bs从R5拷贝到R0,R5又是第1个方框函数的返回值R0赋值得来。
主要说说svcmgr_handler,从第3个方框看到R3=(svcmgr_handler_ptr - 0xA170),svcmgr_handler_ptr的地址在0xA15C,R3=0xFFEC,也就是-0x20,是相对于got表的偏移量,
接着第4个方框内R1=R4+R3,其中R4=PC+(_GLOBAL_OFFSET_TABLE_ - 0x8792),PC是第2个方框内的PC值,总是等于当前地址+8,也就是0x8796,_GLOBAL_OFFSET_TABLE_的地址是0xA170,所以R1=0x8796+0xA170-0x8792+0xA15C-0xA170=0xA15C+4=0xA160。
(PC值似乎有点问题,有待进一步研究哈)
(to be continued)