diff options
| author | Thomas Preud'homme <robotux@celest.fr> | 2016-11-17 23:00:11 +0000 |
|---|---|---|
| committer | Thomas Preud'homme <robotux@celest.fr> | 2016-12-03 17:26:51 +0000 |
| commit | a11b0a67e368f86751431f827db3ca85682b9864 (patch) | |
| tree | 4ca5011b3dfc25ed1b7c8ec7321ebd0cc62e6395 | |
| parent | 1c811a4d1db56e4ed4fefa99ea39c679aa0c29f0 (diff) | |
| download | tinycc-a11b0a67e368f86751431f827db3ca85682b9864.tar.gz tinycc-a11b0a67e368f86751431f827db3ca85682b9864.tar.bz2 | |
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).
| -rw-r--r-- | arm-link.c | 2 | ||||
| -rw-r--r-- | tccelf.c | 40 |
2 files changed, 25 insertions, 17 deletions
@@ -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) @@ -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); |
