将预l31地址转换为.ARM.exidex部分的实际地址



我想了解ARM堆栈展开,因此,我仔细查看了二进制文件的.ARM.exix部分。二进制文件是使用gcc为arm、little-endian和Cortex M0 32位构建的。

不出所料,我得到了exidx表,下面是我用objdump转储的一个示例:

8012d34 c09bff7f ab07b180 909cff7f a907b180  ................
8012d44 c09cff7f b0ab0e80 509eff7f b0ab0c80  ........P.......
8012d54 249fff7f b0aa0580 b49fff7f b0ab0880  $...............
8012d64 aca0ff7f b0ab1080 74a1ff7f b0ab0880  ........t.......
8012d74 dca1ff7f b0b0b080 e4a1ff7f aa03b180  ................
8012d84 34a2ff7f b0ab0880 20a3ff7f b0ab1280  4....... .......
8012d94 20a4ff7f b0b0b080 28a4ff7f b0b0a880   .......(.......
8012da4 44a4ff7f 01000000 10a6ff7f b0b0b080  D...............

据我所知,第一个条目是程序中函数的调用地址(以0x7f结尾的(,并且是prel31格式的,用于指示通用模型。

现在,我的问题是,如何将这些地址转换为实际的函数地址?我在linux中的unflex.h中找到了ARM内核的转换

/* Convert a prel31 symbol to an absolute address */
#define prel31_to_addr(ptr)             
({                          
/* sign-extend to 32 bits */            
long offset = (((long)*(ptr)) << 1) >> 1;   
(unsigned long)(ptr) + offset;          
})

但我无法从exidx部分获得与我可以在地图文件中查找的地址相匹配的地址。

exidx中的地址应该与地图文件中的地址匹配吗?还是我有误解?如果应该匹配,我如何转换它们?

请参阅:ARM extab的结构。

exidx部分与可执行文件链接。exidx和代码之间的距离很重要。您可以让链接器转储表地址。它实际上是"二进制偏移量"。例如,

10000: 8012d34 c09bff7f

然后获取0x7fff9bc0,第二个小端序条目,并在宏中运行它。

偏移为0xffff9bc0->6440因此二进制偏移量为10000-6440->9bc0.

不幸的是,您的"exidx"偏移量可能没有0x10000那么好。如果你有一个链接器文件,你可以添加填充,使其易于为实验翻译。

偏移量很重要,这就是使长度为31的p指针rel等于地址(prel31addr(的原因。

最新更新