More fixes for memory access violations exposed by fuzzed binaries.

PR binutils/17512
	* dwarf.h (struct dwarf_section): Add user_data field.
	* dwarf.c (frame_need_space): Check for an over large register
	number.
	(display_debug_frames): Check the return value from
	frame_need_space.  Check for a CFA expression that is so long the
	start address wraps around.
	(debug_displays): Initialise the user_data field.
	* objdump.c (load_specific_debug_section): Save the BFD section
	pointer in the user_data field of the dwarf_section structure.
	(free_debug_section): Update BFD section data when freeing section
	contents.
	* readelf.c (load_specific_debug_section): Initialise the
	user_data field.

	* archive.c (do_slurp_coff_armap): Add range checks to prevent
	running off the end of the string table.
	* compress.c (bfd_get_full_section_contents): Return a NULL
	pointer for zero sized sections.  Do not attempt to copy a buffer
	onto itself.
	* elf-attrs.c (_bfd_elf_parse_attributes): Check for an empty
	header.  Add range checks to avoid running off the end of the
	section.
	* elf.c (bfd_elf_get_str_section): Seek before allocating so that
	if the seek fails, no memory is allocated.
	(bfd_elf_string_from_elf_section): Do not allocate a string from a
	non string section.  It only leads to trouble later on.
	(_bfd_elf_print_private_bfd_data): Check for there being too
	little external dynamic data.
	(bfd_section_from_shdr): Replace assertion with a failure mode.
	(bfd_section_from_shdr): When walking a loaded group section use
	the internal structure size, not the external size.  Check for the
	group section being empty.
	* elf32-i386.c (elf_i386_rtype_to_howto): Replace assertion with a
	failure mode.
	* elfcode.h (elf_slurp_reloc_table): Likewise.
	* reloc.c (bfd_perform_relocation): Avoid seg-fault if the howto
	parameter is NULL.
This commit is contained in:
Nick Clifton 2014-12-01 16:43:46 +00:00
parent 30b5e341f3
commit 06614111d1
13 changed files with 207 additions and 63 deletions

View File

@ -1,3 +1,30 @@
2014-12-01 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* archive.c (do_slurp_coff_armap): Add range checks to prevent
running off the end of the string table.
* compress.c (bfd_get_full_section_contents): Return a NULL
pointer for zero sized sections. Do not attempt to copy a buffer
onto itself.
* elf-attrs.c (_bfd_elf_parse_attributes): Check for an empty
header. Add range checks to avoid running off the end of the
section.
* elf.c (bfd_elf_get_str_section): Seek before allocating so that
if the seek fails, no memory is allocated.
(bfd_elf_string_from_elf_section): Do not allocate a string from a
non string section. It only leads to trouble later on.
(_bfd_elf_print_private_bfd_data): Check for there being too
little external dynamic data.
(bfd_section_from_shdr): Replace assertion with a failure mode.
(bfd_section_from_shdr): When walking a loaded group section use
the internal structure size, not the external size. Check for the
group section being empty.
* elf32-i386.c (elf_i386_rtype_to_howto): Replace assertion with a
failure mode.
* elfcode.h (elf_slurp_reloc_table): Likewise.
* reloc.c (bfd_perform_relocation): Avoid seg-fault if the howto
parameter is NULL.
2014-11-30 Alan Modra <amodra@gmail.com>
PR 16452, 16457

View File

@ -1038,12 +1038,19 @@ do_slurp_coff_armap (bfd *abfd)
}
/* OK, build the carsyms. */
for (i = 0; i < nsymz; i++)
for (i = 0; i < nsymz && stringsize > 0; i++)
{
bfd_size_type len;
rawptr = raw_armap + i;
carsyms->file_offset = swap ((bfd_byte *) rawptr);
carsyms->name = stringbase;
stringbase += strlen (stringbase) + 1;
/* PR 17512: file: 4a1d50c1. */
len = strnlen (stringbase, stringsize);
if (len < stringsize)
len ++;
stringbase += len;
stringsize -= len;
carsyms++;
}
*stringbase = 0;

View File

