diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2020-05-19 16:47:12 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2020-05-19 16:47:12 +0100 |
commit | 8ac10c5bfca0602398b38cc69976db213a7d9917 (patch) | |
tree | 7138bc1ff4533ed7299dc72e4be2e91639fc19f3 /binutils | |
parent | 7e94cf6cb018df7cc1311afb2b15e9f69adb60d9 (diff) | |
download | gdb-8ac10c5bfca0602398b38cc69976db213a7d9917.zip gdb-8ac10c5bfca0602398b38cc69976db213a7d9917.tar.gz gdb-8ac10c5bfca0602398b38cc69976db213a7d9917.tar.bz2 |
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.
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/ChangeLog | 15 | ||||
-rw-r--r-- | binutils/readelf.c | 39 |
2 files changed, 47 insertions, 7 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index bc0c999..76de37e 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,18 @@ +2020-05-19 H.J. Lu <hjl.tools@gmail.com> + + 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 <amodra@gmail.com> * ar.c (map_over_members, get_pos_bfd, delete_members, move_members), diff --git a/binutils/readelf.c b/binutils/readelf.c index 6bf6d52..87bb574 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")); |