From 8ac10c5bfca0602398b38cc69976db213a7d9917 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 19 May 2020 16:47:12 +0100 Subject: [PATCH] Allow readelf to issue warnings if checking is enabled and there are discrepancies between the dynamic tags and the dynamic sections. PR binutils/25809 * readelf.c (process_program_headers): Warn if the PT_DYNAMIC segment doesn't match the .dynamic section and checks are enabled. (struct filedata): Add dynamic_symtab_section and dynamic_strtab_section fields. (process_section_headers): Set dynamic_symtab_section to the .dynsym section. Set dynamic_strtab_section to the .dynstr section. (process_dynamic_section): Warn if the .dynsym section doesn't match DT_SYMTAB and DT_SYMENT or the .dynstr section doesn't DT_STRTAB and DT_STRSZ. But only if checks are enabled. --- binutils/ChangeLog | 15 +++++++++++++++ binutils/readelf.c | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index bc0c99907bf..76de37e449a 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,18 @@ +2020-05-19 H.J. Lu + + PR binutils/25809 + * readelf.c (process_program_headers): Warn if the PT_DYNAMIC + segment doesn't match the .dynamic section and checks are + enabled. + (struct filedata): Add dynamic_symtab_section and + dynamic_strtab_section fields. + (process_section_headers): Set dynamic_symtab_section to the + .dynsym section. Set dynamic_strtab_section to the .dynstr + section. + (process_dynamic_section): Warn if the .dynsym section doesn't + match DT_SYMTAB and DT_SYMENT or the .dynstr section doesn't + DT_STRTAB and DT_STRSZ. But only if checks are enabled. + 2020-05-19 Alan Modra * ar.c (map_over_members, get_pos_bfd, delete_members, move_members), diff --git a/binutils/readelf.c b/binutils/readelf.c index 6bf6d5294cc..87bb574129f 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -267,8 +267,10 @@ typedef struct filedata bfd_size_type dynamic_size; size_t dynamic_nent; Elf_Internal_Dyn * dynamic_section; + Elf_Internal_Shdr * dynamic_strtab_section; char * dynamic_strings; unsigned long dynamic_strings_length; + Elf_Internal_Shdr * dynamic_symtab_section; unsigned long num_dynamic_syms; Elf_Internal_Sym * dynamic_symbols; bfd_vma version_info[16]; @@ -5363,13 +5365,13 @@ process_program_headers (Filedata * filedata) filedata->dynamic_addr = sec->sh_offset; filedata->dynamic_size = sec->sh_size; - if (filedata->dynamic_addr < segment->p_offset - || filedata->dynamic_addr > segment->p_offset + segment->p_filesz) - warn (_("the .dynamic section is not contained" - " within the dynamic segment\n")); - else if (filedata->dynamic_addr > segment->p_offset) - warn (_("the .dynamic section is not the first section" - " in the dynamic segment.\n")); + /* The PT_DYNAMIC segment, which is used by the run-time + loader, should exactly match the .dynamic section. */ + if (do_checks + && (filedata->dynamic_addr != segment->p_offset + || filedata->dynamic_size != segment->p_filesz)) + warn (_("\ +the .dynamic section is not the same as the dynamic segment\n")); } /* PR binutils/17512: Avoid corrupt dynamic section info in the @@ -6319,6 +6321,7 @@ process_section_headers (Filedata * filedata) CHECK_ENTSIZE (section, i, Sym); filedata->dynamic_symbols = GET_ELF_SYMBOLS (filedata, section, &filedata->num_dynamic_syms); + filedata->dynamic_symtab_section = section; break; case SHT_STRTAB: @@ -6335,6 +6338,7 @@ process_section_headers (Filedata * filedata) 1, section->sh_size, _("dynamic strings")); filedata->dynamic_strings_length = filedata->dynamic_strings == NULL ? 0 : section->sh_size; + filedata->dynamic_strtab_section = section; } break; @@ -10341,6 +10345,18 @@ process_dynamic_section (Filedata * filedata) section.sh_size = (num_of_syms * filedata->dynamic_info[DT_SYMENT]); section.sh_entsize = filedata->dynamic_info[DT_SYMENT]; + + if (do_checks + && filedata->dynamic_symtab_section != NULL + && ((filedata->dynamic_symtab_section->sh_offset + != section.sh_offset) + || (filedata->dynamic_symtab_section->sh_size + != section.sh_size) + || (filedata->dynamic_symtab_section->sh_entsize + != section.sh_entsize))) + warn (_("\ +the .dynsym section doesn't match the DT_SYMTAB and DT_SYMENT tags\n")); + section.sh_name = filedata->string_table_length; filedata->dynamic_symbols = GET_ELF_SYMBOLS (filedata, §ion, @@ -10378,6 +10394,15 @@ process_dynamic_section (Filedata * filedata) offset = offset_from_vma (filedata, filedata->dynamic_info[DT_STRTAB], str_tab_len); + if (do_checks + && filedata->dynamic_strtab_section + && ((filedata->dynamic_strtab_section->sh_offset + != (file_ptr) offset) + || (filedata->dynamic_strtab_section->sh_size + != str_tab_len))) + warn (_("\ +the .dynstr section doesn't match the DT_STRTAB and DT_STRSZ tags\n")); + filedata->dynamic_strings = (char *) get_data (NULL, filedata, offset, 1, str_tab_len, _("dynamic string table")); -- 2.30.2