From: Nick Clifton Date: Mon, 25 Mar 2013 13:16:41 +0000 (+0000) Subject: PR binutils/15202 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f6f0e17bc3616a0e976b250e361bdd61bbffc6e8;p=binutils-gdb.git PR binutils/15202 * dwarf.c (read_leb128): Add END parameter. Do not read at or beyond end. (read_sleb128): Add END parameter. (read_uleb128): New function. (process_extended_line_op): Pass END to leb128 functions. (process_abbrev_section): Likewise. (decode_location_expression): Likewise. (read_and_display_attr_value): Likewise. (read_and_display_attr): Likewise. (process_debug_info): Likewise. (display_debug_lines_raw): Likewise. (display_debug_lines_decoded): Likewise. (display_debug_macinfo): Likewise. (get_line_filename_and_dirname): Likewise. (display_debug_macro): Likewise. (display_loc_list_dwo): Likewise. (display_debug_ranges): Likewise. * dwarf.h (read_leb128): Update prototype. * readelf.c (read_uleb128): Add END parameter. (decode_arm_unwind_bytecode): Pass END to read_uleb128. (decode_tic6x_unwind_bytecode): Likewise. (display_tag_value): New function. (display_arm_attribute): Add END parameter. Pass END to read_uleb128. Use display_tag_value. (display_gnu_attribute): Likewise. (display_power_gnu_attribute): Likewise. (display_sparc_gnu_attribute): Likewise. (display_mips_gnu_attribute): Likewise. (display_tic6x_attribute): Likewise. (process_attributes): Likewise. (display_raw_attribute): New function. --- diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 8d9bb1dfda0..ebede029adb 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,38 @@ +2013-03-25 Nick Clifton + + PR binutils/15202 + * dwarf.c (read_leb128): Add END parameter. Do not read at or + beyond end. + (read_sleb128): Add END parameter. + (read_uleb128): New function. + (process_extended_line_op): Pass END to leb128 functions. + (process_abbrev_section): Likewise. + (decode_location_expression): Likewise. + (read_and_display_attr_value): Likewise. + (read_and_display_attr): Likewise. + (process_debug_info): Likewise. + (display_debug_lines_raw): Likewise. + (display_debug_lines_decoded): Likewise. + (display_debug_macinfo): Likewise. + (get_line_filename_and_dirname): Likewise. + (display_debug_macro): Likewise. + (display_loc_list_dwo): Likewise. + (display_debug_ranges): Likewise. + * dwarf.h (read_leb128): Update prototype. + * readelf.c (read_uleb128): Add END parameter. + (decode_arm_unwind_bytecode): Pass END to read_uleb128. + (decode_tic6x_unwind_bytecode): Likewise. + (display_tag_value): New function. + (display_arm_attribute): Add END parameter. Pass END to + read_uleb128. Use display_tag_value. + (display_gnu_attribute): Likewise. + (display_power_gnu_attribute): Likewise. + (display_sparc_gnu_attribute): Likewise. + (display_mips_gnu_attribute): Likewise. + (display_tic6x_attribute): Likewise. + (process_attributes): Likewise. + (display_raw_attribute): New function. + 2013-03-22 Nick Clifton PR binutils/15201 diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 8a55aeb7e7b..4a11aa5c5da 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -1,6 +1,5 @@ /* dwarf.c -- display DWARF contents of a BFD binary file - Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 - Free Software Foundation, Inc. + Copyright 2005-2013 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -225,15 +224,23 @@ dwarf_vmatoa64 (dwarf_vma hvalue, dwarf_vma lvalue, char *buf, return buf; } +/* Read in a LEB128 encoded value starting at address DATA. + If SIGN is true, return a signed LEB128 value. + If LENGTH_RETURN is not NULL, return in it the number of bytes read. + No bytes will be read at address END or beyond. */ + dwarf_vma -read_leb128 (unsigned char *data, unsigned int *length_return, int sign) +read_leb128 (unsigned char *data, + unsigned int *length_return, + bfd_boolean sign, + const unsigned char * const end) { dwarf_vma result = 0; unsigned int num_read = 0; unsigned int shift = 0; - unsigned char byte; + unsigned char byte = 0; - do + while (data < end) { byte = *data++; num_read++; @@ -241,9 +248,9 @@ read_leb128 (unsigned char *data, unsigned int *length_return, int sign) result |= ((dwarf_vma) (byte & 0x7f)) << shift; shift += 7; - + if ((byte & 0x80) == 0) + break; } - while (byte & 0x80); if (length_return != NULL) *length_return = num_read; @@ -255,10 +262,20 @@ read_leb128 (unsigned char *data, unsigned int *length_return, int sign) } /* Create a signed version to avoid painful typecasts. */ -static dwarf_signed_vma -read_sleb128 (unsigned char *data, unsigned int *length_return) +static inline dwarf_signed_vma +read_sleb128 (unsigned char * data, + unsigned int * length_return, + const unsigned char * const end) { - return (dwarf_signed_vma) read_leb128 (data, length_return, 1); + return (dwarf_signed_vma) read_leb128 (data, length_return, TRUE, end); +} + +static inline dwarf_vma +read_uleb128 (unsigned char * data, + unsigned int * length_return, + const unsigned char * const end) +{ + return read_leb128 (data, length_return, FALSE, end); } typedef struct State_Machine_Registers @@ -296,19 +313,21 @@ reset_state_machine (int is_stmt) Returns the number of bytes read. */ static int -process_extended_line_op (unsigned char *data, int is_stmt) +process_extended_line_op (unsigned char * data, + int is_stmt, + unsigned char * end) { unsigned char op_code; unsigned int bytes_read; unsigned int len; unsigned char *name; - dwarf_vma adr; unsigned char *orig_data = data; + dwarf_vma adr; - len = read_leb128 (data, & bytes_read, 0); + len = read_uleb128 (data, & bytes_read, end); data += bytes_read; - if (len == 0) + if (len == 0 || data == end) { warn (_("badly formed extended line op encountered!\n")); return bytes_read; @@ -336,25 +355,25 @@ process_extended_line_op (unsigned char *data, int is_stmt) case DW_LNE_define_file: printf (_("define new File Table entry\n")); printf (_(" Entry\tDir\tTime\tSize\tName\n")); - printf (" %d\t", ++state_machine_regs.last_file_entry); + name = data; data += strlen ((char *) data) + 1; - printf ("%s\t", dwarf_vmatoa ("u", read_leb128 (data, & bytes_read, 0))); + printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); data += bytes_read; - printf ("%s\t", dwarf_vmatoa ("u", read_leb128 (data, & bytes_read, 0))); + printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); data += bytes_read; - printf ("%s\t", dwarf_vmatoa ("u", read_leb128 (data, & bytes_read, 0))); + printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); data += bytes_read; - printf ("%s", name); - if ((unsigned int) (data - orig_data) != len) - printf (_(" [Bad opcode length]")); - printf ("\n\n"); + printf ("%s\n\n", name); + + if (((unsigned int) (data - orig_data) != len) || data == end) + warn (_("DW_LNE_define_file: Bad opcode length\n")); break; case DW_LNE_set_discriminator: printf (_("set Discriminator to %s\n"), - dwarf_vmatoa ("u", read_leb128 (data, & bytes_read, 0))); + dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); break; /* HP extensions. */ @@ -398,7 +417,7 @@ process_extended_line_op (unsigned char *data, int is_stmt) { unsigned int opc; - opc = read_leb128 (data, & bytes_read, 0); + opc = read_uleb128 (data, & bytes_read, edata); data += bytes_read; switch (opc) @@ -409,22 +428,22 @@ process_extended_line_op (unsigned char *data, int is_stmt) case DW_LNE_HP_SFC_set_listing_line: printf (" DW_LNE_HP_SFC_set_listing_line (%s)\n", dwarf_vmatoa ("u", - read_leb128 (data, & bytes_read, 0))); + read_uleb128 (data, & bytes_read, edata))); data += bytes_read; break; case DW_LNE_HP_SFC_associate: printf (" DW_LNE_HP_SFC_associate "); printf ("(%s", dwarf_vmatoa ("u", - read_leb128 (data, & bytes_read, 0))); + read_uleb128 (data, & bytes_read, edata))); data += bytes_read; printf (",%s", dwarf_vmatoa ("u", - read_leb128 (data, & bytes_read, 0))); + read_uleb128 (data, & bytes_read, edata))); data += bytes_read; printf (",%s)\n", dwarf_vmatoa ("u", - read_leb128 (data, & bytes_read, 0))); + read_uleb128 (data, & bytes_read, edata))); data += bytes_read; break; default: @@ -656,17 +675,21 @@ process_abbrev_section (unsigned char *start, unsigned char *end) unsigned long attribute; int children; - entry = read_leb128 (start, & bytes_read, 0); + entry = read_uleb128 (start, & bytes_read, end); start += bytes_read; /* A single zero is supposed to end the section according to the standard. If there's more, then signal that to the caller. */ + if (start == end) + return NULL; if (entry == 0) - return start == end ? NULL : start; + return start; - tag = read_leb128 (start, & bytes_read, 0); + tag = read_uleb128 (start, & bytes_read, end); start += bytes_read; + if (start == end) + return NULL; children = *start++; @@ -676,11 +699,15 @@ process_abbrev_section (unsigned char *start, unsigned char *end) { unsigned long form; - attribute = read_leb128 (start, & bytes_read, 0); + attribute = read_uleb128 (start, & bytes_read, end); start += bytes_read; + if (start == end) + break; - form = read_leb128 (start, & bytes_read, 0); + form = read_uleb128 (start, & bytes_read, end); start += bytes_read; + if (start == end) + break; add_abbrev_attr (attribute, form); } @@ -803,12 +830,12 @@ decode_location_expression (unsigned char * data, break; case DW_OP_constu: printf ("DW_OP_constu: %s", - dwarf_vmatoa ("u", read_leb128 (data, &bytes_read, 0))); + dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end))); data += bytes_read; break; case DW_OP_consts: printf ("DW_OP_consts: %s", - dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read))); + dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end))); data += bytes_read; break; case DW_OP_dup: @@ -864,7 +891,7 @@ decode_location_expression (unsigned char * data, break; case DW_OP_plus_uconst: printf ("DW_OP_plus_uconst: %s", - dwarf_vmatoa ("u", read_leb128 (data, &bytes_read, 0))); + dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end))); data += bytes_read; break; case DW_OP_shl: @@ -1012,13 +1039,12 @@ decode_location_expression (unsigned char * data, printf ("DW_OP_breg%d (%s): %s", op - DW_OP_breg0, regname (op - DW_OP_breg0, 1), - dwarf_vmatoa ("d", (dwarf_signed_vma) - read_leb128 (data, &bytes_read, 1))); + dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end))); data += bytes_read; break; case DW_OP_regx: - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf ("DW_OP_regx: %s (%s)", dwarf_vmatoa ("u", uvalue), regname (uvalue, 1)); @@ -1026,20 +1052,20 @@ decode_location_expression (unsigned char * data, case DW_OP_fbreg: need_frame_base = 1; printf ("DW_OP_fbreg: %s", - dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read))); + dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end))); data += bytes_read; break; case DW_OP_bregx: - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf ("DW_OP_bregx: %s (%s) %s", dwarf_vmatoa ("u", uvalue), regname (uvalue, 1), - dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read))); + dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end))); data += bytes_read; break; case DW_OP_piece: printf ("DW_OP_piece: %s", - dwarf_vmatoa ("u", read_leb128 (data, &bytes_read, 0))); + dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end))); data += bytes_read; break; case DW_OP_deref_size: @@ -1103,10 +1129,10 @@ decode_location_expression (unsigned char * data, case DW_OP_bit_piece: printf ("DW_OP_bit_piece: "); printf (_("size: %s "), - dwarf_vmatoa ("u", read_leb128 (data, &bytes_read, 0))); + dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end))); data += bytes_read; printf (_("offset: %s "), - dwarf_vmatoa ("u", read_leb128 (data, &bytes_read, 0))); + dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end))); data += bytes_read; break; @@ -1117,7 +1143,7 @@ decode_location_expression (unsigned char * data, case DW_OP_implicit_value: printf ("DW_OP_implicit_value"); - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; display_block (data, uvalue); data += uvalue; @@ -1158,7 +1184,7 @@ decode_location_expression (unsigned char * data, printf ("DW_OP_GNU_implicit_pointer: <0x%s> %s", dwarf_vmatoa ("x", byte_get (data, pointer_size)), dwarf_vmatoa ("d", read_sleb128 (data + pointer_size, - &bytes_read))); + &bytes_read, end))); data += pointer_size + bytes_read; } else @@ -1166,12 +1192,12 @@ decode_location_expression (unsigned char * data, printf ("DW_OP_GNU_implicit_pointer: <0x%s> %s", dwarf_vmatoa ("x", byte_get (data, offset_size)), dwarf_vmatoa ("d", read_sleb128 (data + offset_size, - &bytes_read))); + &bytes_read, end))); data += offset_size + bytes_read; } break; case DW_OP_GNU_entry_value: - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf ("DW_OP_GNU_entry_value: ("); if (decode_location_expression (data, pointer_size, offset_size, @@ -1182,7 +1208,7 @@ decode_location_expression (unsigned char * data, data += uvalue; break; case DW_OP_GNU_const_type: - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf ("DW_OP_GNU_const_type: <0x%s> ", dwarf_vmatoa ("x", cu_offset + uvalue)); @@ -1191,28 +1217,28 @@ decode_location_expression (unsigned char * data, data += uvalue; break; case DW_OP_GNU_regval_type: - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf ("DW_OP_GNU_regval_type: %s (%s)", dwarf_vmatoa ("u", uvalue), regname (uvalue, 1)); - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf (" <0x%s>", dwarf_vmatoa ("x", cu_offset + uvalue)); break; case DW_OP_GNU_deref_type: printf ("DW_OP_GNU_deref_type: %ld", (long) byte_get (data++, 1)); - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf (" <0x%s>", dwarf_vmatoa ("x", cu_offset + uvalue)); break; case DW_OP_GNU_convert: - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf ("DW_OP_GNU_convert <0x%s>", dwarf_vmatoa ("x", uvalue ? cu_offset + uvalue : 0)); break; case DW_OP_GNU_reinterpret: - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf ("DW_OP_GNU_reinterpret <0x%s>", dwarf_vmatoa ("x", uvalue ? cu_offset + uvalue : 0)); @@ -1223,12 +1249,12 @@ decode_location_expression (unsigned char * data, data += 4; break; case DW_OP_GNU_addr_index: - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf ("DW_OP_GNU_addr_index <0x%s>", dwarf_vmatoa ("x", uvalue)); break; case DW_OP_GNU_const_index: - uvalue = read_leb128 (data, &bytes_read, 0); + uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf ("DW_OP_GNU_const_index <0x%s>", dwarf_vmatoa ("x", uvalue)); break; @@ -1322,6 +1348,7 @@ static unsigned char * read_and_display_attr_value (unsigned long attribute, unsigned long form, unsigned char * data, + unsigned char * end, dwarf_vma cu_offset, dwarf_vma pointer_size, dwarf_vma offset_size, @@ -1393,33 +1420,33 @@ read_and_display_attr_value (unsigned long attribute, break; case DW_FORM_sdata: - uvalue = read_leb128 (data, & bytes_read, 1); + uvalue = read_sleb128 (data, & bytes_read, end); data += bytes_read; break; case DW_FORM_GNU_str_index: - uvalue = read_leb128 (data, & bytes_read, 0); + uvalue = read_uleb128 (data, & bytes_read, end); data += bytes_read; break; case DW_FORM_ref_udata: case DW_FORM_udata: - uvalue = read_leb128 (data, & bytes_read, 0); + uvalue = read_uleb128 (data, & bytes_read, end); data += bytes_read; break; case DW_FORM_indirect: - form = read_leb128 (data, & bytes_read, 0); + form = read_uleb128 (data, & bytes_read, end); data += bytes_read; if (!do_loc) printf (" %s", get_FORM_name (form)); - return read_and_display_attr_value (attribute, form, data, + return read_and_display_attr_value (attribute, form, data, end, cu_offset, pointer_size, offset_size, dwarf_version, debug_info_p, do_loc, section, this_set); case DW_FORM_GNU_addr_index: - uvalue = read_leb128 (data, & bytes_read, 0); + uvalue = read_uleb128 (data, & bytes_read, end); data += bytes_read; break; } @@ -1491,7 +1518,7 @@ read_and_display_attr_value (unsigned long attribute, case DW_FORM_block: case DW_FORM_exprloc: - uvalue = read_leb128 (data, & bytes_read, 0); + uvalue = read_uleb128 (data, & bytes_read, end); block_start = data + bytes_read; if (do_loc) data = block_start + uvalue; @@ -1910,7 +1937,7 @@ read_and_display_attr_value (unsigned long attribute, unsigned long abbrev_number; abbrev_entry * entry; - abbrev_number = read_leb128 (section->start + uvalue, NULL, 0); + abbrev_number = read_uleb128 (section->start + uvalue, NULL, end); printf (_("[Abbrev Number: %ld"), abbrev_number); /* Don't look up abbrev for DW_FORM_ref_addr, as it very often will @@ -1966,6 +1993,7 @@ static unsigned char * read_and_display_attr (unsigned long attribute, unsigned long form, unsigned char * data, + unsigned char * end, dwarf_vma cu_offset, dwarf_vma pointer_size, dwarf_vma offset_size, @@ -1977,8 +2005,8 @@ read_and_display_attr (unsigned long attribute, { if (!do_loc) printf (" %-18s:", get_AT_name (attribute)); - data = read_and_display_attr_value (attribute, form, data, cu_offset, - pointer_size, offset_size, + data = read_and_display_attr_value (attribute, form, data, end, + cu_offset, pointer_size, offset_size, dwarf_version, debug_info_p, do_loc, section, this_set); if (!do_loc) @@ -2261,7 +2289,7 @@ process_debug_info (struct dwarf_section *section, die_offset = tags - section_begin; - abbrev_number = read_leb128 (tags, & bytes_read, 0); + abbrev_number = read_uleb128 (tags, & bytes_read, start); tags += bytes_read; /* A null DIE marks the end of a list of siblings or it may also be @@ -2378,6 +2406,7 @@ process_debug_info (struct dwarf_section *section, tags = read_and_display_attr (attr->attribute, attr->form, tags, + end, cu_offset, compunit.cu_pointer_size, offset_size, @@ -2593,19 +2622,24 @@ display_debug_lines_raw (struct dwarf_section *section, printf (" %d\t", ++state_machine_regs.last_file_entry); name = data; - data += strlen ((char *) data) + 1; printf ("%s\t", - dwarf_vmatoa ("u", read_leb128 (data, & bytes_read, 0))); + dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); data += bytes_read; printf ("%s\t", - dwarf_vmatoa ("u", read_leb128 (data, & bytes_read, 0))); + dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); data += bytes_read; printf ("%s\t", - dwarf_vmatoa ("u", read_leb128 (data, & bytes_read, 0))); + dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); data += bytes_read; printf ("%s\n", name); + + if (data == end) + { + warn (_("Corrupt file name table entry\n")); + break; + } } } @@ -2660,7 +2694,7 @@ display_debug_lines_raw (struct dwarf_section *section, else switch (op_code) { case DW_LNS_extended_op: - data += process_extended_line_op (data, linfo.li_default_is_stmt); + data += process_extended_line_op (data, linfo.li_default_is_stmt, end); break; case DW_LNS_copy: @@ -2668,7 +2702,7 @@ display_debug_lines_raw (struct dwarf_section *section, break; case DW_LNS_advance_pc: - uladv = read_leb128 (data, & bytes_read, 0); + uladv = read_uleb128 (data, & bytes_read, end); data += bytes_read; if (linfo.li_max_ops_per_insn == 1) { @@ -2695,7 +2729,7 @@ display_debug_lines_raw (struct dwarf_section *section, break; case DW_LNS_advance_line: - adv = read_sleb128 (data, & bytes_read); + adv = read_sleb128 (data, & bytes_read, end); data += bytes_read; state_machine_regs.line += adv; printf (_(" Advance Line by %s to %d\n"), @@ -2704,7 +2738,7 @@ display_debug_lines_raw (struct dwarf_section *section, break; case DW_LNS_set_file: - adv = read_leb128 (data, & bytes_read, 0); + adv = read_uleb128 (data, & bytes_read, end); data += bytes_read; printf (_(" Set File Name to entry %s in the File Name Table\n"), dwarf_vmatoa ("d", adv)); @@ -2712,7 +2746,7 @@ display_debug_lines_raw (struct dwarf_section *section, break; case DW_LNS_set_column: - uladv = read_leb128 (data, & bytes_read, 0); + uladv = read_uleb128 (data, & bytes_read, end); data += bytes_read; printf (_(" Set column to %s\n"), dwarf_vmatoa ("u", uladv)); @@ -2776,7 +2810,7 @@ display_debug_lines_raw (struct dwarf_section *section, break; case DW_LNS_set_isa: - uladv = read_leb128 (data, & bytes_read, 0); + uladv = read_uleb128 (data, & bytes_read, end); data += bytes_read; printf (_(" Set ISA to %s\n"), dwarf_vmatoa ("u", uladv)); break; @@ -2786,8 +2820,8 @@ display_debug_lines_raw (struct dwarf_section *section, for (i = standard_opcodes[op_code - 1]; i > 0 ; --i) { - printf ("0x%s%s", dwarf_vmatoa ("x", read_leb128 (data, - &bytes_read, 0)), + printf ("0x%s%s", dwarf_vmatoa ("x", read_uleb128 (data, + &bytes_read, end)), i == 1 ? "" : ", "); data += bytes_read; } @@ -2952,11 +2986,11 @@ display_debug_lines_decoded (struct dwarf_section *section, /* Skip Name, directory index, last modification time and length of file. */ data += strlen ((char *) data) + 1; - read_leb128 (data, & bytes_read, 0); + read_uleb128 (data, & bytes_read, end); data += bytes_read; - read_leb128 (data, & bytes_read, 0); + read_uleb128 (data, & bytes_read, end); data += bytes_read; - read_leb128 (data, & bytes_read, 0); + read_uleb128 (data, & bytes_read, end); data += bytes_read; n_files++; @@ -2974,13 +3008,13 @@ display_debug_lines_decoded (struct dwarf_section *section, ptr_file_name_table += strlen ((char *) ptr_file_name_table) + 1; /* We are not interested in directory, time or size. */ - file_table[i].directory_index = read_leb128 (ptr_file_name_table, - & bytes_read, 0); + file_table[i].directory_index = read_uleb128 (ptr_file_name_table, + & bytes_read, end); ptr_file_name_table += bytes_read; - file_table[i].modification_date = read_leb128 (ptr_file_name_table, - & bytes_read, 0); + file_table[i].modification_date = read_uleb128 (ptr_file_name_table, + & bytes_read, end); ptr_file_name_table += bytes_read; - file_table[i].length = read_leb128 (ptr_file_name_table, & bytes_read, 0); + file_table[i].length = read_uleb128 (ptr_file_name_table, & bytes_read, end); ptr_file_name_table += bytes_read; i++; } @@ -3051,7 +3085,8 @@ display_debug_lines_decoded (struct dwarf_section *section, unsigned char ext_op_code; unsigned char *op_code_data = data; - ext_op_code_len = read_leb128 (op_code_data, &bytes_read, 0); + ext_op_code_len = read_uleb128 (op_code_data, &bytes_read, + end_of_sequence); op_code_data += bytes_read; if (ext_op_code_len == 0) @@ -3083,15 +3118,18 @@ display_debug_lines_decoded (struct dwarf_section *section, op_code_data += strlen ((char *) op_code_data) + 1; /* Directory index. */ file_table[n_files].directory_index = - read_leb128 (op_code_data, & bytes_read, 0); + read_uleb128 (op_code_data, & bytes_read, + end_of_sequence); op_code_data += bytes_read; /* Last modification time. */ file_table[n_files].modification_date = - read_leb128 (op_code_data, & bytes_read, 0); + read_uleb128 (op_code_data, & bytes_read, + end_of_sequence); op_code_data += bytes_read; /* File length. */ file_table[n_files].length = - read_leb128 (op_code_data, & bytes_read, 0); + read_uleb128 (op_code_data, & bytes_read, + end_of_sequence); n_files++; break; @@ -3113,7 +3151,7 @@ display_debug_lines_decoded (struct dwarf_section *section, break; case DW_LNS_advance_pc: - uladv = read_leb128 (data, & bytes_read, 0); + uladv = read_uleb128 (data, & bytes_read, end); data += bytes_read; if (linfo.li_max_ops_per_insn == 1) { @@ -3133,13 +3171,13 @@ display_debug_lines_decoded (struct dwarf_section *section, break; case DW_LNS_advance_line: - adv = read_sleb128 (data, & bytes_read); + adv = read_sleb128 (data, & bytes_read, end); data += bytes_read; state_machine_regs.line += adv; break; case DW_LNS_set_file: - adv = read_leb128 (data, & bytes_read, 0); + adv = read_uleb128 (data, & bytes_read, end); data += bytes_read; state_machine_regs.file = adv; if (file_table[state_machine_regs.file - 1].directory_index == 0) @@ -3158,7 +3196,7 @@ display_debug_lines_decoded (struct dwarf_section *section, break; case DW_LNS_set_column: - uladv = read_leb128 (data, & bytes_read, 0); + uladv = read_uleb128 (data, & bytes_read, end); data += bytes_read; state_machine_regs.column = uladv; break; @@ -3206,7 +3244,7 @@ display_debug_lines_decoded (struct dwarf_section *section, break; case DW_LNS_set_isa: - uladv = read_leb128 (data, & bytes_read, 0); + uladv = read_uleb128 (data, & bytes_read, end); data += bytes_read; printf (_(" Set ISA to %lu\n"), uladv); break; @@ -3216,8 +3254,8 @@ display_debug_lines_decoded (struct dwarf_section *section, for (i = standard_opcodes[op_code - 1]; i > 0 ; --i) { - printf ("0x%s%s", dwarf_vmatoa ("x", read_leb128 (data, - &bytes_read, 0)), + printf ("0x%s%s", dwarf_vmatoa ("x", read_uleb128 (data, + &bytes_read, end)), i == 1 ? "" : ", "); data += bytes_read; } @@ -3450,9 +3488,9 @@ display_debug_macinfo (struct dwarf_section *section, { unsigned int filenum; - lineno = read_leb128 (curr, & bytes_read, 0); + lineno = read_uleb128 (curr, & bytes_read, end); curr += bytes_read; - filenum = read_leb128 (curr, & bytes_read, 0); + filenum = read_uleb128 (curr, & bytes_read, end); curr += bytes_read; printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"), @@ -3465,7 +3503,7 @@ display_debug_macinfo (struct dwarf_section *section, break; case DW_MACINFO_define: - lineno = read_leb128 (curr, & bytes_read, 0); + lineno = read_uleb128 (curr, & bytes_read, end); curr += bytes_read; string = (char *) curr; curr += strlen (string) + 1; @@ -3474,7 +3512,7 @@ display_debug_macinfo (struct dwarf_section *section, break; case DW_MACINFO_undef: - lineno = read_leb128 (curr, & bytes_read, 0); + lineno = read_uleb128 (curr, & bytes_read, end); curr += bytes_read; string = (char *) curr; curr += strlen (string) + 1; @@ -3486,7 +3524,7 @@ display_debug_macinfo (struct dwarf_section *section, { unsigned int constant; - constant = read_leb128 (curr, & bytes_read, 0); + constant = read_uleb128 (curr, & bytes_read, end); curr += bytes_read; string = (char *) curr; curr += strlen (string) + 1; @@ -3505,7 +3543,8 @@ display_debug_macinfo (struct dwarf_section *section, FILEIDX. Return NULL on failure. */ static unsigned char * -get_line_filename_and_dirname (dwarf_vma line_offset, dwarf_vma fileidx, +get_line_filename_and_dirname (dwarf_vma line_offset, + dwarf_vma fileidx, unsigned char **dir_name) { struct dwarf_section *section = &debug_displays [line].section; @@ -3513,6 +3552,7 @@ get_line_filename_and_dirname (dwarf_vma line_offset, dwarf_vma fileidx, unsigned int offset_size, initial_length_size; unsigned int version, opcode_base, bytes_read; dwarf_vma length, diridx; + const unsigned char * end; *dir_name = NULL; if (section->start == NULL @@ -3521,6 +3561,7 @@ get_line_filename_and_dirname (dwarf_vma line_offset, dwarf_vma fileidx, return NULL; hdrptr = section->start + line_offset; + end = section->start + section->size; length = byte_get (hdrptr, 4); hdrptr += 4; if (length == 0xffffffff) @@ -3560,18 +3601,18 @@ get_line_filename_and_dirname (dwarf_vma line_offset, dwarf_vma fileidx, for (; *hdrptr != '\0' && fileidx > 1; fileidx--) { hdrptr += strlen ((char *) hdrptr) + 1; - read_leb128 (hdrptr, &bytes_read, 0); + read_uleb128 (hdrptr, &bytes_read, end); hdrptr += bytes_read; - read_leb128 (hdrptr, &bytes_read, 0); + read_uleb128 (hdrptr, &bytes_read, end); hdrptr += bytes_read; - read_leb128 (hdrptr, &bytes_read, 0); + read_uleb128 (hdrptr, &bytes_read, end); hdrptr += bytes_read; } - if (*hdrptr == '\0') + if (hdrptr == end || *hdrptr == '\0') return NULL; file_name = hdrptr; hdrptr += strlen ((char *) hdrptr) + 1; - diridx = read_leb128 (hdrptr, &bytes_read, 0); + diridx = read_uleb128 (hdrptr, &bytes_read, end); if (diridx == 0) return file_name; for (; *dirtable != '\0' && diridx > 1; diridx--) @@ -3642,7 +3683,7 @@ display_debug_macro (struct dwarf_section *section, { op = byte_get (curr++, 1); extended_ops[op] = curr; - nargs = read_leb128 (curr, &bytes_read, 0); + nargs = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; if (nargs == 0) printf (_(" DW_MACRO_GNU_%02x has no arguments\n"), op); @@ -3704,9 +3745,9 @@ display_debug_macro (struct dwarf_section *section, unsigned int filenum; unsigned char *file_name = NULL, *dir_name = NULL; - lineno = read_leb128 (curr, &bytes_read, 0); + lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; - filenum = read_leb128 (curr, &bytes_read, 0); + filenum = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; if ((flags & 2) == 0) @@ -3731,7 +3772,7 @@ display_debug_macro (struct dwarf_section *section, break; case DW_MACRO_GNU_define: - lineno = read_leb128 (curr, &bytes_read, 0); + lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; string = (char *) curr; curr += strlen (string) + 1; @@ -3740,7 +3781,7 @@ display_debug_macro (struct dwarf_section *section, break; case DW_MACRO_GNU_undef: - lineno = read_leb128 (curr, &bytes_read, 0); + lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; string = (char *) curr; curr += strlen (string) + 1; @@ -3749,7 +3790,7 @@ display_debug_macro (struct dwarf_section *section, break; case DW_MACRO_GNU_define_indirect: - lineno = read_leb128 (curr, &bytes_read, 0); + lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; offset = byte_get (curr, offset_size); curr += offset_size; @@ -3759,7 +3800,7 @@ display_debug_macro (struct dwarf_section *section, break; case DW_MACRO_GNU_undef_indirect: - lineno = read_leb128 (curr, &bytes_read, 0); + lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; offset = byte_get (curr, offset_size); curr += offset_size; @@ -3776,7 +3817,7 @@ display_debug_macro (struct dwarf_section *section, break; case DW_MACRO_GNU_define_indirect_alt: - lineno = read_leb128 (curr, &bytes_read, 0); + lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; offset = byte_get (curr, offset_size); curr += offset_size; @@ -3785,7 +3826,7 @@ display_debug_macro (struct dwarf_section *section, break; case DW_MACRO_GNU_undef_indirect_alt: - lineno = read_leb128 (curr, &bytes_read, 0); + lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; offset = byte_get (curr, offset_size); curr += offset_size; @@ -3811,7 +3852,7 @@ display_debug_macro (struct dwarf_section *section, /* Skip over unhandled opcodes. */ dwarf_vma nargs, n; unsigned char *desc = extended_ops[op]; - nargs = read_leb128 (desc, &bytes_read, 0); + nargs = read_uleb128 (desc, &bytes_read, end); desc += bytes_read; if (nargs == 0) { @@ -3823,7 +3864,7 @@ display_debug_macro (struct dwarf_section *section, { curr = read_and_display_attr_value (0, byte_get (desc++, 1), - curr, 0, 0, offset_size, + curr, end, 0, 0, offset_size, version, NULL, 0, NULL, NULL); if (n != nargs - 1) @@ -4044,22 +4085,22 @@ display_loc_list_dwo (struct dwarf_section *section, printf (_("\n")); return; case 1: /* A base-address entry. */ - idx = read_leb128 (start, &bytes_read, 0); + idx = read_uleb128 (start, &bytes_read, section_end); start += bytes_read; print_addr_index (idx, 8); printf (" "); printf (_("(base address selection entry)\n")); continue; case 2: /* A start/end entry. */ - idx = read_leb128 (start, &bytes_read, 0); + idx = read_uleb128 (start, &bytes_read, section_end); start += bytes_read; print_addr_index (idx, 8); - idx = read_leb128 (start, &bytes_read, 0); + idx = read_uleb128 (start, &bytes_read, section_end); start += bytes_read; print_addr_index (idx, 8); break; case 3: /* A start/length entry. */ - idx = read_leb128 (start, &bytes_read, 0); + idx = read_uleb128 (start, &bytes_read, section_end); start += bytes_read; print_addr_index (idx, 8); idx = byte_get (start, 4); @@ -4617,13 +4658,12 @@ display_debug_ranges (struct dwarf_section *section, { unsigned char *start = section->start; unsigned char *last_start = start; - unsigned long bytes; + unsigned long bytes = section->size; unsigned char *section_begin = start; + unsigned char *finish = start + bytes; unsigned int num_range_list, i; struct range_entry *range_entries, *range_entry_fill; - bytes = section->size; - if (bytes == 0) { printf (_("\nThe %s section is empty.\n"), section->name); @@ -4711,7 +4751,7 @@ display_debug_ranges (struct dwarf_section *section, start = next; last_start = next; - while (1) + while (start < finish) { dwarf_vma begin; dwarf_vma end; @@ -4723,6 +4763,8 @@ display_debug_ranges (struct dwarf_section *section, the bottom 32-bits. */ begin = byte_get_signed (start, pointer_size); start += pointer_size; + if (start >= finish) + break; end = byte_get_signed (start, pointer_size); start += pointer_size; @@ -4987,8 +5029,8 @@ frame_display_row (Frame_Chunk *fc, int *need_col_headers, int *max_regs) } #define GET(N) byte_get (start, N); start += N -#define LEB() read_leb128 (start, & length_return, 0); start += length_return -#define SLEB() read_sleb128 (start, & length_return); start += length_return +#define LEB() read_uleb128 (start, & length_return, end); start += length_return +#define SLEB() read_sleb128 (start, & length_return, end); start += length_return static int display_debug_frames (struct dwarf_section *section, diff --git a/binutils/dwarf.h b/binutils/dwarf.h index 2d00b839902..68e93f1ccd6 100644 --- a/binutils/dwarf.h +++ b/binutils/dwarf.h @@ -1,6 +1,5 @@ /* dwarf.h - DWARF support header file - Copyright 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright 2005-2013 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -248,4 +247,4 @@ void * cmalloc (size_t, size_t); void * xcmalloc (size_t, size_t); void * xcrealloc (void *, size_t, size_t); -dwarf_vma read_leb128 (unsigned char *, unsigned int *, int); +extern dwarf_vma read_leb128 (unsigned char *, unsigned int *, bfd_boolean, const unsigned char * const); diff --git a/binutils/readelf.c b/binutils/readelf.c index a7831ef5101..b7607a0f927 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -543,10 +543,12 @@ find_section_in_set (const char * name, unsigned int * set) /* Read an unsigned LEB128 encoded value from p. Set *PLEN to the number of bytes read. */ -static unsigned long -read_uleb128 (unsigned char *data, unsigned int *length_return) +static inline unsigned long +read_uleb128 (unsigned char *data, + unsigned int *length_return, + const unsigned char * const end) { - return read_leb128 (data, length_return, 0); + return read_leb128 (data, length_return, FALSE, end); } /* Return true if the current file is for IA-64 machine and OpenVMS ABI. @@ -6860,7 +6862,7 @@ decode_arm_unwind_bytecode (struct arm_unw_aux_info *aux, break; } assert (i < sizeof (buf)); - offset = read_uleb128 (buf, &len); + offset = read_uleb128 (buf, &len, buf + i + 1); assert (len == i + 1); offset = offset * 4 + 0x204; printf ("vsp = vsp + %ld", offset); @@ -7056,7 +7058,7 @@ decode_tic6x_unwind_bytecode (struct arm_unw_aux_info *aux, break; } assert (i < sizeof (buf)); - offset = read_uleb128 (buf, &len); + offset = read_uleb128 (buf, &len, buf + i + 1); assert (len == i + 1); offset = offset * 8 + 0x408; printf (_("sp = sp + %ld"), offset); @@ -11095,6 +11097,52 @@ process_mips_fpe_exception (int mask) fputs ("0", stdout); } +/* Display's the value of TAG at location P. If TAG is + greater than 0 it is assumed to be an unknown tag, and + a message is printed to this effect. Otherwise it is + assumed that a message has already been printed. + + If the bottom bit of TAG is set it assumed to have a + string value, otherwise it is assumed to have an integer + value. + + Returns an updated P pointing to the first unread byte + beyond the end of TAG's value. + + Reads at or beyond END will not be made. */ + +static unsigned char * +display_tag_value (int tag, + unsigned char * p, + const unsigned char * const end) +{ + unsigned long val; + + if (tag > 0) + printf (" Tag_unknown_%d: ", tag); + + if (p >= end) + { + warn (_("corrupt tag\n")); + } + else if (tag & 1) + { + /* FIXME: we could read beyond END here. */ + printf ("\"%s\"\n", p); + p += strlen ((char *) p) + 1; + } + else + { + unsigned int len; + + val = read_uleb128 (p, &len, end); + p += len; + printf ("%ld (0x%lx)\n", val, val); + } + + return p; +} + /* ARM EABI attributes section. */ typedef struct { @@ -11216,7 +11264,8 @@ static arm_attr_public_tag arm_attr_public_tags[] = #undef LOOKUP static unsigned char * -display_arm_attribute (unsigned char * p) +display_arm_attribute (unsigned char * p, + const unsigned char * const end) { int tag; unsigned int len; @@ -11225,7 +11274,7 @@ display_arm_attribute (unsigned char * p) unsigned i; int type; - tag = read_uleb128 (p, &len); + tag = read_uleb128 (p, &len, end); p += len; attr = NULL; for (i = 0; i < ARRAY_SIZE (arm_attr_public_tags); i++) @@ -11246,7 +11295,7 @@ display_arm_attribute (unsigned char * p) switch (tag) { case 7: /* Tag_CPU_arch_profile. */ - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; switch (val) { @@ -11260,7 +11309,7 @@ display_arm_attribute (unsigned char * p) break; case 24: /* Tag_align_needed. */ - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; switch (val) { @@ -11279,7 +11328,7 @@ display_arm_attribute (unsigned char * p) break; case 25: /* Tag_align_preserved. */ - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; switch (val) { @@ -11298,7 +11347,7 @@ display_arm_attribute (unsigned char * p) break; case 32: /* Tag_compatibility. */ - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (_("flag = %d, vendor = %s\n"), val, p); p += strlen ((char *) p) + 1; @@ -11310,11 +11359,11 @@ display_arm_attribute (unsigned char * p) break; case 65: /* Tag_also_compatible_with. */ - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; if (val == 6 /* Tag_CPU_arch. */) { - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; if ((unsigned int)val >= ARRAY_SIZE (arm_attr_tag_CPU_arch)) printf ("??? (%d)\n", val); @@ -11332,13 +11381,13 @@ display_arm_attribute (unsigned char * p) return p; case 1: + return display_tag_value (-1, p, end); case 2: - type = attr->type; - break; + return display_tag_value (0, p, end); default: assert (attr->type & 0x80); - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; type = attr->type & 0x7f; if (val >= type) @@ -11348,87 +11397,58 @@ display_arm_attribute (unsigned char * p) return p; } } - else - { - if (tag & 1) - type = 1; /* String. */ - else - type = 2; /* uleb128. */ - printf (" Tag_unknown_%d: ", tag); - } - - if (type == 1) - { - printf ("\"%s\"\n", p); - p += strlen ((char *) p) + 1; - } - else - { - val = read_uleb128 (p, &len); - p += len; - printf ("%d (0x%x)\n", val, val); - } - return p; + return display_tag_value (tag, p, end); } static unsigned char * display_gnu_attribute (unsigned char * p, - unsigned char * (* display_proc_gnu_attribute) (unsigned char *, int)) + unsigned char * (* display_proc_gnu_attribute) (unsigned char *, int, const unsigned char * const), + const unsigned char * const end) { int tag; unsigned int len; int val; - int type; - tag = read_uleb128 (p, &len); + tag = read_uleb128 (p, &len, end); p += len; /* Tag_compatibility is the only generic GNU attribute defined at present. */ if (tag == 32) { - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; - printf (_("flag = %d, vendor = %s\n"), val, p); - p += strlen ((char *) p) + 1; + if (p == end) + { + printf (_("flag = %d, vendor = \n"), val); + warn (_("corrupt vendor attribute\n")); + } + else + { + printf (_("flag = %d, vendor = %s\n"), val, p); + p += strlen ((char *) p) + 1; + } return p; } if ((tag & 2) == 0 && display_proc_gnu_attribute) - return display_proc_gnu_attribute (p, tag); + return display_proc_gnu_attribute (p, tag, end); - if (tag & 1) - type = 1; /* String. */ - else - type = 2; /* uleb128. */ - printf (" Tag_unknown_%d: ", tag); - - if (type == 1) - { - printf ("\"%s\"\n", p); - p += strlen ((char *) p) + 1; - } - else - { - val = read_uleb128 (p, &len); - p += len; - printf ("%d (0x%x)\n", val, val); - } - - return p; + return display_tag_value (tag, p, end); } static unsigned char * -display_power_gnu_attribute (unsigned char * p, int tag) +display_power_gnu_attribute (unsigned char * p, + int tag, + const unsigned char * const end) { - int type; unsigned int len; int val; if (tag == Tag_GNU_Power_ABI_FP) { - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_GNU_Power_ABI_FP: "); @@ -11455,7 +11475,7 @@ display_power_gnu_attribute (unsigned char * p, int tag) if (tag == Tag_GNU_Power_ABI_Vector) { - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_GNU_Power_ABI_Vector: "); switch (val) @@ -11481,7 +11501,13 @@ display_power_gnu_attribute (unsigned char * p, int tag) if (tag == Tag_GNU_Power_ABI_Struct_Return) { - val = read_uleb128 (p, &len); + if (p == end) + { + warn (_("corrupt Tag_GNU_Power_ABI_Struct_Return")); + return p; + } + + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_GNU_Power_ABI_Struct_Return: "); switch (val) @@ -11502,25 +11528,7 @@ display_power_gnu_attribute (unsigned char * p, int tag) return p; } - if (tag & 1) - type = 1; /* String. */ - else - type = 2; /* uleb128. */ - printf (" Tag_unknown_%d: ", tag); - - if (type == 1) - { - printf ("\"%s\"\n", p); - p += strlen ((char *) p) + 1; - } - else - { - val = read_uleb128 (p, &len); - p += len; - printf ("%d (0x%x)\n", val, val); - } - - return p; + return display_tag_value (tag & 1, p, end); } static void @@ -11568,53 +11576,36 @@ display_sparc_hwcaps (int mask) } static unsigned char * -display_sparc_gnu_attribute (unsigned char * p, int tag) +display_sparc_gnu_attribute (unsigned char * p, + int tag, + const unsigned char * const end) { - int type; - unsigned int len; - int val; - if (tag == Tag_GNU_Sparc_HWCAPS) { - val = read_uleb128 (p, &len); + unsigned int len; + int val; + + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_GNU_Sparc_HWCAPS: "); - display_sparc_hwcaps (val); return p; } - if (tag & 1) - type = 1; /* String. */ - else - type = 2; /* uleb128. */ - printf (" Tag_unknown_%d: ", tag); - - if (type == 1) - { - printf ("\"%s\"\n", p); - p += strlen ((char *) p) + 1; - } - else - { - val = read_uleb128 (p, &len); - p += len; - printf ("%d (0x%x)\n", val, val); - } - - return p; + return display_tag_value (tag, p, end); } static unsigned char * -display_mips_gnu_attribute (unsigned char * p, int tag) +display_mips_gnu_attribute (unsigned char * p, + int tag, + const unsigned char * const end) { - int type; - unsigned int len; - int val; - if (tag == Tag_GNU_MIPS_ABI_FP) { - val = read_uleb128 (p, &len); + unsigned int len; + int val; + + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_GNU_MIPS_ABI_FP: "); @@ -11642,41 +11633,24 @@ display_mips_gnu_attribute (unsigned char * p, int tag) return p; } - if (tag & 1) - type = 1; /* String. */ - else - type = 2; /* uleb128. */ - printf (" Tag_unknown_%d: ", tag); - - if (type == 1) - { - printf ("\"%s\"\n", p); - p += strlen ((char *) p) + 1; - } - else - { - val = read_uleb128 (p, &len); - p += len; - printf ("%d (0x%x)\n", val, val); - } - - return p; + return display_tag_value (tag & 1, p, end); } static unsigned char * -display_tic6x_attribute (unsigned char * p) +display_tic6x_attribute (unsigned char * p, + const unsigned char * const end) { int tag; unsigned int len; int val; - tag = read_uleb128 (p, &len); + tag = read_uleb128 (p, &len, end); p += len; switch (tag) { case Tag_ISA: - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_ISA: "); @@ -11710,7 +11684,7 @@ display_tic6x_attribute (unsigned char * p) return p; case Tag_ABI_wchar_t: - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_ABI_wchar_t: "); switch (val) @@ -11731,7 +11705,7 @@ display_tic6x_attribute (unsigned char * p) return p; case Tag_ABI_stack_align_needed: - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_ABI_stack_align_needed: "); switch (val) @@ -11749,7 +11723,7 @@ display_tic6x_attribute (unsigned char * p) return p; case Tag_ABI_stack_align_preserved: - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_ABI_stack_align_preserved: "); switch (val) @@ -11767,7 +11741,7 @@ display_tic6x_attribute (unsigned char * p) return p; case Tag_ABI_DSBT: - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_ABI_DSBT: "); switch (val) @@ -11785,7 +11759,7 @@ display_tic6x_attribute (unsigned char * p) return p; case Tag_ABI_PID: - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_ABI_PID: "); switch (val) @@ -11806,7 +11780,7 @@ display_tic6x_attribute (unsigned char * p) return p; case Tag_ABI_PIC: - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_ABI_PIC: "); switch (val) @@ -11824,7 +11798,7 @@ display_tic6x_attribute (unsigned char * p) return p; case Tag_ABI_array_object_alignment: - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_ABI_array_object_alignment: "); switch (val) @@ -11845,7 +11819,7 @@ display_tic6x_attribute (unsigned char * p) return p; case Tag_ABI_array_object_align_expected: - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_ABI_array_object_align_expected: "); switch (val) @@ -11866,7 +11840,7 @@ display_tic6x_attribute (unsigned char * p) return p; case Tag_ABI_compatibility: - val = read_uleb128 (p, &len); + val = read_uleb128 (p, &len, end); p += len; printf (" Tag_ABI_compatibility: "); printf (_("flag = %d, vendor = %s\n"), val, p); @@ -11880,29 +11854,59 @@ display_tic6x_attribute (unsigned char * p) return p; } - printf (" Tag_unknown_%d: ", tag); + return display_tag_value (tag, p, end); +} - if (tag & 1) - { - printf ("\"%s\"\n", p); - p += strlen ((char *) p) + 1; - } - else +static void +display_raw_attribute (unsigned char * p, unsigned char * end) +{ + unsigned long addr = 0; + size_t bytes = end - p; + + while (bytes) { - val = read_uleb128 (p, &len); - p += len; - printf ("%d (0x%x)\n", val, val); + int j; + int k; + int lbytes = (bytes > 16 ? 16 : bytes); + + printf (" 0x%8.8lx ", addr); + + for (j = 0; j < 16; j++) + { + if (j < lbytes) + printf ("%2.2x", p[j]); + else + printf (" "); + + if ((j & 3) == 3) + printf (" "); + } + + for (j = 0; j < lbytes; j++) + { + k = p[j]; + if (k >= ' ' && k < 0x7f) + printf ("%c", k); + else + printf ("."); + } + + putchar ('\n'); + + p += lbytes; + bytes -= lbytes; + addr += lbytes; } - return p; + putchar ('\n'); } static int process_attributes (FILE * file, const char * public_name, unsigned int proc_type, - unsigned char * (* display_pub_attribute) (unsigned char *), - unsigned char * (* display_proc_gnu_attribute) (unsigned char *, int)) + unsigned char * (* display_pub_attribute) (unsigned char *, const unsigned char * const), + unsigned char * (* display_proc_gnu_attribute) (unsigned char *, int, const unsigned char * const)) { Elf_Internal_Shdr * sect; unsigned char * contents; @@ -11997,7 +12001,7 @@ process_attributes (FILE * file, { unsigned int j; - val = read_uleb128 (p, &j); + val = read_uleb128 (p, &j, end); p += j; if (val == 0) break; @@ -12014,18 +12018,19 @@ process_attributes (FILE * file, if (public_section) { while (p < end) - p = display_pub_attribute (p); + p = display_pub_attribute (p, end); } else if (gnu_section) { while (p < end) p = display_gnu_attribute (p, - display_proc_gnu_attribute); + display_proc_gnu_attribute, + end); } else { - /* ??? Do something sensible, like dump hex. */ printf (_(" Unknown section contexts\n")); + display_raw_attribute (p, end); p = end; } }