Description
I was trying to build an arm32 binary that uses 64-bit division a LTO build of compiler-rt.
The 64-bit division function in compiler-rt (__aeabi_ldivmod
) is written in assembly and calls the C function __divmoddi4
, which works fine normally. However, when building with LTO the call inside __aeabi_ldivmod is replaced with a jump to address zero, which then crashes my program.
__aeabi_ldivmod dump:
Disassembly of section .text:
00000000 <__aeabi_ldivmod>:
0: e92d4040 push {r6, lr}
4: e24dd010 sub sp, sp, #16
8: e28d6008 add r6, sp, #8
c: e58d6000 str r6, [sp]
10: ebfffffe bl 0x10 <__aeabi_ldivmod+0x10> @ imm = #-0x8
00000010: R_ARM_CALL __divmoddi4
14: e59d2008 ldr r2, [sp, #0x8]
18: e59d300c ldr r3, [sp, #0xc]
1c: e28dd010 add sp, sp, #16
20: e8bd8040 pop {r6, pc}
I discussed this issue with @ilovepi and it appears that one problem here is that the call to __aeabi_ldivmod is generated post-LTO and the __divmoddi4 symbol is marked as not needed before final codegen.
However, it does seem like lld should be reporting an error for the missing __divmoddi4 instead of using address zero (it is not marked as weak, so that is invalid).
When building with -pie
instead of position dependent static linking, I do get an error:
ld.lld: error: relocation R_ARM_CALL cannot refer to absolute symbol: __divmoddi4
>>> defined in divmoddi4.bc
>>> referenced by aeabi_ldivmod.o:(__aeabi_ldivmod)
This suggests __divmoddi4 was replaced with and absolute zero symbol.
I have created a minimized test case which I will upload as a PR shortly.