@ -152,7 +152,8 @@ DESCRIPTION
return @var{*ptr} with memory malloc'd by this function.
Return @code{TRUE} if the full section contents is retrieved
successfully.
successfully. If the section has no contents then this function
returns @code{TRUE} but @var{*ptr} is set to NULL.
*/
bfd_boolean
@ -172,7 +173,10 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
else
sz = sec->size;
if (sz == 0)
return TRUE;
{
*ptr = NULL;
return TRUE;
}
switch (sec->compress_status)
{
@ -183,6 +187,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
if (p == NULL)
return FALSE;
}
if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
{
if (*ptr != p)
@ -246,7 +251,9 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
return FALSE;
*ptr = p;
}
memcpy (p, sec->contents, sz);
/* PR 17512; file: 5bc29788. */
if (p != sec->contents)
memcpy (p, sec->contents, sz);
return TRUE;
default:

View File

@ -430,9 +430,13 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
{
bfd_byte *contents;
bfd_byte *p;
bfd_byte *p_end;
bfd_vma len;
const char *std_sec;
/* PR 17512: file: 2844a11d. */
if (hdr->sh_size == 0)
return;
contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
if (!contents)
return;
@ -443,11 +447,14 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
return;
}
p = contents;
p_end = p + hdr->sh_size;
std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor;
if (*(p++) == 'A')
{
len = hdr->sh_size - 1;
while (len > 0)
while (len > 0 && p < p_end - 4)
{
unsigned namelen;
bfd_vma section_len;
@ -477,7 +484,7 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
}
p += namelen;
while (section_len > 0)
while (section_len > 0 && p < p_end)
{
int tag;
unsigned int n;
@ -487,7 +494,10 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
tag = read_unsigned_leb128 (abfd, p, &n);
p += n;
subsection_len = bfd_get_32 (abfd, p);
if (p < p_end - 4)
subsection_len = bfd_get_32 (abfd, p);
else
subsection_len = 0;
p += 4;
if (subsection_len == 0)
break;

View File

@ -297,13 +297,14 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
/* Allocate and clear an extra byte at the end, to prevent crashes
in case the string table is not terminated. */
if (shstrtabsize + 1 <= 1
|| (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL
|| bfd_seek (abfd, offset, SEEK_SET) != 0)
|| bfd_seek (abfd, offset, SEEK_SET) != 0
|| (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL)
shstrtab = NULL;
else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize)
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_file_truncated);
bfd_release (abfd, shstrtab);
shstrtab = NULL;
/* Once we've failed to read it, make sure we don't keep
trying. Otherwise, we'll keep allocating space for
@ -332,9 +333,19 @@ bfd_elf_string_from_elf_section (bfd *abfd,
hdr = elf_elfsections (abfd)[shindex];
if (hdr->contents == NULL
&& bfd_elf_get_str_section (abfd, shindex) == NULL)
return NULL;
if (hdr->contents == NULL)
{
if (hdr->sh_type != SHT_STRTAB && hdr->sh_type < SHT_LOOS)
{
/* PR 17512: file: f057ec89. */
_bfd_error_handler (_("%B: attempt to load strings from a non-string section (number %d)"),
abfd, shindex);
return NULL;
}
if (bfd_elf_get_str_section (abfd, shindex) == NULL)
return NULL;
}
if (strindex >= hdr->sh_size)
{
@ -636,6 +647,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
pointers. */
src = shdr->contents + shdr->sh_size;
dest = (Elf_Internal_Group *) (shdr->contents + amt);
while (1)
{
unsigned int idx;
@ -1253,6 +1265,9 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
extdyn = dynbuf;
/* PR 17512: file: 6f427532. */
if (s->size < extdynsize)
goto error_return;
extdynend = extdyn + s->size;
/* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664.
Fix range check. */
@ -1607,7 +1622,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
if (++ nesting > 3)
{
/* PR17512: A corrupt ELF binary might contain a recursive group of
sections, each the string indicies pointing to the next in the
sections, with each the string indicies pointing to the next in the
loop. Detect this here, by refusing to load a section that we are
already in the process of loading. We only trigger this test if
we have nested at least three sections deep as normal ELF binaries
@ -1974,7 +1989,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
else
p_hdr = &esdt->rel.hdr;
BFD_ASSERT (*p_hdr == NULL);
/* PR 17512: file: 0b4f81b7. */
if (*p_hdr != NULL)
goto fail;
amt = sizeof (*hdr2);
hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
if (hdr2 == NULL)
@ -2031,15 +2048,18 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
if (hdr->contents != NULL)
{
Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
unsigned int n_elt = hdr->sh_size / GRP_ENTRY_SIZE;
unsigned int n_elt = hdr->sh_size / sizeof (* idx);
asection *s;
if (n_elt == 0)
goto fail;
if (idx->flags & GRP_COMDAT)
hdr->bfd_section->flags
|= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
/* We try to keep the same section order as it comes in. */
idx += n_elt;
while (--n_elt != 0)
{
--idx;

View File

@ -379,7 +379,9 @@ elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type)
abfd, (int) r_type);
indx = R_386_NONE;
}
BFD_ASSERT (elf_howto_table [indx].type == r_type);
/* PR 17512: file: 0f67f69d. */
if (elf_howto_table [indx].type != r_type)
return NULL;
return &elf_howto_table[indx];
}

View File

@ -1501,7 +1501,9 @@ elf_slurp_reloc_table (bfd *abfd,
rel_hdr2 = d->rela.hdr;
reloc_count2 = rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0;
BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
/* PR 17512: file: 0b4f81b7. */
if (asect->reloc_count != reloc_count + reloc_count2)
return FALSE;
BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset)
|| (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));

