You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM裸机PIC二进制全局变量地址异常问题求助

ARM裸机PIC/PIE全局变量地址问题解决方案

你的问题核心在于:裸机环境没有动态链接器,直接用-fpic编译的代码无法自动处理全局变量的绝对地址重定位,导致返回的是变量相对于二进制的偏移而非实际加载后的绝对地址。以下是具体解决思路和步骤:

1. 改用PIE而非PIC

-fpic是为共享库设计的,依赖动态链接器处理GOT(全局偏移表);而-fpie是为位置独立可执行文件设计的,更适合裸机场景,配合链接时的-pie选项,能生成无需动态链接器的位置独立代码。

修改编译链接命令

把原来的命令调整为:

# 用-fpie编译,生成PIE目标文件
$(ARMCC)-gcc -fpie -mcpu=cortex-a7 main.c -o main.o
# 链接时加-pie选项,生成PIE可执行文件
$(ARMCC)-ld -pie main.o -T linker.ld -o main.elf
# 转成二进制
$(ARMCC)-objcopy -O binary main.elf main.bin

(注:你原来的链接命令里重复了main.o,这是笔误,需要去掉一个)

2. 更新链接脚本,添加GOT段

PIE代码需要GOT段存储全局变量的偏移信息,所以要在linker.ld中添加.got段:

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)

SECTIONS {
    . = ALIGN(4);
    .text : {
        _text_start = .;
        *(.text)
        _text_end = .;
    }

    /* Read only data */
    . = ALIGN(4);
    .rodata : {
        _rodata_start = .;
        *(.rodata)
        _rodata_end = .;
    }

    /* 新增GOT段,用于PIE的全局变量重定位 */
    . = ALIGN(4);
    .got : {
        _got_start = .;
        *(.got)
        _got_end = .;
    }

    /* BSS, Block starting symbol */
    . = ALIGN(4);
    .bss : {
        _bss_start = .;
        *(.bss)
        _bss_end = .;
    }

    /* Regular data */
    . = ALIGN(4);
    .data : {
        _data_start = .;
        *(.data)
        _data_end = .;
    }
}

3. 在启动代码中初始化GOT基地址

ARM架构的PIE代码约定用r9寄存器存储GOT基地址,需要在启动汇编代码中计算并设置这个基地址(因为裸机没有动态链接器帮你做这件事):

.global _start
_start:
    ; 计算GOT的实际运行时基地址
    adr r0, .Lgot_ref       ; 获取当前PC相对的.Lgot_ref地址
    ldr r1, =_got_start     ; 加载链接时GOT的起始地址
    sub r0, r0, r1          ; 计算加载偏移:当前位置 - 链接时GOT地址
    add r9, r1, r0          ; 实际GOT基地址 = 链接时地址 + 加载偏移,存入r9

    ; 调用main函数
    bl main

    ; 程序结束后死循环
loop:
    b loop

.Lgot_ref:
    .word _got_start

这段代码的作用是:根据程序实际加载的地址,动态计算GOT的基地址,确保C代码中访问全局变量时,能通过GOT正确获取到绝对地址。

原理说明

当你用-fpie/-pie编译链接后,全局变量的访问会通过GOT间接获取:代码中会先从GOT中读取变量的偏移,再加上GOT基地址得到变量的绝对地址。启动代码中初始化GOT基地址后,main()返回的&foo就会是实际加载后的绝对地址,而非偏移量。

内容的提问来源于stack exchange,提问作者user16506491

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 11:03:15