Currently GOT/PLT creation happens in two locations depending on whether the GOT/PLT [entry] is required by the symbol or the relocation: - bind_exe_dynsym for relocations to undefined symbol - build_got_entries/put_got_entry for relocations that require a GOT/PLT entry This commit consolidate GOT/PLT creation in build_got_entries by reducing bind_exe_dynsym's job to create a dynamic symbol for undefined symbols. build_got_entries then invoke put_got_entry if the symbol being relocated is undefined or the relocation asks for a PLT or GOT [entry]. put_got_entry is also modified to only export a symbol in the dynamic symbol table when we are in the case of PLT/GOT [entry] required by the relocation (since undefined symbol are already exported by bind_exe_dynsym).
Unified · Split
| @@ -13,7 +13,7 @@ ST_DATA struct reloc_info relocs_info[] = { · 12 unmodified lines | |||
| 13 | INIT_RELOC_INFO (R_ARM_THM_MOVT_ABS, 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) | 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) | 15 | INIT_RELOC_INFO (R_ARM_PREL31, 1, AUTO_GOTPLT_ENTRY, 0) |
| 16 | INIT_RELOC_INFO (R_ARM_ABS32, 0, NO_GOTPLT_ENTRY, 0) | 16 | INIT_RELOC_INFO (R_ARM_ABS32, 0, AUTO_GOTPLT_ENTRY, 0) |
| 17 | INIT_RELOC_INFO (R_ARM_REL32, 0, AUTO_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) | 18 | INIT_RELOC_INFO (R_ARM_GOTPC, 0, BUILD_GOT_ONLY, 0) |
| 19 | INIT_RELOC_INFO (R_ARM_GOTOFF, 0, BUILD_GOT_ONLY, 0) | 19 | INIT_RELOC_INFO (R_ARM_GOTOFF, 0, BUILD_GOT_ONLY, 0) |
| @@ -819,19 +819,19 @@ static void build_got(TCCState *s1) · 818 unmodified lines | |||
| 819 | in s1->symtab. When creating the dynamic symbol table entry for the GOT | 819 | in s1->symtab. When creating the dynamic symbol table entry for the GOT |
| 820 | relocation, use 'size' and 'info' for the corresponding symbol metadata. | 820 | relocation, use 'size' and 'info' for the corresponding symbol metadata. |
| 821 | Returns the offset of the GOT or (if any) PLT entry. */ | 821 | Returns the offset of the GOT or (if any) PLT entry. */ |
| 822 | static unsigned long put_got_entry(TCCState *s1, | 822 | static unsigned long put_got_entry(TCCState *s1, int dyn_reloc_type, |
| 823 | int reloc_type, unsigned long size, int info, | 823 | int reloc_type, unsigned long size, |
| 824 | int sym_index) | 824 | int info, int sym_index) |
| 825 | { | 825 | { |
| 826 | int index, need_plt_entry = 0; | 826 | int index, need_plt_entry = 0; |
| 827 | const char *name; | 827 | const char *name; |
| 828 | ElfW(Sym) *sym; | 828 | ElfW(Sym) *sym, *esym; |
| 829 | unsigned long offset; | 829 | unsigned long offset; |
| 830 | int *ptr; | 830 | int *ptr; |
| 831 | size_t got_offset; | 831 | size_t got_offset; |
| 832 | struct sym_attr *symattr; | 832 | struct sym_attr *symattr; |
| 833 | 833 | ||
| 834 | need_plt_entry = (reloc_type == R_JMP_SLOT); | 834 | need_plt_entry = (dyn_reloc_type == R_JMP_SLOT); |
| 835 | 835 | ||
| 836 | if (!s1->got) | 836 | if (!s1->got) |
| 837 | build_got(s1); | 837 | build_got(s1); |
| @@ -1001,13 +1001,19 @@ static unsigned long put_got_entry(TCCState *s1, · 163 unmodified lines | |||
| 1001 | /* create the dynamic symbol table entry that the relocation refers to | 1001 | /* create the dynamic symbol table entry that the relocation refers to |
| 1002 | in its r_info field to identify the symbol */ | 1002 | in its r_info field to identify the symbol */ |
| 1003 | /* XXX This might generate multiple syms for name. */ | 1003 | /* XXX This might generate multiple syms for name. */ |
| 1004 | index = put_elf_sym(s1->dynsym, offset, size, info, 0, sym->st_shndx, | 1004 | index = find_elf_sym (s1->dynsym, name); |
| 1005 | name); | 1005 | if (index) { |
| 1006 | put_elf_reloc(s1->dynsym, s1->got, got_offset, reloc_type, index); | 1006 | esym = (ElfW(Sym) *) s1->dynsym->data + index; |
| 1007 | } else { | 1007 | esym->st_value = offset; |
| 1008 | put_elf_reloc(symtab_section, s1->got, got_offset, reloc_type, | 1008 | |
| 1009 | } else if (s1->output_type == TCC_OUTPUT_MEMORY || | ||
| 1010 | relocs_info[reloc_type].gotplt_entry == ALWAYS_GOTPLT_ENTRY) | ||
| 1011 | index = put_elf_sym(s1->dynsym, offset, size, info, 0, | ||
| 1012 | sym->st_shndx, name); | ||
| 1013 | put_elf_reloc(s1->dynsym, s1->got, got_offset, dyn_reloc_type, index); | ||
| 1014 | } else | ||
| 1015 | put_elf_reloc(symtab_section, s1->got, got_offset, dyn_reloc_type, | ||
| 1009 | sym_index); | 1016 | sym_index); |
| 1010 | } | ||
| 1011 | 1017 | ||
| 1012 | if (need_plt_entry) | 1018 | if (need_plt_entry) |
| 1013 | return symattr->plt_offset; | 1019 | return symattr->plt_offset; |
| @@ -1067,8 +1073,8 @@ ST_FUNC void build_got_entries(TCCState *s1) · 53 unmodified lines | |||
| 1067 | reloc_type = R_JMP_SLOT; | 1073 | reloc_type = R_JMP_SLOT; |
| 1068 | else | 1074 | else |
| 1069 | reloc_type = R_GLOB_DAT; | 1075 | reloc_type = R_GLOB_DAT; |
| 1070 | ofs = put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, | 1076 | ofs = put_got_entry(s1, reloc_type, type, sym->st_size, |
| 1071 | sym_index); | 1077 | sym->st_info, sym_index); |
| 1072 | 1078 | ||
| 1073 | #ifdef DEBUG_RELOC | 1079 | #ifdef DEBUG_RELOC |
| 1074 | printf ("maybegot: %s, %d, %d --> ofs=0x%x\n", | 1080 | printf ("maybegot: %s, %d, %d --> ofs=0x%x\n", |
| @@ -1420,15 +1426,17 @@ static void bind_exe_dynsyms(TCCState *s1) · 345 unmodified lines | |||
| 1420 | * of the function wanted by the caller of dlsym instead of | 1426 | * of the function wanted by the caller of dlsym instead of |
| 1421 | * the address of the function that would return that | 1427 | * the address of the function that would return that |
| 1422 | * address */ | 1428 | * address */ |
| 1423 | put_got_entry(s1, R_JMP_SLOT, esym->st_size, | 1429 | put_elf_sym(s1->dynsym, 0, esym->st_size, |
| 1424 | ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), | 1430 | ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0, |
| 1425 | sym - (ElfW(Sym) *)symtab_section->data); | 1431 | name); |
| 1426 | } else if (type == STT_OBJECT) { | 1432 | } else if (type == STT_OBJECT) { |
| 1427 | unsigned long offset; | 1433 | unsigned long offset; |
| 1428 | ElfW(Sym) *dynsym; | 1434 | ElfW(Sym) *dynsym; |
| 1429 | offset = bss_section->data_offset; | 1435 | offset = bss_section->data_offset; |
| 1430 | /* XXX: which alignment ? */ | 1436 | /* XXX: which alignment ? */ |
| 1431 | offset = (offset + 16 - 1) & -16; | 1437 | offset = (offset + 16 - 1) & -16; |
| 1438 | set_elf_sym (s1->symtab, offset, esym->st_size, | ||
| 1439 | esym->st_info, 0, bss_section->sh_num, name); | ||
| 1432 | index = put_elf_sym(s1->dynsym, offset, esym->st_size, | 1440 | index = put_elf_sym(s1->dynsym, offset, esym->st_size, |
| 1433 | esym->st_info, 0, bss_section->sh_num, | 1441 | esym->st_info, 0, bss_section->sh_num, |
| 1434 | name); | 1442 | name); |