aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-05-19 16:47:12 +0100
committerNick Clifton <nickc@redhat.com>2020-05-19 16:47:12 +0100
commit8ac10c5bfca0602398b38cc69976db213a7d9917 (patch)
tree7138bc1ff4533ed7299dc72e4be2e91639fc19f3 /binutils
parent7e94cf6cb018df7cc1311afb2b15e9f69adb60d9 (diff)
downloadgdb-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/ChangeLog15
-rw-r--r--binutils/readelf.c39
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, &section,
@@ -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"));