Factor most of common logic between targets in build_got_entries by defining target specific info into structures in the backends.
Unified · Split
| @@ -138,6 +138,7 @@ enum { · 137 unmodified lines | ||
| 138 | 138 | #define R_DATA_32 R_ARM_ABS32 |
| 139 | 139 | #define R_DATA_PTR R_ARM_ABS32 |
| 140 | 140 | #define R_JMP_SLOT R_ARM_JUMP_SLOT |
| 141 | +#define R_GLOB_DAT R_ARM_GLOB_DAT | |
| 141 | 142 | #define R_COPY R_ARM_COPY |
| 142 | 143 | |
| 143 | 144 | #define ELF_START_ADDR 0x00008000 |
| @@ -1,6 +1,30 @@ | ||
| 1 | 1 | #include "tcc.h" |
| 2 | 2 | #define HAVE_SECTION_RELOC |
| 3 | 3 | |
| 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 | + | |
| 4 | 28 | void relocate_init(Section *sr) {} |
| 5 | 29 | |
| 6 | 30 | 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 | ||
| 19 | 43 | { |
| 20 | 44 | int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko; |
| 21 | 45 | 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) | |
| 24 | 47 | val = s1->plt->sh_addr; |
| 25 | 48 | #ifdef DEBUG_RELOC |
| 26 | 49 | 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 | ||
| 89 | 112 | (val < plt->sh_addr + plt->data_offset); |
| 90 | 113 | is_call = (type == R_ARM_THM_PC22); |
| 91 | 114 | |
| 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 | + | |
| 92 | 142 | /* Compute final offset */ |
| 93 | 143 | if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */ |
| 94 | 144 | x -= 4; |
| @@ -48,6 +48,7 @@ · 47 unmodified lines | ||
| 48 | 48 | #define R_DATA_32 R_AARCH64_ABS32 |
| 49 | 49 | #define R_DATA_PTR R_AARCH64_ABS64 |
| 50 | 50 | #define R_JMP_SLOT R_AARCH64_JUMP_SLOT |
| 51 | +#define R_GLOB_DAT R_AARCH64_GLOB_DAT | |
| 51 | 52 | #define R_COPY R_AARCH64_COPY |
| 52 | 53 | |
| 53 | 54 | #define ELF_START_ADDR 0x00400000 |
| @@ -1,6 +1,23 @@ | ||
| 1 | 1 | #include "tcc.h" |
| 2 | 2 | #define HAVE_SECTION_RELOC |
| 3 | 3 | |
| 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 | + | |
| 4 | 21 | void relocate_init(Section *sr) {} |
| 5 | 22 | |
| 6 | 23 | 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 | ||
| 51 | 68 | /* This check must match the one in build_got_entries, testing |
| 52 | 69 | if we really need a PLT slot. */ |
| 53 | 70 | if (sym->st_shndx == SHN_UNDEF || |
| 54 | − s1->output_type == TCC_OUTPUT_MEMORY) | |
| 71 | + sym->st_shndx == SHN_ABS) | |
| 55 | 72 | /* We've put the PLT slot offset into r_addend when generating |
| 56 | 73 | it, and that's what we must use as relocation value (adjusted |
| 57 | 74 | by section offset of course). */ |
| @@ -117,6 +117,7 @@ enum { · 116 unmodified lines | ||
| 117 | 117 | #define R_DATA_32 R_C60_32 |
| 118 | 118 | #define R_DATA_PTR R_C60_32 |
| 119 | 119 | #define R_JMP_SLOT R_C60_JMP_SLOT |
| 120 | +#define R_GLOB_DAT R_C60_GLOB_DAT | |
| 120 | 121 | #define R_COPY R_C60_COPY |
| 121 | 122 | |
| 122 | 123 | #define ELF_START_ADDR 0x00000400 |
| @@ -82,6 +82,7 @@ enum { · 81 unmodified lines | ||
| 82 | 82 | #define R_DATA_32 R_386_32 |
| 83 | 83 | #define R_DATA_PTR R_386_32 |
| 84 | 84 | #define R_JMP_SLOT R_386_JMP_SLOT |
| 85 | +#define R_GLOB_DAT R_386_GLOB_DAT | |
| 85 | 86 | #define R_COPY R_386_COPY |
| 86 | 87 | |
| 87 | 88 | #define ELF_START_ADDR 0x08048000 |
| @@ -2,6 +2,19 @@ · 1 unmodified line | ||
| 2 | 2 | #define HAVE_SECTION_RELOC |
| 3 | 3 | |
| 4 | 4 | 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 | +}; | |
| 5 | 18 | |
| 6 | 19 | void relocate_init(Section *sr) |
| 7 | 20 | { |
| @@ -1305,6 +1305,26 @@ typedef struct { · 1304 unmodified lines | ||
| 1305 | 1305 | unsigned int n_value; /* value of symbol */ |
| 1306 | 1306 | } Stab_Sym; |
| 1307 | 1307 | |
| 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 | + | |
| 1308 | 1328 | ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ |
| 1309 | 1329 | ST_DATA Section *cur_text_section; /* current section where function code is generated */ |
| 1310 | 1330 | #ifdef CONFIG_TCC_ASM |
| @@ -1022,6 +1022,7 @@ ST_FUNC void build_got_entries(TCCState *s1) · 1021 unmodified lines | ||
| 1022 | 1022 | ElfW_Rel *rel; |
| 1023 | 1023 | ElfW(Sym) *sym; |
| 1024 | 1024 | int i, type, reloc_type, sym_index; |
| 1025 | + unsigned long ofs; | |
| 1025 | 1026 | |
| 1026 | 1027 | for(i = 1; i < s1->nb_sections; i++) { |
| 1027 | 1028 | s = s1->sections[i]; |
| @@ -1034,222 +1035,70 @@ ST_FUNC void build_got_entries(TCCState *s1) · 6 unmodified lines | ||
| 1034 | 1035 | type = ELFW(R_TYPE)(rel->r_info); |
| 1035 | 1036 | sym_index = ELFW(R_SYM)(rel->r_info); |
| 1036 | 1037 | 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; | |
| 1050 | 1040 | |
| 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; | |
| 1084 | 1051 | |
| 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 | + } | |
| 1120 | 1058 | #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; | |
| 1165 | 1059 | |
| 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); | |
| 1219 | 1062 | |
| 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; | |
| 1225 | 1065 | |
| 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); | |
| 1249 | 1077 | #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; | |
| 1252 | 1100 | } |
| 1101 | +#endif | |
| 1253 | 1102 | } |
| 1254 | 1103 | } |
| 1255 | 1104 | } |
| @@ -110,6 +110,7 @@ enum { · 109 unmodified lines | ||
| 110 | 110 | #define R_DATA_32 R_X86_64_32 |
| 111 | 111 | #define R_DATA_PTR R_X86_64_64 |
| 112 | 112 | #define R_JMP_SLOT R_X86_64_JUMP_SLOT |
| 113 | +#define R_GLOB_DAT R_X86_64_GLOB_DAT | |
| 113 | 114 | #define R_COPY R_X86_64_COPY |
| 114 | 115 | |
| 115 | 116 | #define ELF_START_ADDR 0x400000 |
| @@ -2,6 +2,20 @@ · 1 unmodified line | ||
| 2 | 2 | #define HAVE_SECTION_RELOC |
| 3 | 3 | |
| 4 | 4 | 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 | +}; | |
| 5 | 19 | |
| 6 | 20 | void relocate_init(Section *sr) |
| 7 | 21 | { |