[binutils-gdb] readelf: fold get_{32,64}bit_elf_symbols()
Jan Beulich via Binutils-cvs <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=73323df07c7c10ffe91297712a96bcf7c59f6ca9 commit 73323df07c7c10ffe91297712a96bcf7c59f6ca9 Author: Jan Beulich <[email protected]> Date: Fri Aug 14 10:55:04 2026 +0200 readelf: fold get_{32,64}bit_elf_symbols() PR binutils/34356 They're identical except for the types used and the order of fields processed. The latter doesn't matter for correctness, and the former can be addressed by compiling the same code twice. Diff: --- binutils/readelf-nn.c | 118 +++++++++++++++++++++++++ binutils/readelf.c | 240 +------------------------------------------------- 2 files changed, 120 insertions(+), 238 deletions(-) diff --git a/binutils/readelf-nn.c b/binutils/readelf-nn.c index f86f6eeeb78..50d9605892e 100644 --- a/binutils/readelf-nn.c +++ b/binutils/readelf-nn.c @@ -162,4 +162,122 @@ ElfXX(_get_section_headers) (Filedata * filedata, bool probe) return true; } +static Elf_Internal_Sym * +ElfXX(_get_symbols) (Filedata *filedata, const Elf_Internal_Shdr *section, + uint64_t *num_syms_return) +{ + uint64_t number = 0; + ElfXX(_External_Sym) * esyms = NULL; + Elf_External_Sym_Shndx * shndx = NULL; + Elf_Internal_Sym * isyms = NULL; + Elf_Internal_Sym * psym; + unsigned int j; + elf_section_list * entry; + + if (section->sh_size == 0) + { + if (num_syms_return != NULL) + * num_syms_return = 0; + return NULL; + } + + /* Run some sanity checks first. */ + if (section->sh_entsize == 0 || section->sh_entsize > section->sh_size) + { + error (_("Section %s has an invalid sh_entsize of %#" PRIx64 "\n"), + printable_section_name (filedata, section), + section->sh_entsize); + goto exit_point; + } + + if (section->sh_size > filedata->file_size) + { + error (_("Section %s has an invalid sh_size of %#" PRIx64 "\n"), + printable_section_name (filedata, section), + section->sh_size); + goto exit_point; + } + + number = section->sh_size / section->sh_entsize; + + if (number * sizeof (*esyms) > section->sh_size + 1) + { + error (_("Size (%#" PRIx64 ") of section %s " + "is not a multiple of its sh_entsize (%#" PRIx64 ")\n"), + section->sh_size, + printable_section_name (filedata, section), + section->sh_entsize); + goto exit_point; + } + + esyms = get_data (NULL, filedata, section->sh_offset, 1, section->sh_size, + _("symbols")); + if (esyms == NULL) + goto exit_point; + + shndx = NULL; + for (entry = filedata->symtab_shndx_list; entry != NULL; entry = entry->next) + { + if (entry->hdr->sh_link != (size_t) (section - filedata->section_headers)) + continue; + + if (shndx != NULL) + { + error (_("Multiple symbol table index sections associated with the same symbol section\n")); + free (shndx); + } + + shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata, + entry->hdr->sh_offset, + 1, entry->hdr->sh_size, + _("symbol table section indices")); + if (shndx == NULL) + goto exit_point; + + /* PR17531: file: heap-buffer-overflow */ + if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number) + { + error (_("Index section %s has an sh_size of %#" PRIx64 " - expected %#" PRIx64 "\n"), + printable_section_name (filedata, entry->hdr), + entry->hdr->sh_size, + section->sh_size); + goto exit_point; + } + } + + isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym)); + + if (isyms == NULL) + { + error (_("Out of memory reading %" PRIu64 " symbols\n"), number); + goto exit_point; + } + + for (j = 0, psym = isyms; j < number; j++, psym++) + { + psym->st_name = BYTE_GET (esyms[j].st_name); + psym->st_value = BYTE_GET (esyms[j].st_value); + psym->st_size = BYTE_GET (esyms[j].st_size); + psym->st_shndx = BYTE_GET (esyms[j].st_shndx); + + if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL) + psym->st_shndx + = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); + else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff)) + psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff); + + psym->st_info = BYTE_GET (esyms[j].st_info); + psym->st_other = BYTE_GET (esyms[j].st_other); + } + + exit_point: + free (shndx); + free (esyms); + + if (num_syms_return != NULL) + * num_syms_return = isyms == NULL ? 0 : number; + + return isyms; +} + #undef ElfXX diff --git a/binutils/readelf.c b/binutils/readelf.c index 31cb14a06b0..4560dc55c5e 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -7871,251 +7871,15 @@ get_section_headers (Filedata *filedata, bool probe) return Elf64_get_section_headers (filedata, probe); } -static Elf_Internal_Sym * -get_32bit_elf_symbols (Filedata *filedata, - Elf_Internal_Shdr *section, - uint64_t *num_syms_return) -{ - uint64_t number = 0; - Elf32_External_Sym * esyms = NULL; - Elf_External_Sym_Shndx * shndx = NULL; - Elf_Internal_Sym * isyms = NULL; - Elf_Internal_Sym * psym; - unsigned int j; - elf_section_list * entry; - - if (section->sh_size == 0) - { - if (num_syms_return != NULL) - * num_syms_return = 0; - return NULL; - } - - /* Run some sanity checks first. */ - if (section->sh_entsize == 0 || section->sh_entsize > section->sh_size) - { - error (_("Section %s has an invalid sh_entsize of %#" PRIx64 "\n"), - printable_section_name (filedata, section), - section->sh_entsize); - goto exit_point; - } - - if (section->sh_size > filedata->file_size) - { - error (_("Section %s has an invalid sh_size of %#" PRIx64 "\n"), - printable_section_name (filedata, section), - section->sh_size); - goto exit_point; - } - - number = section->sh_size / section->sh_entsize; - - if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1) - { - error (_("Size (%#" PRIx64 ") of section %s " - "is not a multiple of its sh_entsize (%#" PRIx64 ")\n"), - section->sh_size, - printable_section_name (filedata, section), - section->sh_entsize); - goto exit_point; - } - - esyms = (Elf32_External_Sym *) get_data (NULL, filedata, section->sh_offset, 1, - section->sh_size, _("symbols")); - if (esyms == NULL) - goto exit_point; - - shndx = NULL; - for (entry = filedata->symtab_shndx_list; entry != NULL; entry = entry->next) - { - if (entry->hdr->sh_link != (size_t) (section - filedata->section_headers)) - continue; - - if (shndx != NULL) - { - error (_("Multiple symbol table index sections associated with the same symbol section\n")); - free (shndx); - } - - shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata, - entry->hdr->sh_offset, - 1, entry->hdr->sh_size, - _("symbol table section indices")); - if (shndx == NULL) - goto exit_point; - - /* PR17531: file: heap-buffer-overflow */ - if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number) - { - error (_("Index section %s has an sh_size of %#" PRIx64 " - expected %#" PRIx64 "\n"), - printable_section_name (filedata, entry->hdr), - entry->hdr->sh_size, - section->sh_size); - goto exit_point; - } - } - - isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym)); - - if (isyms == NULL) - { - error (_("Out of memory reading %" PRIu64 " symbols\n"), number); - goto exit_point; - } - - for (j = 0, psym = isyms; j < number; j++, psym++) - { - psym->st_name = BYTE_GET (esyms[j].st_name); - psym->st_value = BYTE_GET (esyms[j].st_value); - psym->st_size = BYTE_GET (esyms[j].st_size); - psym->st_shndx = BYTE_GET (esyms[j].st_shndx); - if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL) - psym->st_shndx - = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); - else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff)) - psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff); - psym->st_info = BYTE_GET (esyms[j].st_info); - psym->st_other = BYTE_GET (esyms[j].st_other); - } - - exit_point: - free (shndx); - free (esyms); - - if (num_syms_return != NULL) - * num_syms_return = isyms == NULL ? 0 : number; - - return isyms; -} - -static Elf_Internal_Sym * -get_64bit_elf_symbols (Filedata *filedata, - Elf_Internal_Shdr *section, - uint64_t *num_syms_return) -{ - uint64_t number = 0; - Elf64_External_Sym * esyms = NULL; - Elf_External_Sym_Shndx * shndx = NULL; - Elf_Internal_Sym * isyms = NULL; - Elf_Internal_Sym * psym; - unsigned int j; - elf_section_list * entry; - - if (section->sh_size == 0) - { - if (num_syms_return != NULL) - * num_syms_return = 0; - return NULL; - } - - /* Run some sanity checks first. */ - if (section->sh_entsize == 0 || section->sh_entsize > section->sh_size) - { - error (_("Section %s has an invalid sh_entsize of %#" PRIx64 "\n"), - printable_section_name (filedata, section), - section->sh_entsize); - goto exit_point; - } - - if (section->sh_size > filedata->file_size) - { - error (_("Section %s has an invalid sh_size of %#" PRIx64 "\n"), - printable_section_name (filedata, section), - section->sh_size); - goto exit_point; - } - - number = section->sh_size / section->sh_entsize; - - if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1) - { - error (_("Size (%#" PRIx64 ") of section %s " - "is not a multiple of its sh_entsize (%#" PRIx64 ")\n"), - section->sh_size, - printable_section_name (filedata, section), - section->sh_entsize); - goto exit_point; - } - - esyms = (Elf64_External_Sym *) get_data (NULL, filedata, section->sh_offset, 1, - section->sh_size, _("symbols")); - if (!esyms) - goto exit_point; - - shndx = NULL; - for (entry = filedata->symtab_shndx_list; entry != NULL; entry = entry->next) - { - if (entry->hdr->sh_link != (size_t) (section - filedata->section_headers)) - continue; - - if (shndx != NULL) - { - error (_("Multiple symbol table index sections associated with the same symbol section\n")); - free (shndx); - } - - shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata, - entry->hdr->sh_offset, - 1, entry->hdr->sh_size, - _("symbol table section indices")); - if (shndx == NULL) - goto exit_point; - - /* PR17531: file: heap-buffer-overflow */ - if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number) - { - error (_("Index section %s has an sh_size of %#" PRIx64 " - expected %#" PRIx64 "\n"), - printable_section_name (filedata, entry->hdr), - entry->hdr->sh_size, - section->sh_size); - goto exit_point; - } - } - - isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym)); - - if (isyms == NULL) - { - error (_("Out of memory reading %" PRIu64 " symbols\n"), number); - goto exit_point; - } - - for (j = 0, psym = isyms; j < number; j++, psym++) - { - psym->st_name = BYTE_GET (esyms[j].st_name); - psym->st_info = BYTE_GET (esyms[j].st_info); - psym->st_other = BYTE_GET (esyms[j].st_other); - psym->st_shndx = BYTE_GET (esyms[j].st_shndx); - - if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL) - psym->st_shndx - = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); - else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff)) - psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff); - - psym->st_value = BYTE_GET (esyms[j].st_value); - psym->st_size = BYTE_GET (esyms[j].st_size); - } - - exit_point: - free (shndx); - free (esyms); - - if (num_syms_return != NULL) - * num_syms_return = isyms == NULL ? 0 : number; - - return isyms; -} - static Elf_Internal_Sym * get_elf_symbols (Filedata *filedata, Elf_Internal_Shdr *section, uint64_t *num_syms_return) { if (is_32bit_elf) - return get_32bit_elf_symbols (filedata, section, num_syms_return); + return Elf32_get_symbols (filedata, section, num_syms_return); else - return get_64bit_elf_symbols (filedata, section, num_syms_return); + return Elf64_get_symbols (filedata, section, num_syms_return); } static const char *