From 53b8873bef9753edf97fa8ef2bcabefd566bcd48 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 30 Jun 2006 13:38:57 +0000 Subject: [PATCH] * dwarf.c (display_debug_frames): Catch a corrupt length field generating an end of block address that is beyond the end of the section. When encountering a corrupt CIE pointer do not reset the start pointer as more data still has to be read. Do not warn about user defined call frame instructions. --- binutils/ChangeLog | 9 +++++++++ binutils/dwarf.c | 43 ++++++++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 1c7a2a60f6..9eb02021ca 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,12 @@ +2006-06-30 Nick Clifton + + * dwarf.c (display_debug_frames): Catch a corrupt length field + generating an end of block address that is beyond the end of the + section. + When encountering a corrupt CIE pointer do not reset the start + pointer as more data still has to be read. + Do not warn about user defined call frame instructions. + 2006-06-29 DJ Delorie * readelf.c (process_section_headers): Add H8/300 support. diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 56669be6fb..0db2a8b3d8 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -2519,6 +2519,7 @@ display_debug_aranges (struct dwarf_section *section, unsigned char *ranges; unsigned long length; unsigned long address; + unsigned char address_size; int excess; int offset_size; int initial_length_size; @@ -2565,26 +2566,37 @@ display_debug_aranges (struct dwarf_section *section, printf (_(" Pointer Size: %d\n"), arange.ar_pointer_size); printf (_(" Segment Size: %d\n"), arange.ar_segment_size); + address_size = arange.ar_pointer_size + arange.ar_segment_size; + + /* The DWARF spec does not require that the address size be a power + of two, but we do. This will have to change if we ever encounter + an uneven architecture. */ + if ((address_size & (address_size - 1)) != 0) + { + warn (_("Pointer size + Segment size is not a power of two.\n")); + break; + } + printf (_("\n Address Length\n")); ranges = hdrptr; - /* Must pad to an alignment boundary that is twice the pointer size. */ - excess = (hdrptr - start) % (2 * arange.ar_pointer_size); + /* Must pad to an alignment boundary that is twice the address size. */ + excess = (hdrptr - start) % (2 * address_size); if (excess) - ranges += (2 * arange.ar_pointer_size) - excess; + ranges += (2 * address_size) - excess; start += arange.ar_length + initial_length_size; - while (ranges + 2 * arange.ar_pointer_size <= start) + while (ranges + 2 * address_size <= start) { - address = byte_get (ranges, arange.ar_pointer_size); + address = byte_get (ranges, address_size); - ranges += arange.ar_pointer_size; + ranges += address_size; - length = byte_get (ranges, arange.ar_pointer_size); + length = byte_get (ranges, address_size); - ranges += arange.ar_pointer_size; + ranges += address_size; printf (" %8.8lx %lu\n", address, length); } @@ -2879,6 +2891,7 @@ static dwarf_vma get_encoded_value (unsigned char *data, int encoding) { int size = size_of_encoded_value (encoding); + if (encoding & DW_EH_PE_signed) return byte_get_signed (data, size); else @@ -2944,6 +2957,12 @@ display_debug_frames (struct dwarf_section *section, } block_end = saved_start + length + initial_length_size; + if (block_end > end) + { + warn ("Invalid length %#08lx in FDE at %#08lx\n", + length, (unsigned long)(saved_start - section_start)); + block_end = end; + } cie_id = byte_get (start, offset_size); start += offset_size; if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID)) @@ -3078,9 +3097,8 @@ display_debug_frames (struct dwarf_section *section, if (!cie) { - warn ("Invalid CIE pointer %08lx in FDE at %08lx\n", + warn ("Invalid CIE pointer %#08lx in FDE at %#08lx\n", cie_id, (unsigned long)(saved_start - section_start)); - start = block_end; fc->ncols = 0; fc->col_type = xmalloc (sizeof (short int)); fc->col_offset = xmalloc (sizeof (int)); @@ -3584,7 +3602,10 @@ display_debug_frames (struct dwarf_section *section, break; default: - warn (_("unsupported or unknown DW_CFA_%d\n"), op); + if (op >= DW_CFA_lo_user && op <= DW_CFA_hi_user) + printf (_(" DW_CFA_??? (User defined call frame op: %#x)\n"), op); + else + warn (_("unsupported or unknown Dwarf Call Frame Instruction number: %#x\n"), op); start = block_end; } }