Add support for the R_ARM_THM relocations used in the objects present
in arm-linux-gnueabihf-gcc. These are:
- R_ARM_THM_CALL
- R_ARM_THM_JUMP11
- R_ARM_THM_JUMP19
- R_ARM_THM_JUMP24
- R_ARM_THM_MOVT_ABS
- R_ARM_THM_MOVW_ABS_NC
Interworking between ARM and Thumb is partially supported with BLX. The R_ARM_CALL relocation for ARM instructions and R_ARM_THM_CALL relocation for Thumb instructions will write out a BL or BLX depending on the state of the Target.
Assumptions:
- Target processor has BLX instruction and extended range of Thumb 4-byte Branch instructions (true for ARMv7a).
- In relocateOne if (Val & 0x1) == 1 target is Thumb, 0 is ARM. This will hold for objects that comply with the ABI for the ARM architecture.
This is sufficient interworking support for a Thumb hello world to work with a recent arm-linux-gnueabihf distribution such as Linaro GCC 5.3-2016.02).
Limitations:
- No interworking thunks for R_ARM_JUMP24, R_ARM_THM_JUMP24, R_ARM_THM_JUMP19 and the deprecated R_ARM_PLT32 and R_ARM_PC24 instructions as the instructions cannot be written out as a BLX and need a state change thunk.
- No range extension thunks. The R_ARM_JUMP24 and R_ARM_THM_CALL have a range of 16Mb
- No regression test in the test suite for R_ARM_JUMP11, llvm-mc does not emit a relocation for B.N which is sensible and permissible under the ABI as the range of the branch is too small to be usefully relocated, however gnu-as does produce the relocation and there is at least one instance in the arm-linux-gnueabihf libraries so it may be present in input objects.
References:
- The Thumb instruction encodings are unfortunately not pretty, the 4-byte instructions are encoded as a consecutive pair of halfwords. The encodings are defined in the ARM Architecture Reference Manual: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0406c/index.html (requires free registration)
- The relocations are defined in ELF for the ARM Architecture: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044f/IHI0044F_aaelf.pdf (no registration required)
I will look into interworking thunks next.
So, are all of these really R_PLT_PC and not R_PC?
If the target symbol is not preemptible we don't create a plt entry and just use the target address. But if the target symbol is preemptible we will create a plt and that will have a call in it. That will break code that is not expecting the link register to change, no?