反汇编代码里的地址 链接地址 运行地址 存储地址 位置无关码 位置有关码

本文介绍了反汇编代码地址、链接地址、运行地址及存储地址的概念,并深入解析了位置无关码与位置相关码的区别,同时阐述了代码重定位的过程。
反汇编代码地址就是链接地址;


链接地址不一定等于运行地址(通常链接地址和运行地址的值是一样的);


运行地址是在统一编址的存储区间中,正在运行的代码所处的地址;


存储地址是也就是代码被下载到物理介质上的地址。


位置无关码的代码中没有绝对地址的不连续跳转,反之就是位置相关码;


代码重定位的判断本质是依赖与PC寄存器实现。


具体是PC值的相对位置固定,可以锁定两个相对位置:相对PC锁定运行时代码的首地址和相对PC锁定某个特定的存储单元,以这个单元里的数值为绝对地址得到重定位地址。
比较重定位的地址和当前代码运行的首地址,若相同不需要重定位,如不同则复制代码,清BSS段(实现C语言中未初始化的全局变量是0),刷新PC值跳过去。
<think>我们正在讨论ELF文件中静态变量的地址问题。用户询问的是:ELF文件中的地址与实际静态变量地址是否会一致。 结合之前的引用和知识,我们可以分析如下: 1. **编译链接阶段**:在编译和链接时,全局变量和静态变量的地址已经被确定(引用[1]提到全局变量和静态变量的地址在编译时就决定了)。这些地址是虚拟地址(VMA),在ELF文件中记录在符号表或程序头中。 2. **加载执行阶段**:当程序被加载到内存时,操作系统根据ELF文件的程序头表(Program Header Table)将各个段(如.text, .data, .bss)映射到进程的虚拟地址空间(引用[3]提到ELF文件加载到内存时,通过mm_struct等建立映射)。此时,如果加载地址与ELF文件中预设的地址一致(即没有地址随机化),那么静态变量的虚拟地址就会与ELF文件中的地址一致。 3. **地址随机化(ASLR)**:现代操作系统为了安全,会启用地址空间布局随机化(ASLR)。开启ASLR后,每次程序加载时,其基地址(即程序头中的虚拟地址的起始点)会被随机偏移。因此,ELF文件中的地址(称为链接虚拟地址,Link-time Virtual Address)与实际运行时虚拟地址(Runtime Virtual Address)会有一个偏移量。 4. **静态链接与动态链接**: - 静态链接的程序,其所有代码和数据地址链接时已经确定(引用[2]提到静态链接)。 - 动态链接的程序,其共享库的加载地址运行时确定(引用[3]提到动态链接与动态库加载)。但对于程序本身的静态变量(非共享库中的),其地址链接时已经确定(相对于程序基址),运行时由加载器根据基址偏移调整。 5. **结论**: - 如果没有开启ASLR,那么ELF文件中的地址与实际运行的虚拟地址一致。 - 如果开启ASLR,那么实际运行地址等于ELF文件中的地址加上一个随机偏移量(基址偏移)。 - 无论是否开启ASLR,静态变量的相对位置(相对于基址)是固定的。 因此,我们可以回答:**ELF文件中的地址链接时确定的虚拟地址)与实际运行时的虚拟地址可能会一致,主要原因是地址空间布局随机化(ASLR)**。 为了更清晰地说明,我们可以用公式表示: 设ELF文件中符号的虚拟地址为$V_{link}$,运行时程序的基地址(Image Base)为$B_r$(如果没有ASLR,则$B_r$等于链接时基地址$B_{link}$;有ASLR时$B_r$是随机的),那么实际运行时虚拟地址$V_{runtime}$为: $$ V_{runtime} = V_{link} + (B_r - B_{link}) $$ 其中,$(B_r - B_{link})$就是随机偏移量。 --- ### 验证方法 1. **查看ELF文件中的地址**: ```bash readelf -s program | grep [静态变量名] ``` 输出结果中的`Value`字段就是链接时的虚拟地址$V_{link}$。 2. **运行时查看变量地址**: - 使用调试器(如gdb)运行程序,查看变量的地址。 - 在程序中打印变量的地址: ```c printf("%p", &static_var); ``` 3. **比较两个地址**: - 关闭ASLR(Linux下): ```bash echo 0 | sudo tee /proc/sys/kernel/randomize_va_space ``` 然后运行程序,比较地址是否相同。 - 开启ASLR(默认)时,每次运行地址都会变化,但相对位置变。 4. **计算偏移量**: 如果知道程序运行时的基地址(可以通过`/proc/[pid]/maps`查看),就可以验证上述公式。 --- ### 相关问题 §§相关问题§§ 1. 如何关闭Linux系统的ASLR功能? 2. ELF文件中哪些段会受ASLR影响? 3. 动态链接库中的静态变量地址运行时如何确定? </think>### ELF文件中的地址与实际静态变量地址是否一致? 在ELF文件中,静态变量(包括全局静态与局部静态)的地址在**编译链接阶段就已确定**,但实际运行地址可能与ELF文件中的地址一致,原因如下: --- #### 一、正常情况下地址一致性原理 1. **编译链接阶段** 静态变量的地址在编译链接时由链接器分配,存储在ELF的`.data`(已初始化)或`.bss`(未初始化)段中[^1]。例如: ```bash readelf -s program | grep static_var # 输出示例:08049000 4 OBJECT LOCAL DEFAULT 15 static_var ``` 此地址`0x08049000`是链接时确定的**虚拟地址**。 2. **加载阶段** 操作系统加载ELF时,根据程序头表(Program Header Table)将代码和数据段映射到内存的**相同虚拟地址**(默认无ASLR时)[^4]。此时: $$ \text{ELF虚拟地址} \approx \text{运行时虚拟地址} $$ --- #### 二、地址一致的情形及原因 1. **地址空间随机化(ASLR)** - 现代操作系统默认启用ASLR,导致每次加载时程序基址随机偏移 - **偏移公式**: $$ \text{实际地址} = \text{ELF虚拟地址} + \text{随机偏移量} $$ - **验证方法**: ```bash # 关闭ASLR后地址恒定 echo 0 | sudo tee /proc/sys/kernel/randomize_va_space ./program ``` 2. **动态链接干扰** - 若静态变量在动态库中,加载地址由动态链接器决定 - 符号可能被重定位(Relocation),如: ```bash readelf -r program | grep static_var # 输出示例:R_386_GLOB_DAT 08049000 static_var ``` 3. **位置无关代码(PIE)** - 编译选项`-fPIE`或`-pie`会使所有地址在加载时重定位 - ELF文件中的地址仅为**相对偏移量**,需加运行时基址[^3]: $$ \text{实际地址} = \text{ELF相对地址} + \text{运行时基址} $$ --- #### 三、关键验证方法 ##### 1. 检查ASLR状态 ```bash cat /proc/sys/kernel/randomize_va_space # 2=开启, 0=关闭 ``` ##### 2. 对比ELF与运行地址 ```c // 示例代码: addr_check.c #include <stdio.h> static int static_var = 42; int main() { printf("编译时地址: %p (ELF文件中)\n", &static_var); // 编译时输出 printf("运行地址: %p\n", &static_var); // 运行时输出 return 0; } ``` 编译运行: ```bash gcc addr_check.c -o addr_check ./addr_check # 多次运行观察地址变化(ASLR开启时) ``` ##### 3. 分析ELF重定位信息 ```bash readelf -r program # 查看重定位表 objdump -d -j .data program # 反汇编.data段 ``` --- #### 四、地址一致性总结 | **场景** | 地址是否一致 | 原因 | |----------------------|--------------|-------------------------------| | 静态链接 + ASLR关闭 | ✅ 一致 | 无随机偏移 | | 静态链接 + ASLR开启 | ❌ 一致 | 基址随机偏移 | | 动态链接库中的变量 | ❌ 一致 | 动态库加载地址随机 | | 启用PIE编译 | ❌ 一致 | 所有地址重定位 | > **核心结论**: > 当且仅当**静态链接且关闭ASLR**时,ELF文件中地址与实际运行地址一致;其他情况下因安全机制(ASLR/PIE)或动态链接会导致地址偏移。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值