diff options
Diffstat (limited to 'rts')
-rw-r--r-- | rts/linker/Elf.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c index 77107a73ea..174fc47001 100644 --- a/rts/linker/Elf.c +++ b/rts/linker/Elf.c @@ -992,15 +992,37 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC, IF_DEBUG(linker,debugBelch( "`%s' resolves to %p\n", symbol, (void*)S )); #ifdef arm_HOST_ARCH - // Thumb instructions have bit 0 of symbol's st_value set - is_target_thm = S & 0x1; - - T = sym.st_info & STT_FUNC && is_target_thm; - - // Make sure we clear bit 0. Strictly speaking we should have done - // this to st_value above but I believe alignment requirements should - // ensure that no instructions start on an odd address - S &= ~1; + /* + * 4.5.3 Symbol Values + * + * In addition to the normal rules for symbol values the following + * rules shall also apply to symbols of type STT_FUNC: + * - If the symbol addresses an ARM instruction, its value is the + * address of the instruction (in a relocatable object, the + * offset of the instruction from the start of the section + * containing it). + * - If the symbol addresses a Thumb instruction, its value is the + * address of the instruction with bit zero set (in a relocatable + * object, the section offset with bit zero set). + * - For the purposes of relocation the value used shall be the + * address of the instruction (st_value & ~1). + * + * Note: This allows a linker to distinguish ARM and Thumb code + * symbols without having to refer to the map. An ARM symbol + * will always have an even value, while a Thumb symbol will + * always have an odd value. However, a linker should strip + * the discriminating bit from the value before using it for + * relocation. + * + * (source: ELF for the ARM Architecture + * ARM IHI 0044F, current through ABI release 2.10 + * 24th November 2015) + */ + if(ELF_ST_TYPE(sym.st_info) == STT_FUNC) { + is_target_thm = S & 0x1; + T = is_target_thm; + S &= ~1; + } #endif } |