ELF for the ARM architecture requires linkers to provide interworking for symbols that are of type STT_FUNC. Interworking for other symbols must be encoded directly in the object file. LLD was always providing interworking, regardless of the symbol type, this breaks some programs that have branches from Thumb state targeting STT_NOTYPE symbols that have bit 0 clear, but they are in fact internal labels in a Thumb function. LLD treats these symbols as ARM and inserts a transition to Arm.
This fixes the problem for in range branches, R_ARM_JUMP24, R_ARM_THM_JUMP24 and R_ARM_THM_JUMP19. This is expected to be the vast majority of problem cases as branching to an internal label close to the function.
There is at least one follow up patch required.
- R_ARM_CALL and R_ARM_THM_CALL may do interworking via BL/BLX substitution. A fix for this is dependent on D73254
In theory range-extension thunks can be altered to not change state when the symbol type is not STT_FUNC. I think this is a corner case on a corner case, but will need to check if BFD does it.
Fixes (part of) https://github.com/ClangBuiltLinux/linux/issues/773
ELF for the Arm Architecture https://static.docs.arm.com/ihi0044/g/aaelf32.pdf