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).
This commit is contained in:
Thomas Preud'homme 2016-11-17 23:00:11 +00:00
parent 1c811a4d1d
commit a11b0a67e3
2 changed files with 25 additions and 17 deletions

View File

@ -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_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_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_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_REL32, 0, AUTO_GOTPLT_ENTRY, 0)
INIT_RELOC_INFO (R_ARM_GOTPC, 0, BUILD_GOT_ONLY, 0) INIT_RELOC_INFO (R_ARM_GOTPC, 0, BUILD_GOT_ONLY, 0)
INIT_RELOC_INFO (R_ARM_GOTOFF, 0, BUILD_GOT_ONLY, 0) INIT_RELOC_INFO (R_ARM_GOTOFF, 0, BUILD_GOT_ONLY, 0)

View File

@ -819,19 +819,19 @@ static void build_got(TCCState *s1)
in s1->symtab. When creating the dynamic symbol table entry for the GOT in s1->symtab. When creating the dynamic symbol table entry for the GOT
relocation, use 'size' and 'info' for the corresponding symbol metadata. relocation, use 'size' and 'info' for the corresponding symbol metadata.
Returns the offset of the GOT or (if any) PLT entry. */ Returns the offset of the GOT or (if any) PLT entry. */
static unsigned long put_got_entry(TCCState *s1, static unsigned long put_got_entry(TCCState *s1, int dyn_reloc_type,
int reloc_type, unsigned long size, int info, int reloc_type, unsigned long size,
int sym_index) int info, int sym_index)
{ {
int index, need_plt_entry = 0; int index, need_plt_entry = 0;
const char *name; const char *name;
ElfW(Sym) *sym; ElfW(Sym) *sym, *esym;
unsigned long offset; unsigned long offset;
int *ptr; int *ptr;
size_t got_offset; size_t got_offset;
struct sym_attr *symattr; struct sym_attr *symattr;
need_plt_entry = (reloc_type == R_JMP_SLOT); need_plt_entry = (dyn_reloc_type == R_JMP_SLOT);
if (!s1->got) if (!s1->got)
build_got(s1); 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 /* create the dynamic symbol table entry that the relocation refers to
in its r_info field to identify the symbol */ in its r_info field to identify the symbol */
/* XXX This might generate multiple syms for name. */ /* XXX This might generate multiple syms for name. */
index = put_elf_sym(s1->dynsym, offset, size, info, 0, sym->st_shndx, index = find_elf_sym (s1->dynsym, name);
name); if (index) {
put_elf_reloc(s1->dynsym, s1->got, got_offset, reloc_type, index); esym = (ElfW(Sym) *) s1->dynsym->data + index;
} else { esym->st_value = offset;
put_elf_reloc(symtab_section, s1->got, got_offset, reloc_type,
} 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); sym_index);
}
if (need_plt_entry) if (need_plt_entry)
return symattr->plt_offset; return symattr->plt_offset;
@ -1067,8 +1073,8 @@ ST_FUNC void build_got_entries(TCCState *s1)
reloc_type = R_JMP_SLOT; reloc_type = R_JMP_SLOT;
else else
reloc_type = R_GLOB_DAT; reloc_type = R_GLOB_DAT;
ofs = put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, ofs = put_got_entry(s1, reloc_type, type, sym->st_size,
sym_index); sym->st_info, sym_index);
#ifdef DEBUG_RELOC #ifdef DEBUG_RELOC
printf ("maybegot: %s, %d, %d --> ofs=0x%x\n", 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 * of the function wanted by the caller of dlsym instead of
* the address of the function that would return that * the address of the function that would return that
* address */ * address */
put_got_entry(s1, R_JMP_SLOT, esym->st_size, put_elf_sym(s1->dynsym, 0, esym->st_size,
ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0,
sym - (ElfW(Sym) *)symtab_section->data); name);
} else if (type == STT_OBJECT) { } else if (type == STT_OBJECT) {
unsigned long offset; unsigned long offset;
ElfW(Sym) *dynsym; ElfW(Sym) *dynsym;
offset = bss_section->data_offset; offset = bss_section->data_offset;
/* XXX: which alignment ? */ /* XXX: which alignment ? */
offset = (offset + 16 - 1) & -16; 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, index = put_elf_sym(s1->dynsym, offset, esym->st_size,
esym->st_info, 0, bss_section->sh_num, esym->st_info, 0, bss_section->sh_num,
name); name);