View File

@ -592,6 +592,10 @@ bfd_perform_relocation (bfd *abfd,
return bfd_reloc_ok;
}
/* PR 17512: file: 0f67f69d. */
if (howto == NULL)
return bfd_reloc_undefined;
/* If we are not producing relocatable output, return an error if
the symbol is not defined. An undefined weak symbol is
considered to have a value of zero (SVR4 ABI, p. 4-27). */

View File

@ -1,3 +1,20 @@
2014-12-01 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* dwarf.h (struct dwarf_section): Add user_data field.
* dwarf.c (frame_need_space): Check for an over large register
number.
(display_debug_frames): Check the return value from
frame_need_space. Check for a CFA expression that is so long the
start address wraps around.
(debug_displays): Initialise the user_data field.
* objdump.c (load_specific_debug_section): Save the BFD section
pointer in the user_data field of the dwarf_section structure.
(free_debug_section): Update BFD section data when freeing section
contents.
* readelf.c (load_specific_debug_section): Initialise the
user_data field.
2014-12-01 Nick Clifton <nickc@redhat.com>
PR binutils/17531

View File

@ -5157,6 +5157,16 @@ frame_need_space (Frame_Chunk *fc, unsigned int reg)
if (fc->ncols == 0)
return -1;
/* PR 17512: file: 2844a11d. */
if (fc->ncols > 1024)
{
error (_("Unfeasibly large register number: %u\n"), reg);
fc->ncols = 0;
/* FIXME: 1024 is an arbitrary limit. Increase it if
we ever encounter a valid binary that exceeds it. */
return -1;
}
fc->col_type = (short int *) xcrealloc (fc->col_type, fc->ncols,
sizeof (short int));
fc->col_offset = (int *) xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
@ -5590,7 +5600,8 @@ display_debug_frames (struct dwarf_section *section,
mreg = max_regs > 0 ? max_regs - 1 : 0;
if (mreg < fc->ra)
mreg = fc->ra;
frame_need_space (fc, mreg);
if (frame_need_space (fc, mreg) < 0)
break;
if (fc->fde_encoding)
encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
@ -5696,7 +5707,11 @@ display_debug_frames (struct dwarf_section *section,
mreg = max_regs > 0 ? max_regs - 1 : 0;
if (mreg < cie->ra)
mreg = cie->ra;
frame_need_space (cie, mreg);
if (frame_need_space (cie, mreg) < 0)
{
warn (_("Invalid max register\n"));
break;
}
if (cie->fde_encoding)
encoded_ptr_size
= size_of_encoded_value (cie->fde_encoding);
@ -5716,7 +5731,11 @@ display_debug_frames (struct dwarf_section *section,
fc->ncols = 0;
fc->col_type = (short int *) xmalloc (sizeof (short int));
fc->col_offset = (int *) xmalloc (sizeof (int));
frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0);
if (frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0) < 0)
{
warn (_("Invalid max register\n"));
break;
}
cie = fc;
fc->augmentation = "";
fc->fde_encoding = 0;
@ -5739,7 +5758,11 @@ display_debug_frames (struct dwarf_section *section,
fc->cfa_reg = cie->cfa_reg;
fc->cfa_offset = cie->cfa_offset;
fc->ra = cie->ra;
frame_need_space (fc, max_regs > 0 ? max_regs - 1: 0);
if (frame_need_space (fc, max_regs > 0 ? max_regs - 1: 0) < 0)
{
warn (_("Invalid max register\n"));
break;
}
fc->fde_encoding = cie->fde_encoding;
}
@ -5857,7 +5880,6 @@ display_debug_frames (struct dwarf_section *section,
break;
case DW_CFA_restore_extended:
reg = LEB ();
frame_need_space (fc, reg);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
@ -6176,7 +6198,12 @@ display_debug_frames (struct dwarf_section *section,
fc->cfa_reg = rs->cfa_reg;
fc->ra = rs->ra;
fc->cfa_exp = rs->cfa_exp;
frame_need_space (fc, rs->ncols - 1);
if (frame_need_space (fc, rs->ncols - 1) < 0)
{
warn (_("Invalid column number in saved frame state"));
fc->ncols = 0;
break;
}
memcpy (fc->col_type, rs->col_type, rs->ncols * sizeof (* rs->col_type));
memcpy (fc->col_offset, rs->col_offset,
rs->ncols * sizeof (* rs->col_offset));
@ -6218,7 +6245,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_def_cfa_expression:
ul = LEB ();
if (start >= block_end || start + ul > block_end)
if (start >= block_end || start + ul > block_end || start + ul < start)
{
printf (_(" DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
break;
@ -6240,7 +6267,8 @@ display_debug_frames (struct dwarf_section *section,
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
/* PR 17512: file: 069-133014-0.006. */
if (start >= block_end || start + ul > block_end)
/* PR 17512: file: 98c02eb4. */
if (start >= block_end || start + ul > block_end || start + ul < start)
{
printf (_(" DW_CFA_expression: <corrupt len %lu>\n"), ul);
break;
@ -6263,7 +6291,7 @@ display_debug_frames (struct dwarf_section *section,
ul = LEB ();
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (start >= block_end || start + ul > block_end)
if (start >= block_end || start + ul > block_end || start + ul < start)
{
printf (" DW_CFA_val_expression: <corrupt len %lu>\n", ul);
break;
@ -7189,76 +7217,76 @@ dwarf_select_sections_all (void)
struct dwarf_section_display debug_displays[] =
{
{ { ".debug_abbrev", ".zdebug_abbrev", NULL, NULL, 0, 0, 0 },
{ { ".debug_abbrev", ".zdebug_abbrev", NULL, NULL, 0, 0, 0, NULL },
display_debug_abbrev, &do_debug_abbrevs, 0 },
{ { ".debug_aranges", ".zdebug_aranges", NULL, NULL, 0, 0, 0 },
{ { ".debug_aranges", ".zdebug_aranges", NULL, NULL, 0, 0, 0, NULL },
display_debug_aranges, &do_debug_aranges, 1 },
{ { ".debug_frame", ".zdebug_frame", NULL, NULL, 0, 0, 0 },
{ { ".debug_frame", ".zdebug_frame", NULL, NULL, 0, 0, 0, NULL },
display_debug_frames, &do_debug_frames, 1 },
{ { ".debug_info", ".zdebug_info", NULL, NULL, 0, 0, abbrev },
{ { ".debug_info", ".zdebug_info", NULL, NULL, 0, 0, abbrev, NULL },
display_debug_info, &do_debug_info, 1 },
{ { ".debug_line", ".zdebug_line", NULL, NULL, 0, 0, 0 },
{ { ".debug_line", ".zdebug_line", NULL, NULL, 0, 0, 0, NULL },
display_debug_lines, &do_debug_lines, 1 },
{ { ".debug_pubnames", ".zdebug_pubnames", NULL, NULL, 0, 0, 0 },
{ { ".debug_pubnames", ".zdebug_pubnames", NULL, NULL, 0, 0, 0, NULL },
display_debug_pubnames, &do_debug_pubnames, 0 },
{ { ".debug_gnu_pubnames", ".zdebug_gnu_pubnames", NULL, NULL, 0, 0, 0 },
{ { ".debug_gnu_pubnames", ".zdebug_gnu_pubnames", NULL, NULL, 0, 0, 0, NULL },
display_debug_gnu_pubnames, &do_debug_pubnames, 0 },
{ { ".eh_frame", "", NULL, NULL, 0, 0, 0 },
{ { ".eh_frame", "", NULL, NULL, 0, 0, 0, NULL },
display_debug_frames, &do_debug_frames, 1 },
{ { ".debug_macinfo", ".zdebug_macinfo", NULL, NULL, 0, 0, 0 },
{ { ".debug_macinfo", ".zdebug_macinfo", NULL, NULL, 0, 0, 0, NULL },
display_debug_macinfo, &do_debug_macinfo, 0 },
{ { ".debug_macro", ".zdebug_macro", NULL, NULL, 0, 0, 0 },
{ { ".debug_macro", ".zdebug_macro", NULL, NULL, 0, 0, 0, NULL },
display_debug_macro, &do_debug_macinfo, 1 },
{ { ".debug_str", ".zdebug_str", NULL, NULL, 0, 0, 0 },
{ { ".debug_str", ".zdebug_str", NULL, NULL, 0, 0, 0, NULL },
display_debug_str, &do_debug_str, 0 },
{ { ".debug_loc", ".zdebug_loc", NULL, NULL, 0, 0, 0 },
{ { ".debug_loc", ".zdebug_loc", NULL, NULL, 0, 0, 0, NULL },
display_debug_loc, &do_debug_loc, 1 },
{ { ".debug_pubtypes", ".zdebug_pubtypes", NULL, NULL, 0, 0, 0 },
{ { ".debug_pubtypes", ".zdebug_pubtypes", NULL, NULL, 0, 0, 0, NULL },
display_debug_pubnames, &do_debug_pubtypes, 0 },
{ { ".debug_gnu_pubtypes", ".zdebug_gnu_pubtypes", NULL, NULL, 0, 0, 0 },
{ { ".debug_gnu_pubtypes", ".zdebug_gnu_pubtypes", NULL, NULL, 0, 0, 0, NULL },
display_debug_gnu_pubnames, &do_debug_pubtypes, 0 },
{ { ".debug_ranges", ".zdebug_ranges", NULL, NULL, 0, 0, 0 },
{ { ".debug_ranges", ".zdebug_ranges", NULL, NULL, 0, 0, 0, NULL },
display_debug_ranges, &do_debug_ranges, 1 },
{ { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0, 0 },
{ { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0, 0, NULL },
display_debug_not_supported, NULL, 0 },
{ { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0, 0 },
{ { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0, 0, NULL },
display_debug_not_supported, NULL, 0 },
{ { ".debug_types", ".zdebug_types", NULL, NULL, 0, 0, abbrev },
{ { ".debug_types", ".zdebug_types", NULL, NULL, 0, 0, abbrev, NULL },
display_debug_types, &do_debug_info, 1 },
{ { ".debug_weaknames", ".zdebug_weaknames", NULL, NULL, 0, 0, 0 },
{ { ".debug_weaknames", ".zdebug_weaknames", NULL, NULL, 0, 0, 0, NULL },
display_debug_not_supported, NULL, 0 },
{ { ".gdb_index", "", NULL, NULL, 0, 0, 0 },
{ { ".gdb_index", "", NULL, NULL, 0, 0, 0, NULL },
display_gdb_index, &do_gdb_index, 0 },
{ { ".trace_info", "", NULL, NULL, 0, 0, trace_abbrev },
{ { ".trace_info", "", NULL, NULL, 0, 0, trace_abbrev, NULL },
display_trace_info, &do_trace_info, 1 },
{ { ".trace_abbrev", "", NULL, NULL, 0, 0, 0 },
{ { ".trace_abbrev", "", NULL, NULL, 0, 0, 0, NULL },
display_debug_abbrev, &do_trace_abbrevs, 0 },
{ { ".trace_aranges", "", NULL, NULL, 0, 0, 0 },
{ { ".trace_aranges", "", NULL, NULL, 0, 0, 0, NULL },
display_debug_aranges, &do_trace_aranges, 0 },
{ { ".debug_info.dwo", ".zdebug_info.dwo", NULL, NULL, 0, 0, abbrev_dwo },
{ { ".debug_info.dwo", ".zdebug_info.dwo", NULL, NULL, 0, 0, abbrev_dwo, NULL },
display_debug_info, &do_debug_info, 1 },
{ { ".debug_abbrev.dwo", ".zdebug_abbrev.dwo", NULL, NULL, 0, 0, 0 },
{ { ".debug_abbrev.dwo", ".zdebug_abbrev.dwo", NULL, NULL, 0, 0, 0, NULL },
display_debug_abbrev, &do_debug_abbrevs, 0 },
{ { ".debug_types.dwo", ".zdebug_types.dwo", NULL, NULL, 0, 0, abbrev_dwo },
{ { ".debug_types.dwo", ".zdebug_types.dwo", NULL, NULL, 0, 0, abbrev_dwo, NULL },
display_debug_types, &do_debug_info, 1 },
{ { ".debug_line.dwo", ".zdebug_line.dwo", NULL, NULL, 0, 0, 0 },
{ { ".debug_line.dwo", ".zdebug_line.dwo", NULL, NULL, 0, 0, 0, NULL },
display_debug_lines, &do_debug_lines, 1 },
{ { ".debug_loc.dwo", ".zdebug_loc.dwo", NULL, NULL, 0, 0, 0 },
{ { ".debug_loc.dwo", ".zdebug_loc.dwo", NULL, NULL, 0, 0, 0, NULL },
display_debug_loc, &do_debug_loc, 1 },
{ { ".debug_macro.dwo", ".zdebug_macro.dwo", NULL, NULL, 0, 0, 0 },
{ { ".debug_macro.dwo", ".zdebug_macro.dwo", NULL, NULL, 0, 0, 0, NULL },
display_debug_macro, &do_debug_macinfo, 1 },
{ { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo", NULL, NULL, 0, 0, 0 },
{ { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo", NULL, NULL, 0, 0, 0, NULL },
display_debug_macinfo, &do_debug_macinfo, 0 },
{ { ".debug_str.dwo", ".zdebug_str.dwo", NULL, NULL, 0, 0, 0 },
{ { ".debug_str.dwo", ".zdebug_str.dwo", NULL, NULL, 0, 0, 0, NULL },
display_debug_str, &do_debug_str, 1 },
{ { ".debug_str_offsets", ".zdebug_str_offsets", NULL, NULL, 0, 0, 0 },
{ { ".debug_str_offsets", ".zdebug_str_offsets", NULL, NULL, 0, 0, 0, NULL },
display_debug_str_offsets, NULL, 0 },
{ { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo", NULL, NULL, 0, 0, 0 },
{ { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo", NULL, NULL, 0, 0, 0, NULL },
display_debug_str_offsets, NULL, 0 },
{ { ".debug_addr", ".zdebug_addr", NULL, NULL, 0, 0, 0 },
{ { ".debug_addr", ".zdebug_addr", NULL, NULL, 0, 0, 0, NULL },
display_debug_addr, &do_debug_addr, 1 },
{ { ".debug_cu_index", "", NULL, NULL, 0, 0, 0 },
{ { ".debug_cu_index", "", NULL, NULL, 0, 0, 0, NULL },
display_cu_index, &do_debug_cu_index, 0 },
{ { ".debug_tu_index", "", NULL, NULL, 0, 0, 0 },
{ { ".debug_tu_index", "", NULL, NULL, 0, 0, 0, NULL },
display_cu_index, &do_debug_cu_index, 0 },
};

View File

@ -164,6 +164,8 @@ struct dwarf_section
dwarf_vma address;
dwarf_size_type size;
enum dwarf_section_display_enum abbrev_sec;
/* A spare field for random use. */
void *user_data;
};
/* A structure containing the name of a debug section

View File

@ -2280,6 +2280,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
section->address = bfd_get_section_vma (abfd, sec);
section->size = bfd_get_section_size (sec);
section->start = NULL;
section->user_data = sec;
ret = bfd_get_full_section_contents (abfd, sec, &section->start);
if (! ret)
@ -2346,6 +2347,22 @@ free_debug_section (enum dwarf_section_display_enum debug)
if (section->start == NULL)
return;
/* PR 17512: file: 0f67f69d. */
if (section->user_data != NULL)
{
asection * sec = (asection *) section->user_data;
/* If we are freeing contents that are also pointed to by the BFD
library's section structure then make sure to update those pointers
too. Otherwise, the next time we try to load data for this section
we can end up using a stale pointer. */
if (section->start == sec->contents)
{
sec->contents = NULL;
sec->flags &= ~ SEC_IN_MEMORY;
}
}
free ((char *) section->start);
section->start = NULL;
section->address = 0;

View File

@ -11713,6 +11713,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
snprintf (buf, sizeof (buf), _("%s section data"), section->name);
section->address = sec->sh_addr;
section->user_data = NULL;
section->start = (unsigned char *) get_data (NULL, (FILE *) file,
sec->sh_offset, 1,
sec->sh_size, buf);