@@ -0,0 +1,100 @@
1+From 8e2c350f870f8cd99122c62efd023820e563e935 Mon Sep 17 00:00:00 2001
2+From: Moritz Angermann <moritz.angermann@gmail.com>
3+Date: Thu, 16 May 2019 13:35:31 +0800
4+Subject: [PATCH] Add _GLOBAL_OFFSET_TABLE_ support
5+
6+This adds lookup logic for _GLOBAL_OFFSET_TABLE_ as well as
7+relocation logic for R_ARM_BASE_PREL and R_ARM_GOT_BREL which
8+the gnu toolchain (gas, gcc, ...) prefers to produce. Apparently
9+recent llvm toolchains will produce those as well.
10+---
11+ rts/linker/Elf.c | 33 +++++++++++++++++++++++++++++++--
12+ rts/linker/elf_got.c | 10 +++++++---
13+ 2 files changed, 38 insertions(+), 5 deletions(-)
14+
15+diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
16+index b647d207cb..c6f82af72a 100644
17+--- a/rts/linker/Elf.c
18++++ b/rts/linker/Elf.c
19+@@ -1023,6 +1023,19 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
20+ return 1;
21+ }
22+
23++ /* The following nomenclature is used for the operation:
24++ * - S -- (when used on its own) is the address of the symbol.
25++ * - A -- is the addend for the relocation.
26++ * - P -- is the address of the place being relocated (derived from r_offset).
27++ * - Pa - is the adjusted address of the place being relocated, defined as (P & 0xFFFFFFFC).
28++ * - T -- is 1 if the target symbol S has type STT_FUNC and the symbol addresses a Thumb instruction; it is 0 otherwise.
29++ * - B(S) is the addressing origin of the output segment defining the symbol S. The origin is not required to be the
30++ * base address of the segment. This value must always be word-aligned.
31++ * - GOT_ORG is the addressing origin of the Global Offset Table (the indirection table for imported data addresses).
32++ * This value must always be word-aligned. See §4.6.1.8, Proxy generating relocations.
33++ * - GOT(S) is the address of the GOT entry for the symbol S.
34++ */
35++
36+ for (j = 0; j < nent; j++) {
37+ Elf_Addr offset = rtab[j].r_offset;
38+ Elf_Addr info = rtab[j].r_info;
39+@@ -1117,19 +1130,35 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
40+ # endif
41+
42+ # ifdef arm_HOST_ARCH
43+- case COMPAT_R_ARM_ABS32:
44++ case COMPAT_R_ARM_ABS32: /* (S + A) | T */
45+ // Specified by Linux ARM ABI to be equivalent to ABS32
46+ case COMPAT_R_ARM_TARGET1:
47+ *(Elf32_Word *)P += S;
48+ *(Elf32_Word *)P |= T;
49+ break;
50+
51+- case COMPAT_R_ARM_REL32:
52++ case COMPAT_R_ARM_REL32: /* ((S + A) | T) – P */
53+ *(Elf32_Word *)P += S;
54+ *(Elf32_Word *)P |= T;
55+ *(Elf32_Word *)P -= P;
56+ break;
57+
58++ case COMPAT_R_ARM_BASE_PREL: /* B(S) + A – P */
59++ {
60++ int32_t A = *pP;
61++ // bfd used to encode sb (B(S)) as 0.
62++ *(uint32_t *)P += 0 + A - P;
63++ break;
64++ }
65++
66++ case COMPAT_R_ARM_GOT_BREL: /* GOT(S) + A – GOT_ORG */
67++ {
68++ int32_t A = *pP;
69++ void* GOT_S = symbol->got_addr;
70++ *(uint32_t *)P = (uint32_t) GOT_S + A - (uint32_t) oc->info->got_start;
71++ break;
72++ }
73++
74+ case COMPAT_R_ARM_CALL:
75+ case COMPAT_R_ARM_JUMP24:
76+ {
77+diff --git a/rts/linker/elf_got.c b/rts/linker/elf_got.c
78+index 10ea25b98b..162fff3161 100644
79+--- a/rts/linker/elf_got.c
80++++ b/rts/linker/elf_got.c
81+@@ -83,9 +83,13 @@ fillGot(ObjectCode * oc) {
82+ if(0x0 == symbol->addr) {
83+ symbol->addr = lookupSymbol_(symbol->name);
84+ if(0x0 == symbol->addr) {
85+- errorBelch("Failed to lookup symbol: %s\n",
86+- symbol->name);
87+- return EXIT_FAILURE;
88++ if(0 == strncmp(symbol->name,"_GLOBAL_OFFSET_TABLE_",21)) {
89++ symbol->addr = oc->info->got_start;
90++ } else {
91++ errorBelch("Failed to lookup symbol: %s\n",
92++ symbol->name);
93++ return EXIT_FAILURE;
94++ }
95+ }
96+ } else {
97+ // we already have the address.
98+--
99+2.21.0
100+