History

Make build_got_entries more target independent

Factor most of common logic between targets in build_got_entries by defining target specific info into structures in the backends.

Thomas Preud'homme committed 10 years ago

Commit 1c811a41 parent 523b55d11 files · +179 −211Browse files

Unified · Split

11 files
  1. arm-gen.c +1 −0
  2. arm-link.c +52 −2
  3. arm64-gen.c +1 −0
  4. arm64-link.c +18 −1
  5. c67-gen.c +1 −0
  6. i386-gen.c +1 −0
  7. i386-link.c +13 −0
  8. tcc.h +20 −0
  9. tccelf.c +57 −208
  10. x86_64-gen.c +1 −0
  11. x86_64-link.c +14 −0
arm-gen.c+1−0
@@ -138,6 +138,7 @@ enum { · 137 unmodified lines
138138 #define R_DATA_32 R_ARM_ABS32
139139 #define R_DATA_PTR R_ARM_ABS32
140140 #define R_JMP_SLOT R_ARM_JUMP_SLOT
141+#define R_GLOB_DAT R_ARM_GLOB_DAT
141142 #define R_COPY R_ARM_COPY
142143
143144 #define ELF_START_ADDR 0x00008000
arm-link.c+52−2
@@ -1,6 +1,30 @@
11 #include "tcc.h"
22 #define HAVE_SECTION_RELOC
33
4+ST_DATA struct reloc_info relocs_info[] = {
5+ INIT_RELOC_INFO (R_ARM_PC24, 1, AUTO_GOTPLT_ENTRY, 0)
6+ INIT_RELOC_INFO (R_ARM_CALL, 1, AUTO_GOTPLT_ENTRY, 0)
7+ INIT_RELOC_INFO (R_ARM_JUMP24, 1, AUTO_GOTPLT_ENTRY, 0)
8+ INIT_RELOC_INFO (R_ARM_PLT32, 1, ALWAYS_GOTPLT_ENTRY, 0)
9+ INIT_RELOC_INFO (R_ARM_THM_PC22, 1, AUTO_GOTPLT_ENTRY, 0)
10+ INIT_RELOC_INFO (R_ARM_THM_JUMP24, 1, AUTO_GOTPLT_ENTRY, 0)
11+ INIT_RELOC_INFO (R_ARM_MOVT_ABS, 0, AUTO_GOTPLT_ENTRY, 0)
12+ INIT_RELOC_INFO (R_ARM_MOVW_ABS_NC, 0, AUTO_GOTPLT_ENTRY, 0)
13+ INIT_RELOC_INFO (R_ARM_THM_MOVT_ABS, 0, AUTO_GOTPLT_ENTRY, 0)
14+ INIT_RELOC_INFO (R_ARM_THM_MOVW_ABS_NC, 0, AUTO_GOTPLT_ENTRY, 0)
15+ INIT_RELOC_INFO (R_ARM_PREL31, 1, AUTO_GOTPLT_ENTRY, 0)
16+ INIT_RELOC_INFO (R_ARM_ABS32, 0, NO_GOTPLT_ENTRY, 0)
17+ INIT_RELOC_INFO (R_ARM_REL32, 0, AUTO_GOTPLT_ENTRY, 0)
18+ INIT_RELOC_INFO (R_ARM_GOTPC, 0, BUILD_GOT_ONLY, 0)
19+ INIT_RELOC_INFO (R_ARM_GOTOFF, 0, BUILD_GOT_ONLY, 0)
20+ INIT_RELOC_INFO (R_ARM_GOT32, 0, ALWAYS_GOTPLT_ENTRY, 0)
21+ INIT_RELOC_INFO (R_ARM_COPY, 0, NO_GOTPLT_ENTRY, 0)
22+ INIT_RELOC_INFO (R_ARM_V4BX, 1, AUTO_GOTPLT_ENTRY, 0)
23+ INIT_RELOC_INFO (R_ARM_GLOB_DAT, 0, NO_GOTPLT_ENTRY, 0)
24+ INIT_RELOC_INFO (R_ARM_JUMP_SLOT, 1, NO_GOTPLT_ENTRY, 0)
25+ INIT_RELOC_INFO (R_ARM_NONE, 0, NO_GOTPLT_ENTRY, 0)
26+};
27+
428 void relocate_init(Section *sr) {}
529
630 void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, addr_t val)
@@ -19,8 +43,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add · 12 unmodified lines
1943 {
2044 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
2145 x = (*(int *) ptr) & 0xffffff;
22− if (sym->st_shndx == SHN_UNDEF ||
23− s1->output_type == TCC_OUTPUT_MEMORY)
46+ if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_ABS)
2447 val = s1->plt->sh_addr;
2548 #ifdef DEBUG_RELOC
2649 printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
@@ -89,6 +112,33 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add · 62 unmodified lines
89112 (val < plt->sh_addr + plt->data_offset);
90113 is_call = (type == R_ARM_THM_PC22);
91114
115+ if (!to_thumb && !to_plt && !is_call) {
116+ int index;
117+ uint8_t *p;
118+ char *name, buf[1024];
119+ Section *text_section;
120+
121+ name = (char *) symtab_section->link->data + sym->st_name;
122+ text_section = s1->sections[sym->st_shndx];
123+ /* Modify reloc to target a thumb stub to switch to ARM */
124+ snprintf(buf, sizeof(buf), "%s_from_thumb", name);
125+ index = put_elf_sym(symtab_section,
126+ text_section->data_offset + 1,
127+ sym->st_size, sym->st_info, 0,
128+ sym->st_shndx, buf);
129+ to_thumb = 1;
130+ val = text_section->data_offset + 1;
131+ rel->r_info = ELFW(R_INFO)(index, type);
132+ /* Create a thumb stub function to switch to ARM mode */
133+ put_elf_reloc(symtab_section, text_section,
134+ text_section->data_offset + 4, R_ARM_JUMP24,
135+ sym_index);
136+ p = section_ptr_add(text_section, 8);
137+ write32le(p, 0x4778); /* bx pc */
138+ write32le(p+2, 0x46c0); /* nop */
139+ write32le(p+4, 0xeafffffe); /* b $sym */
140+ }
141+
92142 /* Compute final offset */
93143 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
94144 x -= 4;
arm64-gen.c+1−0
@@ -48,6 +48,7 @@ · 47 unmodified lines
4848 #define R_DATA_32 R_AARCH64_ABS32
4949 #define R_DATA_PTR R_AARCH64_ABS64
5050 #define R_JMP_SLOT R_AARCH64_JUMP_SLOT
51+#define R_GLOB_DAT R_AARCH64_GLOB_DAT
5152 #define R_COPY R_AARCH64_COPY
5253
5354 #define ELF_START_ADDR 0x00400000
arm64-link.c+18−1
@@ -1,6 +1,23 @@
11 #include "tcc.h"
22 #define HAVE_SECTION_RELOC
33
4+ST_DATA struct reloc_info relocs_info[] = {
5+ INIT_RELOC_INFO (R_AARCH64_ABS32, 0, NO_GOTPLT_ENTRY, 0)
6+ INIT_RELOC_INFO (R_AARCH64_ABS64, 0, NO_GOTPLT_ENTRY, 0)
7+ INIT_RELOC_INFO (R_AARCH64_MOVW_UABS_G0_NC, 0, NO_GOTPLT_ENTRY, 0)
8+ INIT_RELOC_INFO (R_AARCH64_MOVW_UABS_G1_NC, 0, NO_GOTPLT_ENTRY, 0)
9+ INIT_RELOC_INFO (R_AARCH64_MOVW_UABS_G2_NC, 0, NO_GOTPLT_ENTRY, 0)
10+ INIT_RELOC_INFO (R_AARCH64_MOVW_UABS_G3, 0, NO_GOTPLT_ENTRY, 0)
11+ INIT_RELOC_INFO (R_AARCH64_ADR_PREL_PG_HI21, 0, NO_GOTPLT_ENTRY, 0)
12+ INIT_RELOC_INFO (R_AARCH64_ADD_ABS_LO12_NC, 0, NO_GOTPLT_ENTRY, 0)
13+ INIT_RELOC_INFO (R_AARCH64_JUMP26, 1, AUTO_GOTPLT_ENTRY, 1)
14+ INIT_RELOC_INFO (R_AARCH64_CALL26, 1, AUTO_GOTPLT_ENTRY, 1)
15+ INIT_RELOC_INFO (R_AARCH64_ADR_GOT_PAGE, 0, ALWAYS_GOTPLT_ENTRY, 0)
16+ INIT_RELOC_INFO (R_AARCH64_LD64_GOT_LO12_NC, 0, ALWAYS_GOTPLT_ENTRY, 0)
17+ INIT_RELOC_INFO (R_AARCH64_GLOB_DAT, 0, NO_GOTPLT_ENTRY, 0)
18+ INIT_RELOC_INFO (R_AARCH64_JUMP_SLOT, 1, NO_GOTPLT_ENTRY, 0)
19+};
20+
421 void relocate_init(Section *sr) {}
522
623 void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, addr_t val)
@@ -51,7 +68,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add · 44 unmodified lines
5168 /* This check must match the one in build_got_entries, testing
5269 if we really need a PLT slot. */
5370 if (sym->st_shndx == SHN_UNDEF ||
54− s1->output_type == TCC_OUTPUT_MEMORY)
71+ sym->st_shndx == SHN_ABS)
5572 /* We've put the PLT slot offset into r_addend when generating
5673 it, and that's what we must use as relocation value (adjusted
5774 by section offset of course). */
c67-gen.c+1−0
@@ -117,6 +117,7 @@ enum { · 116 unmodified lines
117117 #define R_DATA_32 R_C60_32
118118 #define R_DATA_PTR R_C60_32
119119 #define R_JMP_SLOT R_C60_JMP_SLOT
120+#define R_GLOB_DAT R_C60_GLOB_DAT
120121 #define R_COPY R_C60_COPY
121122
122123 #define ELF_START_ADDR 0x00000400
i386-gen.c+1−0
@@ -82,6 +82,7 @@ enum { · 81 unmodified lines
8282 #define R_DATA_32 R_386_32
8383 #define R_DATA_PTR R_386_32
8484 #define R_JMP_SLOT R_386_JMP_SLOT
85+#define R_GLOB_DAT R_386_GLOB_DAT
8586 #define R_COPY R_386_COPY
8687
8788 #define ELF_START_ADDR 0x08048000
i386-link.c+13−0
@@ -2,6 +2,19 @@ · 1 unmodified line
22 #define HAVE_SECTION_RELOC
33
44 static ElfW_Rel *qrel; /* ptr to next reloc entry reused */
5+ST_DATA struct reloc_info relocs_info[] = {
6+ INIT_RELOC_INFO (R_386_32, 0, NO_GOTPLT_ENTRY, 0)
7+ INIT_RELOC_INFO (R_386_PC32, 1, AUTO_GOTPLT_ENTRY, 0)
8+ INIT_RELOC_INFO (R_386_PLT32, 1, ALWAYS_GOTPLT_ENTRY, 0)
9+ INIT_RELOC_INFO (R_386_GLOB_DAT, 0, NO_GOTPLT_ENTRY, 0)
10+ INIT_RELOC_INFO (R_386_JMP_SLOT, 1, NO_GOTPLT_ENTRY, 0)
11+ INIT_RELOC_INFO (R_386_GOTPC, 0, BUILD_GOT_ONLY, 0)
12+ INIT_RELOC_INFO (R_386_GOTOFF, 0, BUILD_GOT_ONLY, 0)
13+ INIT_RELOC_INFO (R_386_GOT32, 0, ALWAYS_GOTPLT_ENTRY, 0)
14+ INIT_RELOC_INFO (R_386_GOT32X, 0, ALWAYS_GOTPLT_ENTRY, 0)
15+ INIT_RELOC_INFO (R_386_16, 0, NO_GOTPLT_ENTRY, 0)
16+ INIT_RELOC_INFO (R_386_PC16, 1, AUTO_GOTPLT_ENTRY, 0)
17+};
518
619 void relocate_init(Section *sr)
720 {
tcc.h+20−0
@@ -1305,6 +1305,26 @@ typedef struct { · 1304 unmodified lines
13051305 unsigned int n_value; /* value of symbol */
13061306 } Stab_Sym;
13071307
1308+/* Wether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so
1309+ that unknown relocation don't create a GOT or PLT entry */
1310+enum gotplt_entry {
1311+ NO_GOTPLT_ENTRY, /* never generate (eg. GLOB_DAT & JMP_SLOT relocs) */
1312+ BUILD_GOT_ONLY, /* only build GOT (eg. TPOFF relocs) */
1313+ AUTO_GOTPLT_ENTRY, /* generate if sym is UNDEF */
1314+ ALWAYS_GOTPLT_ENTRY /* always generate (eg. PLTOFF relocs) */
1315+};
1316+
1317+/* what kind of relocation is it */
1318+struct reloc_info {
1319+ int code_reloc; /* if false, that's a data reloc */
1320+ int gotplt_entry; /* wether and when to create a GOT/PLT entry */
1321+ int pltoff_addend; /* wether to store the PLT offset in addend */
1322+};
1323+
1324+#define INIT_RELOC_INFO(rtype, code_reloc, gotplt_entry, pltoff_addend) \
1325+ [rtype] = {code_reloc, gotplt_entry, pltoff_addend},
1326+ST_DATA struct reloc_info relocs_info[];
1327+
13081328 ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
13091329 ST_DATA Section *cur_text_section; /* current section where function code is generated */
13101330 #ifdef CONFIG_TCC_ASM
tccelf.c+57−208
@@ -1022,6 +1022,7 @@ ST_FUNC void build_got_entries(TCCState *s1) · 1021 unmodified lines
10221022 ElfW_Rel *rel;
10231023 ElfW(Sym) *sym;
10241024 int i, type, reloc_type, sym_index;
1025+ unsigned long ofs;
10251026
10261027 for(i = 1; i < s1->nb_sections; i++) {
10271028 s = s1->sections[i];
@@ -1034,222 +1035,70 @@ ST_FUNC void build_got_entries(TCCState *s1) · 6 unmodified lines
10341035 type = ELFW(R_TYPE)(rel->r_info);
10351036 sym_index = ELFW(R_SYM)(rel->r_info);
10361037 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1037− switch(type) {
1038−#if defined(TCC_TARGET_I386)
1039− case R_386_PC16:
1040− case R_386_PC32:
1041− case R_386_GOT32:
1042− case R_386_GOT32X:
1043− case R_386_GOTOFF:
1044− case R_386_GOTPC:
1045− case R_386_PLT32:
1046− if (sym->st_shndx != SHN_UNDEF && type != R_386_GOT32 &&
1047− type != R_386_GOT32X && type != R_386_GOTOFF &&
1048− type != R_386_GOTPC && type != R_386_PLT32)
1049− break;
1038+ if (relocs_info[type].gotplt_entry == NO_GOTPLT_ENTRY)
1039+ continue;
10501040
1051− if (!s1->got)
1052− build_got(s1);
1053−
1054− if (type != R_386_GOTOFF && type != R_386_GOTPC) {
1055− /* look at the symbol got offset. If none, then add one */
1056− if (type == R_386_GOT32 || type == R_386_GOT32X)
1057− reloc_type = R_386_GLOB_DAT;
1058− else
1059− reloc_type = R_386_JMP_SLOT;
1060− put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1061− sym_index);
1062− }
1063− break;
1064−#elif defined(TCC_TARGET_ARM)
1065− case R_ARM_PC24:
1066− case R_ARM_CALL:
1067− case R_ARM_JUMP24:
1068− case R_ARM_PLT32:
1069− case R_ARM_THM_PC22:
1070− case R_ARM_MOVT_ABS:
1071− case R_ARM_MOVW_ABS_NC:
1072− case R_ARM_THM_MOVT_ABS:
1073− case R_ARM_THM_MOVW_ABS_NC:
1074− case R_ARM_PREL31:
1075− case R_ARM_REL32:
1076− case R_ARM_GOTPC:
1077− case R_ARM_GOTOFF:
1078− case R_ARM_GOT32:
1079− case R_ARM_V4BX:
1080− if (sym->st_shndx != SHN_UNDEF && type != R_ARM_GOT32 &&
1081− type != R_ARM_GOTOFF && type != R_ARM_GOTPC &&
1082− type != R_ARM_PLT32)
1083− break;
1041+ /* Proceed with PLT/GOT [entry] creation if any of the following
1042+ condition is met:
1043+ - it is an undefined reference (dynamic relocation needed)
1044+ - symbol is absolute (probably created by tcc_add_symbol)
1045+ - relocation requires a PLT/GOT (BUILD_GOTPLT_ENTRY or
1046+ ALWAYS_GOTPLT_ENTRY). */
1047+ if (sym->st_shndx != SHN_UNDEF &&
1048+ sym->st_shndx != SHN_ABS &&
1049+ relocs_info[type].gotplt_entry == AUTO_GOTPLT_ENTRY)
1050+ continue;
10841051
1085− if (!s1->got)
1086− build_got(s1);
1087− if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC
1088− && (sym->st_shndx == SHN_UNDEF
1089− || s1->output_type == TCC_OUTPUT_MEMORY)) {
1090− unsigned long ofs;
1091− /* look at the symbol got offset. If none, then add one */
1092− if (type == R_ARM_GOT32 || type == R_ARM_MOVT_ABS ||
1093− type == R_ARM_MOVW_ABS_NC ||
1094− type == R_ARM_THM_MOVT_ABS ||
1095− type == R_ARM_THM_MOVW_ABS_NC || type == R_ARM_ABS32 ||
1096− type == R_ARM_REL32)
1097− reloc_type = R_ARM_GLOB_DAT;
1098− else
1099− reloc_type = R_ARM_JUMP_SLOT;
1100− ofs = put_got_entry(s1, reloc_type, sym->st_size,
1101− sym->st_info, sym_index);
1102−#ifdef DEBUG_RELOC
1103− printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1104− (char *) symtab_section->link->data + sym->st_name,
1105− type, sym->st_shndx, ofs);
1106−#endif
1107− if (type == R_ARM_PC24 || type == R_ARM_CALL ||
1108− type == R_ARM_JUMP24 || type == R_ARM_PLT32) {
1109− addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
1110− + rel->r_offset);
1111− /* x must be signed! */
1112− int x = *ptr & 0xffffff;
1113− x = (x << 8) >> 8;
1114− x <<= 2;
1115− x += ofs;
1116− x >>= 2;
1117−#ifdef DEBUG_RELOC
1118− printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
1119− (*ptr & 0xff000000) | x, x);
1052+#ifdef TCC_TARGET_X86_64
1053+ if (type == R_X86_64_PLT32 &&
1054+ ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT) {
1055+ rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
1056+ continue;
1057+ }
11201058 #endif
1121− *ptr = (*ptr & 0xff000000) | x;
1122− }
1123− }
1124− break;
1125− case R_ARM_THM_JUMP24:
1126− sym_index = ELFW(R_SYM)(rel->r_info);
1127− sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1128− /* We are relocating a jump from thumb code to arm code */
1129− if (sym->st_shndx != SHN_UNDEF && !(sym->st_value & 1)) {
1130− int index;
1131− uint8_t *p;
1132− char *name, buf[1024];
1133− Section *text_section;
1134−
1135− name = (char *) symtab_section->link->data + sym->st_name;
1136− text_section = s1->sections[sym->st_shndx];
1137− /* Modify reloc to target a thumb stub to switch to ARM */
1138− snprintf(buf, sizeof(buf), "%s_from_thumb", name);
1139− index = put_elf_sym(symtab_section,
1140− text_section->data_offset + 1,
1141− sym->st_size, sym->st_info, 0,
1142− sym->st_shndx, buf);
1143− rel->r_info = ELFW(R_INFO)(index, type);
1144− /* Create a thumb stub fonction to switch to ARM mode */
1145− put_elf_reloc(symtab_section, text_section,
1146− text_section->data_offset + 4, R_ARM_JUMP24,
1147− sym_index);
1148− p = section_ptr_add(text_section, 8);
1149− write32le(p, 0x4778); /* bx pc */
1150− write32le(p+2, 0x46c0); /* nop */
1151− write32le(p+4, 0xeafffffe); /* b $sym */
1152− }
1153−#elif defined(TCC_TARGET_ARM64)
1154− //xx Other cases may be required here:
1155− case R_AARCH64_ADR_GOT_PAGE:
1156− case R_AARCH64_LD64_GOT_LO12_NC:
1157− if (!s1->got)
1158− build_got(s1);
1159− sym_index = ELFW(R_SYM)(rel->r_info);
1160− sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1161− reloc_type = R_AARCH64_GLOB_DAT;
1162− put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1163− sym_index);
1164− break;
11651059
1166− case R_AARCH64_JUMP26:
1167− case R_AARCH64_CALL26:
1168− if (!s1->got)
1169− build_got(s1);
1170− sym_index = ELFW(R_SYM)(rel->r_info);
1171− sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1172− if (sym->st_shndx == SHN_UNDEF ||
1173− s1->output_type == TCC_OUTPUT_MEMORY) {
1174− unsigned long ofs;
1175− reloc_type = R_AARCH64_JUMP_SLOT;
1176− ofs = put_got_entry(s1, reloc_type, sym->st_size,
1177− sym->st_info, sym_index);
1178− /* We store the place of the generated PLT slot
1179− in our addend. */
1180− rel->r_addend += ofs;
1181− }
1182− break;
1183−#elif defined(TCC_TARGET_C67)
1184− case R_C60_GOT32:
1185− case R_C60_GOTOFF:
1186− case R_C60_GOTPC:
1187− case R_C60_PLT32:
1188− if (!s1->got)
1189− build_got(s1);
1190− if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1191− sym_index = ELFW(R_SYM)(rel->r_info);
1192− sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1193− /* look at the symbol got offset. If none, then add one */
1194− if (type == R_C60_GOT32)
1195− reloc_type = R_C60_GLOB_DAT;
1196− else
1197− reloc_type = R_C60_JMP_SLOT;
1198− put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1199− sym_index);
1200− }
1201− break;
1202−#elif defined(TCC_TARGET_X86_64)
1203− case R_X86_64_32:
1204− case R_X86_64_32S:
1205− case R_X86_64_64:
1206− case R_X86_64_PC32:
1207− case R_X86_64_GOT32:
1208− case R_X86_64_GOTTPOFF:
1209− case R_X86_64_GOTPCREL:
1210− case R_X86_64_GOTPCRELX:
1211− case R_X86_64_REX_GOTPCRELX:
1212− case R_X86_64_PLT32:
1213− sym_index = ELFW(R_SYM)(rel->r_info);
1214− sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1215− if ((type == R_X86_64_32 || type == R_X86_64_32S ||
1216− type == R_X86_64_64 || type == R_X86_64_PC32) &&
1217− sym->st_shndx != SHN_UNDEF)
1218− break;
1060+ if (!s1->got)
1061+ build_got(s1);
12191062
1220− if (type == R_X86_64_PLT32 &&
1221− ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT) {
1222− rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
1223− break;
1224− }
1063+ if (relocs_info[type].gotplt_entry == BUILD_GOT_ONLY)
1064+ continue;
12251065
1226− if (!s1->got)
1227− build_got(s1);
1228− if (type != R_X86_64_GOTTPOFF) {
1229− unsigned long ofs;
1230− /* look at the symbol got offset. If none, then add one */
1231− if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1232− type == R_X86_64_GOTPCRELX ||
1233− type == R_X86_64_REX_GOTPCRELX ||
1234− type == R_X86_64_32 || type == R_X86_64_32S ||
1235− type == R_X86_64_64)
1236− reloc_type = R_X86_64_GLOB_DAT;
1237− else
1238− reloc_type = R_X86_64_JUMP_SLOT;
1239− ofs = put_got_entry(s1, reloc_type, sym->st_size,
1240− sym->st_info, sym_index);
1241− if (type == R_X86_64_PLT32)
1242− /* We store the place of the generated PLT slot
1243− in our addend. */
1244− rel->r_addend += ofs;
1245− }
1246− break;
1247−#else
1248−#error unsupported CPU
1066+ if (relocs_info[type].code_reloc)
1067+ reloc_type = R_JMP_SLOT;
1068+ else
1069+ reloc_type = R_GLOB_DAT;
1070+ ofs = put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1071+ sym_index);
1072+
1073+#ifdef DEBUG_RELOC
1074+ printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1075+ (char *) symtab_section->link->data + sym->st_name, type,
1076+ sym->st_shndx, ofs);
12491077 #endif
1250− default:
1251− break;
1078+
1079+#if defined (TCC_TARGET_X86_64) || defined(TCC_TARGET_ARM64)
1080+ /* We store the place of the generated PLT slot in our addend. */
1081+ if (relocs_info[type].pltoff_addend)
1082+ rel->r_addend += ofs;
1083+
1084+#elif defined (TCC_TARGET_ARM)
1085+ if (type == R_ARM_PC24 || type == R_ARM_CALL ||
1086+ type == R_ARM_JUMP24 || type == R_ARM_PLT32) {
1087+ addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
1088+ + rel->r_offset);
1089+ /* x must be signed! */
1090+ int x = *ptr & 0xffffff;
1091+ x = (x << 8) >> 8;
1092+ x <<= 2;
1093+ x += ofs;
1094+ x >>= 2;
1095+#ifdef DEBUG_RELOC
1096+ printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
1097+ (*ptr & 0xff000000) | x, x);
1098+#endif
1099+ *ptr = (*ptr & 0xff000000) | x;
12521100 }
1101+#endif
12531102 }
12541103 }
12551104 }
x86_64-gen.c+1−0
@@ -110,6 +110,7 @@ enum { · 109 unmodified lines
110110 #define R_DATA_32 R_X86_64_32
111111 #define R_DATA_PTR R_X86_64_64
112112 #define R_JMP_SLOT R_X86_64_JUMP_SLOT
113+#define R_GLOB_DAT R_X86_64_GLOB_DAT
113114 #define R_COPY R_X86_64_COPY
114115
115116 #define ELF_START_ADDR 0x400000
x86_64-link.c+14−0
@@ -2,6 +2,20 @@ · 1 unmodified line
22 #define HAVE_SECTION_RELOC
33
44 static ElfW_Rel *qrel; /* ptr to next reloc entry reused */
5+ST_DATA struct reloc_info relocs_info[] = {
6+ INIT_RELOC_INFO (R_X86_64_64, 0, AUTO_GOTPLT_ENTRY, 0)
7+ INIT_RELOC_INFO (R_X86_64_32, 0, AUTO_GOTPLT_ENTRY, 0)
8+ INIT_RELOC_INFO (R_X86_64_32S, 0, AUTO_GOTPLT_ENTRY, 0)
9+ INIT_RELOC_INFO (R_X86_64_PC32, 1, AUTO_GOTPLT_ENTRY, 0)
10+ INIT_RELOC_INFO (R_X86_64_PLT32, 1, ALWAYS_GOTPLT_ENTRY, 1)
11+ INIT_RELOC_INFO (R_X86_64_GLOB_DAT, 0, NO_GOTPLT_ENTRY, 0)
12+ INIT_RELOC_INFO (R_X86_64_JUMP_SLOT, 1, NO_GOTPLT_ENTRY, 0)
13+ INIT_RELOC_INFO (R_X86_64_GOTPCREL, 0, ALWAYS_GOTPLT_ENTRY, 0)
14+ INIT_RELOC_INFO (R_X86_64_GOTPCRELX, 0, ALWAYS_GOTPLT_ENTRY, 0)
15+ INIT_RELOC_INFO (R_X86_64_REX_GOTPCRELX, 0, ALWAYS_GOTPLT_ENTRY, 0)
16+ INIT_RELOC_INFO (R_X86_64_GOTTPOFF, 0, BUILD_GOT_ONLY, 0)
17+ INIT_RELOC_INFO (R_X86_64_GOT32, 0, ALWAYS_GOTPLT_ENTRY, 0)
18+};
519
620 void relocate_init(Section *sr)
721 {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t