summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
Diffstat (limited to 'rts')
-rw-r--r--rts/linker/Elf.c40
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
}