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

如何让Clang基于AArch64固定段地址填充指令偏移?

问题:AArch64汇编编译时固定段地址参数未生效,指令偏移未按预期填充

我正在开展AArch64代码分析项目,需要用clang将AArch64汇编代码转换为字节码,再通过llvm-objdump提取分析。要求固定段地址:text段为0x40000、data段为0x50000、bss段为0x60000,并据此填充汇编中的偏移。

使用以下命令编译:

clang -c -target aarch64-none -march=armv8.1-a -Ttext=0x40000 -Tdata=0x50000 -Tbss=0x60000 test.s -o test.o

编译的汇编代码为:

.text
.globl main
main:
    adrp x0, var1
    ldr w1, [x0, :lo12:var1]
    adrp x2, var2
    ldr w3, [x2, :lo12:var2]
    ret
.data
.globl var1
var1:
    .zero 8
    .size var1, 8
.globl var2
var2:
    .zero 8
    .size var2, 8

clang提示参数未被使用:

clang: warning: argument unused during compilation: '-Ttext=0x40000' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-Tdata=0x50000' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-Tbss=0x60000' [-Wunused-command-line-argument]

用llvm-objdump-15 -d test.o反汇编,发现指令偏移未按预期填充:

test.o:       file format elf64-littleaarch64

Disassembly of section .text:

0000000000000000 <main>:
       0: 90000000      adrp    x0, 0x0 <main>
       4: b9400001      ldr     w1, [x0]
       8: 90000002      adrp    x2, 0x0 <main+0x8>
       c: b9400043      ldr     w3, [x2]
      10: d65f03c0      ret

用llvm-objdump-15 -r查看重定位信息,也显示未使用指定的段地址:

test.o:       file format elf64-littleaarch64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE                     VALUE
0000000000000000 R_AARCH64_ADR_PREL_PG_HI21 var1
0000000000000004 R_AARCH64_LDST32_ABS_LO12_NC var1
0000000000000008 R_AARCH64_ADR_PREL_PG_HI21 var2
000000000000000c R_AARCH64_LDST32_ABS_LO12_NC var2

补充:去掉-c选项会遇到大量交叉编译问题,有没有办法在不编译为完整程序的前提下预填充指令偏移?


解决方案

核心原因

-Ttext/-Tdata/-Tbss是链接器(ld)的选项,而非编译器/汇编器选项。当使用clang -c时,clang仅执行编译/汇编步骤,不会调用链接器,因此这些参数会被直接忽略,这就是警告的来源。

要在生成可重定位目标文件(.o)的前提下实现固定段地址并填充指令偏移,有两种可行方法:


方法一:汇编代码中直接绑定符号的绝对地址

修改汇编代码,通过.set伪指令给data段的符号指定绝对地址,让汇编器直接计算出基于固定段地址的偏移:

.text
.globl main
main:
    adrp x0, var1
    ldr w1, [x0, :lo12:var1]
    adrp x2, var2
    ldr w3, [x2, :lo12:var2]
    ret
.data
.globl var1
.set var1, 0x50000  // 绑定var1到data段起始地址0x50000
var1:
    .zero 8
    .size var1, 8
.globl var2
.set var2, 0x50008  // var2在var1之后8字节,绑定到0x50008
var2:
    .zero 8
    .size var2, 8

编译时无需再添加-T参数,直接执行:

clang -c -target aarch64-none -march=armv8.1-a test.s -o test.o

反汇编后会看到adrp指令的目标已正确指向0x50000,指令偏移也已填充完成,无需依赖后续重定位。


方法二:用链接脚本+ld重定位链接生成带固定地址的目标文件

通过链接脚本指定段地址,再用ld -r(重定位链接,生成可重定位目标文件)将原目标文件转换为带固定段地址的版本:

  1. 编写链接脚本layout.ld:
SECTIONS {
  .text 0x40000 : { *(.text) }
  .data 0x50000 : { *(.data) }
  .bss 0x60000 : { *(.bss) }
}
  1. 先将汇编代码编译为普通可重定位目标文件:
clang -c -target aarch64-none -march=armv8.1-a test.s -o test.o
  1. 用ld -r结合链接脚本生成带固定段地址的目标文件:
aarch64-none-ld -r -T layout.ld test.o -o test_fixed.o

生成的test_fixed.o中,.text段起始为0x40000,.data段起始为0x50000,反汇编结果如下:

test_fixed.o:       file format elf64-littleaarch64

Disassembly of section .text:

0000000000040000 <main>:
   40000: 90000200      adrp    x0, 0x50000 <var1>
   40004: b9400001      ldr     w1, [x0]
   40008: 90000202      adrp    x2, 0x50000 <var1>
   4000c: b9400443      ldr     w3, [x2, #8]
   40010: d65f03c0      ret

该方法保留了重定位信息,但所有偏移都基于指定的固定段地址计算,满足代码分析的需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 11:27:06