From a11b0a67e368f86751431f827db3ca85682b9864 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Thu, 17 Nov 2016 23:00:11 +0000 Subject: [PATCH] Consolidate GOT creation in build_got_entries 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). --- arm-link.c | 2 +- tccelf.c | 40 ++++++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/arm-link.c b/arm-link.c index ec989bb..7d94048 100644 --- a/arm-link.c +++ b/arm-link.c @@ -13,7 +13,7 @@ ST_DATA struct reloc_info relocs_info[] = { INIT_RELOC_INFO (R_ARM_THM_MOVT_ABS, 0, AUTO_GOTPLT_ENTRY, 0) INIT_RELOC_INFO (R_ARM_THM_MOVW_ABS_NC, 0, AUTO_GOTPLT_ENTRY, 0) INIT_RELOC_INFO (R_ARM_PREL31, 1, AUTO_GOTPLT_ENTRY, 0) - INIT_RELOC_INFO (R_ARM_ABS32, 0, NO_GOTPLT_ENTRY, 0) + INIT_RELOC_INFO (R_ARM_ABS32, 0, AUTO_GOTPLT_ENTRY, 0) INIT_RELOC_INFO (R_ARM_REL32, 0, AUTO_GOTPLT_ENTRY, 0) INIT_RELOC_INFO (R_ARM_GOTPC, 0, BUILD_GOT_ONLY, 0) INIT_RELOC_INFO (R_ARM_GOTOFF, 0, BUILD_GOT_ONLY, 0) diff --git a/tccelf.c b/tccelf.c index 8bab121..4af7a08 100644 --- a/tccelf.c +++ b/tccelf.c @@ -819,19 +819,19 @@ static void build_got(TCCState *s1) in s1->symtab. When creating the dynamic symbol table entry for the GOT relocation, use 'size' and 'info' for the corresponding symbol metadata. Returns the offset of the GOT or (if any) PLT entry. */ -static unsigned long put_got_entry(TCCState *s1, - int reloc_type, unsigned long size, int info, - int sym_index) +static unsigned long put_got_entry(TCCState *s1, int dyn_reloc_type, + int reloc_type, unsigned long size, + int info, int sym_index) { int index, need_plt_entry = 0; const char *name; - ElfW(Sym) *sym; + ElfW(Sym) *sym, *esym; unsigned long offset; int *ptr; size_t got_offset; struct sym_attr *symattr; - need_plt_entry = (reloc_type == R_JMP_SLOT); + need_plt_entry = (dyn_reloc_type == R_JMP_SLOT); if (!s1->got) build_got(s1); @@ -1001,13 +1001,19 @@ static unsigned long put_got_entry(TCCState *s1, /* create the dynamic symbol table entry that the relocation refers to in its r_info field to identify the symbol */ /* XXX This might generate multiple syms for name. */ - index = put_elf_sym(s1->dynsym, offset, size, info, 0, sym->st_shndx, - name); - put_elf_reloc(s1->dynsym, s1->got, got_offset, reloc_type, index); - } else { - put_elf_reloc(symtab_section, s1->got, got_offset, reloc_type, + index = find_elf_sym (s1->dynsym, name); + if (index) { + esym = (ElfW(Sym) *) s1->dynsym->data + index; + esym->st_value = offset; + + } else if (s1->output_type == TCC_OUTPUT_MEMORY || + relocs_info[reloc_type].gotplt_entry == ALWAYS_GOTPLT_ENTRY) + index = put_elf_sym(s1->dynsym, offset, size, info, 0, + sym->st_shndx, name); + put_elf_reloc(s1->dynsym, s1->got, got_offset, dyn_reloc_type, index); + } else + put_elf_reloc(symtab_section, s1->got, got_offset, dyn_reloc_type, sym_index); - } if (need_plt_entry) return symattr->plt_offset; @@ -1067,8 +1073,8 @@ ST_FUNC void build_got_entries(TCCState *s1) reloc_type = R_JMP_SLOT; else reloc_type = R_GLOB_DAT; - ofs = put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, - sym_index); + ofs = put_got_entry(s1, reloc_type, type, sym->st_size, + sym->st_info, sym_index); #ifdef DEBUG_RELOC printf ("maybegot: %s, %d, %d --> ofs=0x%x\n", @@ -1420,15 +1426,17 @@ static void bind_exe_dynsyms(TCCState *s1) * of the function wanted by the caller of dlsym instead of * the address of the function that would return that * address */ - put_got_entry(s1, R_JMP_SLOT, esym->st_size, - ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), - sym - (ElfW(Sym) *)symtab_section->data); + put_elf_sym(s1->dynsym, 0, esym->st_size, + ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0, + name); } else if (type == STT_OBJECT) { unsigned long offset; ElfW(Sym) *dynsym; offset = bss_section->data_offset; /* XXX: which alignment ? */ offset = (offset + 16 - 1) & -16; + set_elf_sym (s1->symtab, offset, esym->st_size, + esym->st_info, 0, bss_section->sh_num, name); index = put_elf_sym(s1->dynsym, offset, esym->st_size, esym->st_info, 0, bss_section->sh_num, name);