/* 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.
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++;
result |= ((dwarf_vma) (byte & 0x7f)) << shift;
shift += 7;
-
+ if ((byte & 0x80) == 0)
+ break;
}
- while (byte & 0x80);
if (length_return != NULL)
*length_return = num_read;
}
/* 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
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;
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. */
{
unsigned int opc;
- opc = read_leb128 (data, & bytes_read, 0);
+ opc = read_uleb128 (data, & bytes_read, edata);
data += bytes_read;
switch (opc)
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:
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++;
{
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);
}
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:
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:
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));
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:
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;
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;
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
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,
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));
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));
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;
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,
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;
}
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;
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
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,
{
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)
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
tags = read_and_display_attr (attr->attribute,
attr->form,
tags,
+ end,
cu_offset,
compunit.cu_pointer_size,
offset_size,
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;
+ }
}
}
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:
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)
{
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"),
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));
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));
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;
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;
}
/* 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++;
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++;
}
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)
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;
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)
{
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)
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;
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;
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;
}
{
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"),
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;
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;
{
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;
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;
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
return NULL;
hdrptr = section->start + line_offset;
+ end = section->start + section->size;
length = byte_get (hdrptr, 4);
hdrptr += 4;
if (length == 0xffffffff)
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--)
{
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);
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)
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;
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;
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;
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;
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;
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;
/* 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)
{
{
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)
printf (_("<End of list>\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);
{
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);
start = next;
last_start = next;
- while (1)
+ while (start < finish)
{
dwarf_vma begin;
dwarf_vma end;
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;
}
#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,
/* 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.
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);
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);
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
{
#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;
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++)
switch (tag)
{
case 7: /* Tag_CPU_arch_profile. */
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
switch (val)
{
break;
case 24: /* Tag_align_needed. */
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
switch (val)
{
break;
case 25: /* Tag_align_preserved. */
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
switch (val)
{
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;
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);
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)
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 = <corrupt>\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: ");
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)
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)
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
}
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: ");
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: ");
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)
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)
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)
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)
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)
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)
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)
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)
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);
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;
{
unsigned int j;
- val = read_uleb128 (p, &j);
+ val = read_uleb128 (p, &j, end);
p += j;
if (val == 0)
break;
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;
}
}