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 | 13 | INIT_RELOC_INFO (R_ARM_THM_MOVT_ABS, 0, AUTO_GOTPLT_ENTRY, 0) |
| 14 | 14 | INIT_RELOC_INFO (R_ARM_THM_MOVW_ABS_NC, 0, AUTO_GOTPLT_ENTRY, 0) |
| 15 | 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 | 17 | INIT_RELOC_INFO (R_ARM_REL32, 0, AUTO_GOTPLT_ENTRY, 0) |
| 18 | 18 | INIT_RELOC_INFO (R_ARM_GOTPC, 0, BUILD_GOT_ONLY, 0) |
| 19 | 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 | 819 | in s1->symtab. When creating the dynamic symbol table entry for the GOT |
| 820 | 820 | relocation, use 'size' and 'info' for the corresponding symbol metadata. |
| 821 | 821 | Returns the offset of the GOT or (if any) PLT entry. */ |
| 822 | −static unsigned long put_got_entry(TCCState *s1, | |
| 823 | − int reloc_type, unsigned long size, int info, | |
| 824 | − int sym_index) | |
| 822 | +static unsigned long put_got_entry(TCCState *s1, int dyn_reloc_type, | |
| 823 | + int reloc_type, unsigned long size, | |
| 824 | + int info, int sym_index) | |
| 825 | 825 | { |
| 826 | 826 | int index, need_plt_entry = 0; |
| 827 | 827 | const char *name; |
| 828 | − ElfW(Sym) *sym; | |
| 828 | + ElfW(Sym) *sym, *esym; | |
| 829 | 829 | unsigned long offset; |
| 830 | 830 | int *ptr; |
| 831 | 831 | size_t got_offset; |
| 832 | 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 | 836 | if (!s1->got) |
| 837 | 837 | build_got(s1); |
| @@ -1001,13 +1001,19 @@ static unsigned long put_got_entry(TCCState *s1, · 163 unmodified lines | ||
| 1001 | 1001 | /* create the dynamic symbol table entry that the relocation refers to |
| 1002 | 1002 | in its r_info field to identify the symbol */ |
| 1003 | 1003 | /* XXX This might generate multiple syms for name. */ |
| 1004 | − index = put_elf_sym(s1->dynsym, offset, size, info, 0, sym->st_shndx, | |
| 1005 | − name); | |
| 1006 | − put_elf_reloc(s1->dynsym, s1->got, got_offset, reloc_type, index); | |
| 1007 | − } else { | |
| 1008 | − put_elf_reloc(symtab_section, s1->got, got_offset, reloc_type, | |
| 1004 | + index = find_elf_sym (s1->dynsym, name); | |
| 1005 | + if (index) { | |
| 1006 | + esym = (ElfW(Sym) *) s1->dynsym->data + index; | |
| 1007 | + esym->st_value = offset; | |
| 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 | 1016 | sym_index); |
| 1010 | − } | |
| 1011 | 1017 | |
| 1012 | 1018 | if (need_plt_entry) |
| 1013 | 1019 | return symattr->plt_offset; |
| @@ -1067,8 +1073,8 @@ ST_FUNC void build_got_entries(TCCState *s1) · 53 unmodified lines | ||
| 1067 | 1073 | reloc_type = R_JMP_SLOT; |
| 1068 | 1074 | else |
| 1069 | 1075 | reloc_type = R_GLOB_DAT; |
| 1070 | − ofs = put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, | |
| 1071 | − sym_index); | |
| 1076 | + ofs = put_got_entry(s1, reloc_type, type, sym->st_size, | |
| 1077 | + sym->st_info, sym_index); | |
| 1072 | 1078 | |
| 1073 | 1079 | #ifdef DEBUG_RELOC |
| 1074 | 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 | 1426 | * of the function wanted by the caller of dlsym instead of |
| 1421 | 1427 | * the address of the function that would return that |
| 1422 | 1428 | * address */ |
| 1423 | − put_got_entry(s1, R_JMP_SLOT, esym->st_size, | |
| 1424 | − ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), | |
| 1425 | − sym - (ElfW(Sym) *)symtab_section->data); | |
| 1429 | + put_elf_sym(s1->dynsym, 0, esym->st_size, | |
| 1430 | + ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0, | |
| 1431 | + name); | |
| 1426 | 1432 | } else if (type == STT_OBJECT) { |
| 1427 | 1433 | unsigned long offset; |
| 1428 | 1434 | ElfW(Sym) *dynsym; |
| 1429 | 1435 | offset = bss_section->data_offset; |
| 1430 | 1436 | /* XXX: which alignment ? */ |
| 1431 | 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 | 1440 | index = put_elf_sym(s1->dynsym, offset, esym->st_size, |
| 1433 | 1441 | esym->st_info, 0, bss_section->sh_num, |
| 1434 | 1442 | name); |