【问题标题】:Static Address vs. Execution Address In An Elf Loader精灵加载器中的静态地址与执行地址
【发布时间】:2019-01-25 19:27:16
【问题描述】:
我正在为 ARM/ARM64 编写一个 Elf Loader。在处理动态重定位时,我对我关注的documentation 中的一些术语/符号感到有些困惑。
在 Pg.14 中指出,
“S(单独使用时)是符号的地址。”
"P是被重定位的地方的地址(从r_offset派生)。"
"Delta(S) 如果 S 是一个普通符号,则解析为 S 的静态链接地址与
S 的执行地址。如果 S 是空符号(ELF 符号索引 0),则解析为
P的静态链接地址和P的执行地址。"
据我所知,我认为 S(或 P)的“执行地址”是进程内存空间中符号的地址,但不确定“静态链接地址”是什么意思。
如果有人能澄清一些很棒的术语,谢谢。
【问题讨论】:
标签:
linker
arm
elf
arm64
relocation
【解决方案1】:
什么是“静态链接地址”。
非 PIE 可执行文件链接到特定地址加载。比如在x86_64Linux上默认静态链接地址是0x400000:
echo "int main() { return 0; }" | gcc -xc - -no-pie
readelf -Wl a.out | grep LOAD
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x000618 0x000618 R E 0x200000
LOAD 0x000e50 0x0000000000600e50 0x0000000000600e50 0x0001d8 0x0001e0 RW 0x200000
该二进制文件与0x400000的静态链接地址链接,其中的符号反映:
nm a.out | grep ' main'
0000000000400487 T main
这个可执行文件必须加载到0x400000,如果加载到其他地方将无法正常工作。
注意默认的非PIE静态链接地址
- 对于不同的架构是不同的(
i386默认是0x8048000),并且
- 可以在静态链接时通过链接器脚本和/或链接器标志进行更改。
将此与 PIE 可执行文件进行对比,后者通常链接到静态链接地址 0:
echo "int main() { return 0; }" | gcc -xc - -fPIE -pie
readelf -Wl a.out | grep LOAD
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0007d8 0x0007d8 R E 0x200000
LOAD 0x000e18 0x0000000000200e18 0x0000000000200e18 0x000210 0x000218 RW 0x200000
nm a.out | grep ' main'
00000000000005fa T main
所以main的静态链接地址在非PIE情况下为0x400487,在PIE情况下为0x5fa。