From 4c82b003420fabbb95e077866784badc1a49189b Mon Sep 17 00:00:00 2001 From: herman ten brugge Date: Tue, 17 May 2022 07:34:10 +0200 Subject: [PATCH] Update for elflint problems tccgen.c: - When __FUNCTION__ is used and no code is generated use symbol len = 0. tccelf.c: - If library is present in verneed it should be in DT_NEEDED. - @plt symbols should have size 0 - set _GLOBAL_OFFSET_TABLE_ st_size correct - Remove version symbol if new value present reported by elflint: __FUNCTION__ problem: section [19] '.symtab': symbol 2134 (L.195) does not fit completely in referenced section [14] '.data.ro' DT_NEEDED problem: section [26] '.gnu.version_r': entry 2 references unknown dependency @plt symbols should have size 0: section [22] '.symtab': symbol 36557 (r_core_config_init@plt) does not fit completely in referenced section [14] '.plt' _GLOBAL_OFFSET_TABLE_ size: section [44] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol size 4 does not match .got section size 736 Remove version symbol: section [25] '.gnu.version': symbol 86: version index 3 is for requested version This happened for example with bounds checking symbol malloc --- tccelf.c | 33 ++++++++++++++++++++++++++++++--- tccgen.c | 2 +- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/tccelf.c b/tccelf.c index ceb54b61..3f44a1cc 100644 --- a/tccelf.c +++ b/tccelf.c @@ -547,7 +547,7 @@ LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, static void version_add (TCCState *s1) { - int i; + int i, j; ElfW(Sym) *sym; ElfW(Verneed) *vn = NULL; Section *symtab; @@ -593,6 +593,14 @@ version_add (TCCState *s1) ElfW(Vernaux) *vna = 0; if (sv->out_index < 1) continue; + /* If present in verneed it should be in DT_NEEDED */ + for (j = 0; j < s1->nb_loaded_dlls; j++) { + DLLReference *dllref = s1->loaded_dlls[j]; + if (!strcmp(sv->lib, dllref->name)) { + dllref->level = 0; + break; + } + } vnofs = section_add(verneed_section, sizeof(*vn), 1); vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); vn->vn_version = 1; @@ -1137,7 +1145,7 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type, len = sizeof plt_name - 5; memcpy(plt_name, name, len); strcpy(plt_name + len, "@plt"); - attr->plt_sym = put_elf_sym(s1->symtab, attr->plt_offset, sym->st_size, + attr->plt_sym = put_elf_sym(s1->symtab, attr->plt_offset, 0, ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC), 0, s1->plt->sh_num, plt_name); } else { attr->got_offset = got_offset; @@ -2526,6 +2534,14 @@ static Section *create_bsd_note_section(TCCState *s1, } #endif +static void elf_patch_global_offset_size(TCCState *s1, Section *s) +{ + int sym_index; + + if ((sym_index = find_elf_sym(s, "_GLOBAL_OFFSET_TABLE_"))) + ((ElfW(Sym) *)s->data)[sym_index].st_size = s1->got->data_offset; +} + /* Output an elf, coff or binary file */ /* XXX: suppress unneeded sections */ static int elf_output_file(TCCState *s1, const char *filename) @@ -2589,7 +2605,8 @@ static int elf_output_file(TCCState *s1, const char *filename) dynamic->link = dynstr; dynamic->sh_entsize = sizeof(ElfW(Dyn)); - build_got(s1); + if (!s1->got) + build_got(s1); if (file_type == TCC_OUTPUT_EXE) { bind_exe_dynsyms(s1); @@ -2602,6 +2619,8 @@ static int elf_output_file(TCCState *s1, const char *filename) } } build_got_entries(s1); + elf_patch_global_offset_size(s1, symtab_section); + elf_patch_global_offset_size(s1, s1->dynsym); version_add (s1); } @@ -3065,6 +3084,14 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, sym->st_info, sym->st_other, sym->st_shndx, name); old_to_new_syms[i] = sym_index; +#ifndef ELF_OBJ_ONLY + /* Remove version symbol if new value present */ + sym_index = find_elf_sym(s1->dynsymtab_section, name); + if (sym_index && sym_index < nb_sym_to_version && + sym->st_shndx != SHN_UNDEF && + ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) + sym_to_version[sym_index] = -1; +#endif } /* third pass to patch relocation entries */ diff --git a/tccgen.c b/tccgen.c index 98295348..01afd89e 100644 --- a/tccgen.c +++ b/tccgen.c @@ -5328,7 +5328,7 @@ ST_FUNC void unary(void) type.t |= VT_ARRAY; type.ref->c = len; sec = rodata_section; - vpush_ref(&type, sec, sec->data_offset, len); + vpush_ref(&type, sec, sec->data_offset, NODATA_WANTED ? 0 : len); if (!NODATA_WANTED) memcpy(section_ptr_add(sec, len), funcname, len); next();