【发布时间】:2017-09-02 09:54:29
【问题描述】:
我正在为需要链接到现有 THUMB 代码的嵌入式内核 (ARM7TDMI) 编写 THUMB 代码。我正在使用 GNU ARM 嵌入式工具链 (link)。我无法让链接器将现有的外部代码视为 THUMB;似乎一直认为是ARM。我链接到的现有代码是绝对静态的,不能更改/重新编译(基本上,它是位于 ROM 芯片上的普通二进制文件)。
这是一个示例程序 multiply.c,它演示了这个问题:
extern int externalFunction(int x);
int multiply(int x, int y)
{
return externalFunction(x * y);
}
编译使用:
arm-none-eabi-gcc -o multiply.o -c -O3 multiply.c -march=armv4t -mtune=arm7tdmi -mthumb
arm-none-eabi-ld -o linked.o multiply.o -T symbols.txt
symbols.txt 是一个简单的链接脚本:
SECTIONS
{
.text 0x8000000 : { *(.text) }
}
externalFunction = 0x8002000;
当我objdump -d linked.o 时,我得到:
08000000 <multiply>:
8000000: b510 push {r4, lr}
8000002: 4348 muls r0, r1
8000004: f000 f804 bl 8000010 <__externalFunction_from_thumb>
8000008: bc10 pop {r4}
800000a: bc02 pop {r1}
800000c: 4708 bx r1
800000e: 46c0 nop ; (mov r8, r8)
08000010 <__externalFunction_from_thumb>:
8000010: 4778 bx pc
8000012: 46c0 nop ; (mov r8, r8)
8000014: ea0007f9 b 8002000 <externalFunction>
它不是直接分支到 0x8002000,而是分支到一个存根,该存根首先切换到 ARM 模式,然后在 ARM 模式下分支到 0x8002000。我希望 BL 直接分支到 0x8002000 并保持 THUMB 模式,这样我就可以得到这个:
08000000 <multiply>:
8000000: b510 push {r4, lr}
8000002: 4348 muls r0, r1
8000004: ???? ???? bl 8002000 <__externalFunction>
8000008: bc10 pop {r4}
800000a: bc02 pop {r1}
800000c: 4708 bx r1
抛开 ABI 和调用约定问题,我该如何实现?
【问题讨论】:
-
显而易见的尝试是
externalFunction = 0x8002001;。 -
我得到与使用
0x8002001之前相同的输出:它实际上是在清除位的情况下组装的。似乎非常致力于确保这是一个 ARM 调用... -
似乎有一个关于此的错误报告,sourceware.org/bugzilla/show_bug.cgi?id=15302,但不幸的是,它的修复仅适用于您似乎没有使用的 Thumb 目标。如果您不介意非链接器脚本解决方案,您可以这样做:
static int (* const externalFunction)(int x) = (int (*)(int)) 0x80002001;
标签: gcc arm cross-compiling ld thumb