一個辦法做到這一點是讓它做你想要什麼
branchto.s
.thumb
.thumb_func
.globl branchto
branchto:
bx r0
so.c
extern unsigned int externalFunction;
extern int branchto (unsigned int, int);
int fun (int x)
{
return(branchto(externalFunction,x)+3);
}
so.ld
SECTIONS
{
.text 0x8000000 : { *(.text) }
}
externalFunction = 0x8002001;
生產
08000000 <fun>:
8000000: 4b04 ldr r3, [pc, #16] ; (8000014 <fun+0x14>)
8000002: b510 push {r4, lr}
8000004: 0001 movs r1, r0
8000006: 6818 ldr r0, [r3, #0]
8000008: f000 f806 bl 8000018 <branchto>
800000c: 3003 adds r0, #3
800000e: bc10 pop {r4}
8000010: bc02 pop {r1}
8000012: 4708 bx r1
8000014: 08002001 stmdaeq r0, {r0, sp}
08000018 <branchto>:
8000018: 4700 bx r0
羅斯里奇在評論解決方案工作
static int (* const externalFunction)(int x) = (int (*)(int)) 0x80002001;
int fun (int x)
{
return((* externalFunction)(x)+3);
}
但是硬編碼地址是在代碼不是鏈接腳本,如果該事項,試圖解決這一點,不可能。
08000000 <fun>:
8000000: b510 push {r4, lr}
8000002: 4b03 ldr r3, [pc, #12] ; (8000010 <fun+0x10>)
8000004: f000 f806 bl 8000014 <fun+0x14>
8000008: 3003 adds r0, #3
800000a: bc10 pop {r4}
800000c: bc02 pop {r1}
800000e: 4708 bx r1
8000010: 80002001 andhi r2, r0, r1
8000014: 4718 bx r3
8000016: 46c0 nop ; (mov r8, r8)
我更喜歡這樣的裝配解決方案來強制我想要的確切指令。當然,如果你在外部函數中鏈接了它,它應該會/應該剛剛工作(有一些例外,但是gnu在鏈接器中解決了你進出手臂/拇指的問題)。
我不認爲它是一個實際的gnu錯誤,而是他們需要在鏈接描述文件中將該變量聲明爲拇指函數地址,而不僅僅是一些通用鏈接器定義變量(同樣也是一個手臂函數地址)。就像 。thumb_func做(或更長的功能/過程聲明)
.word branchto
.thumb
.globl branchto
branchto:
bx r0
8000018: 0800001c stmdaeq r0, {r2, r3, r4}
0800001c <branchto>:
800001c: 4700 bx r0
.word branchto
.thumb
.thumb_func
.globl branchto
branchto:
bx r0
8000018: 0800001d stmdaeq r0, {r0, r2, r3, r4}
0800001c <branchto>:
800001c: 4700 bx r0
僅僅閱讀GNU鏈接的文件有可能被希望能得到你想要的東西
SECTIONS
{
.text0 0x08000000 : { so.o }
.text1 0x08002000 (NOLOAD) : { ex.o }
}
ex.o從虛擬函數對正在添加讓每個人都開心
int externalFunction (int x)
{
return(x);
}
08000000 <fun>:
8000000: b510 push {r4, lr}
8000002: f001 fffd bl 8002000 <externalFunction>
8000006: 3003 adds r0, #3
8000008: bc10 pop {r4}
800000a: bc02 pop {r1}
800000c: 4708 bx r1
和NOLOAD保持二進制的虛擬函數。
arm-none-eabi-objcopy so.elf -O srec --srec-forceS3 so.srec
S00A0000736F2E7372656338
S3150800000010B501F0FDFF033010BC02BC0847C0461E
S315080000104743433A2028474E552920362E322E305C
S31508000020004129000000616561626900011F000046
S3150800003000053454000602080109011204140115CA
S31008000040011703180119011A011E021E
S70500000000FA
注意到它不是完美有額外的垃圾是得到了拉昇的,或許符號
08000000 <fun>:
8000000: b510 push {r4, lr}
8000002: f001 fffd bl 8002000 <externalFunction>
8000006: 3003 adds r0, #3
8000008: bc10 pop {r4}
800000a: bc02 pop {r1}
800000c: 4708 bx r1
800000e: 46c0 nop ; (mov r8, r8)
8000010: 3a434347
8000014: 4e472820
8000018: 36202955
800001c: 302e322e
8000020: 00294100
8000024: 65610000
8000028: 00696261
800002c: 00001f01
8000030: 54340500
8000034: 08020600
8000038: 12010901
800003c: 15011404
8000040: 18031701
8000044: 1a011901
,你可以在SREC看到,但0x08002000代碼是不是有那麼您的實際外部函數打電話。
如果你不想要任何asm,我只要做出你想要的指令或函數指針就可以了。
最明顯的事情,試圖將'externalFunction = 0x8002001;' 。 –
我使用'0x8002001'獲得與以前相同的輸出:它實際上在清除位後進行彙編。它似乎_very_致力於確保它是一個ARM調用... –
似乎有一個關於這個報告的錯誤,https://sourceware.org/bugzilla/show_bug.cgi?id=15302,但不幸的是它的修復僅適用於您沒有使用的僅限拇指目標。如果您不介意非鏈接腳本解決方案,您可以這樣做:'static int(* const externalFunction)(int x)=(int(*)(int))0x80002001;' –