/* dwarf.c -- display DWARF contents of a BFD binary file
- Copyright 2005
+ Copyright 2005, 2006
Free Software Foundation, Inc.
This file is part of GNU Binutils.
Returns the number of bytes read. */
static int
-process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size)
+process_extended_line_op (unsigned char *data, int is_stmt)
{
unsigned char op_code;
unsigned int bytes_read;
break;
case DW_LNE_set_address:
- adr = byte_get (data, pointer_size);
+ adr = byte_get (data, len - bytes_read - 1);
printf (_("set Address to 0x%lx\n"), adr);
state_machine_regs.address = adr;
break;
if (section->start == NULL)
return _("<no .debug_str section>");
+ /* DWARF sections under Mach-O have non-zero addresses. */
+ offset -= section->address;
if (offset > section->size)
{
warn (_("DW_FORM_strp offset too big: %lx\n"), offset);
free_abbrevs ();
- /* Process the abbrevs used by this compilation unit. */
+ /* Process the abbrevs used by this compilation unit. DWARF
+ sections under Mach-O have non-zero addresses. */
process_abbrev_section
((unsigned char *) debug_displays [abbrev].section.start
- + compunit.cu_abbrev_offset,
+ + compunit.cu_abbrev_offset - debug_displays [abbrev].section.address,
(unsigned char *) debug_displays [abbrev].section.start
+ debug_displays [abbrev].section.size);
return 0;
}
-/* Retrieve the pointer size associated with the given compilation unit.
- Optionally the offset of this unit into the .debug_info section is
- also retutned. If there is no .debug_info section then an error
- message is issued and 0 is returned. If the requested comp unit has
- not been defined in the .debug_info section then a warning message
- is issued and the last know pointer size is returned. This message
- is only issued once per section dumped per file dumped. */
-
-static unsigned int
-get_pointer_size_and_offset_of_comp_unit (unsigned int comp_unit,
- const char * section_name,
- unsigned long * offset_return)
-{
- unsigned long offset = 0;
-
- if (num_debug_info_entries == 0)
- error (_("%s section needs a populated .debug_info section\n"),
- section_name);
-
- else if (comp_unit >= num_debug_info_entries)
- {
- if (!warned_about_missing_comp_units)
- {
- warn (_("%s section has more comp units than .debug_info section\n"),
- section_name);
- warn (_("assuming that the pointer size is %d, from the last comp unit in .debug_info\n\n"),
- last_pointer_size);
- warned_about_missing_comp_units = TRUE;
- }
- }
- else
- {
- last_pointer_size = debug_information [comp_unit].pointer_size;
- offset = debug_information [comp_unit].cu_offset;
- }
-
- if (offset_return != NULL)
- * offset_return = offset;
-
- return last_pointer_size;
-}
-
static int
display_debug_lines (struct dwarf_section *section, void *file)
{
unsigned char *start = section->start;
unsigned char *data = start;
unsigned char *end = start + section->size;
- unsigned int comp_unit = 0;
printf (_("\nDump of debug contents of section %s:\n\n"),
section->name);
unsigned char *standard_opcodes;
unsigned char *end_of_sequence;
unsigned char *hdrptr;
- unsigned int pointer_size;
int initial_length_size;
int offset_size;
int i;
info.li_line_base <<= 24;
info.li_line_base >>= 24;
- /* Get the pointer size from the comp unit associated
- with this block of line number information. */
- pointer_size = get_pointer_size_and_offset_of_comp_unit
- (comp_unit, ".debug_line", NULL);
- comp_unit ++;
-
printf (_(" Length: %ld\n"), info.li_length);
printf (_(" DWARF Version: %d\n"), info.li_version);
printf (_(" Prologue Length: %d\n"), info.li_prologue_length);
printf (_(" Line Base: %d\n"), info.li_line_base);
printf (_(" Line Range: %d\n"), info.li_line_range);
printf (_(" Opcode Base: %d\n"), info.li_opcode_base);
- printf (_(" (Pointer size: %u)%s\n"),
- pointer_size,
- warned_about_missing_comp_units ? " [assumed]" : "" );
end_of_sequence = data + info.li_length + initial_length_size;
else switch (op_code)
{
case DW_LNS_extended_op:
- if (pointer_size == 0)
- {
- warn (_("Extend line ops need a valid pointer size, guessing at 4\n"));
- pointer_size = 4;
- }
-
- data += process_extended_line_op (data, info.li_default_is_stmt,
- pointer_size);
+ data += process_extended_line_op (data, info.li_default_is_stmt);
break;
case DW_LNS_copy:
if (!seen_first_offset)
error (_("No location lists in .debug_info section!\n"));
- if (debug_information [first].loc_offsets [0] != 0)
+ /* DWARF sections under Mach-O have non-zero addresses. */
+ if (debug_information [first].num_loc_offsets > 0
+ && debug_information [first].loc_offsets [0] != section->address)
warn (_("Location lists in %s section start at 0x%lx\n"),
section->name, debug_information [first].loc_offsets [0]);
for (j = 0; j < debug_information [i].num_loc_offsets; j++)
{
has_frame_base = debug_information [i].have_frame_base [j];
- offset = debug_information [i].loc_offsets [j];
+ /* DWARF sections under Mach-O have non-zero addresses. */
+ offset = debug_information [i].loc_offsets [j] - section->address;
next = section_begin + offset;
base_address = debug_information [i].base_address;
unsigned char *ranges;
unsigned long length;
unsigned long address;
+ unsigned char address_size;
int excess;
int offset_size;
int initial_length_size;
printf (_(" Pointer Size: %d\n"), arange.ar_pointer_size);
printf (_(" Segment Size: %d\n"), arange.ar_segment_size);
- printf (_("\n Address Length\n"));
+ 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;
+ }
+
+ if (address_size > 4)
+ printf (_("\n Address Length\n"));
+ else
+ 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;
- for (;;)
- {
- address = byte_get (ranges, arange.ar_pointer_size);
+ start += arange.ar_length + initial_length_size;
- ranges += arange.ar_pointer_size;
+ while (ranges + 2 * address_size <= start)
+ {
+ address = byte_get (ranges, address_size);
- length = byte_get (ranges, arange.ar_pointer_size);
+ ranges += address_size;
- ranges += arange.ar_pointer_size;
+ length = byte_get (ranges, address_size);
- /* A pair of zeros marks the end of the list. */
- if (address == 0 && length == 0)
- break;
+ ranges += address_size;
- printf (" %8.8lx %lu\n", address, length);
+ if (address_size > 4)
+ printf (" 0x%16.16lx 0x%lx\n", address, length);
+ else
+ printf (" 0x%8.8lx 0x%lx\n", address, length);
}
-
- start += arange.ar_length + initial_length_size;
}
printf ("\n");
if (!seen_first_offset)
error (_("No range lists in .debug_info section!\n"));
- if (debug_information [first].range_lists [0] != 0)
+ /* DWARF sections under Mach-O have non-zero addresses. */
+ if (debug_information [first].num_range_lists > 0
+ && debug_information [first].range_lists [0] != section->address)
warn (_("Range lists in %s section start at 0x%lx\n"),
section->name, debug_information [first].range_lists [0]);
for (j = 0; j < debug_information [i].num_range_lists; j++)
{
- offset = debug_information [i].range_lists [j];
+ /* DWARF sections under Mach-O have non-zero addresses. */
+ offset = debug_information [i].range_lists [j] - section->address;
next = section_begin + offset;
base_address = debug_information [i].base_address;
case DW_CFA_offset:
sprintf (tmp, "c%+d", fc->col_offset[r]);
break;
+ case DW_CFA_val_offset:
+ sprintf (tmp, "v%+d", fc->col_offset[r]);
+ break;
case DW_CFA_register:
sprintf (tmp, "r%d", fc->col_offset[r]);
break;
case DW_CFA_expression:
strcpy (tmp, "exp");
break;
+ case DW_CFA_val_expression:
+ strcpy (tmp, "vexp");
+ break;
default:
strcpy (tmp, "n/a");
break;
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
{
printf ("\n%08lx ZERO terminator\n\n",
(unsigned long)(saved_start - section_start));
- return 1;
+ continue;
}
if (length == 0xffffffff)
}
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))
if (!cie)
{
- warn ("Invalid CIE pointer %08lx in FDE at %p\n",
- cie_id, saved_start);
- start = block_end;
+ warn ("Invalid CIE pointer %#08lx in FDE at %#08lx\n",
+ cie_id, (unsigned long)(saved_start - section_start));
fc->ncols = 0;
fc->col_type = xmalloc (sizeof (short int));
fc->col_offset = xmalloc (sizeof (int));
start += 4;
break;
case DW_CFA_offset_extended:
+ case DW_CFA_val_offset:
reg = LEB (); LEB ();
frame_need_space (fc, reg);
fc->col_type[reg] = DW_CFA_undefined;
start += tmp;
break;
case DW_CFA_expression:
+ case DW_CFA_val_expression:
reg = LEB ();
tmp = LEB ();
start += tmp;
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_offset_extended_sf:
+ case DW_CFA_val_offset_sf:
reg = LEB (); SLEB ();
frame_need_space (fc, reg);
fc->col_type[reg] = DW_CFA_undefined;
fc->col_offset[reg] = roffs * fc->data_factor;
break;
+ case DW_CFA_val_offset:
+ reg = LEB ();
+ roffs = LEB ();
+ if (! do_debug_frames_interp)
+ printf (" DW_CFA_val_offset: r%ld at cfa%+ld\n",
+ reg, roffs * fc->data_factor);
+ fc->col_type[reg] = DW_CFA_val_offset;
+ fc->col_offset[reg] = roffs * fc->data_factor;
+ break;
+
case DW_CFA_restore_extended:
reg = LEB ();
if (! do_debug_frames_interp)
start += ul;
break;
+ case DW_CFA_val_expression:
+ reg = LEB ();
+ ul = LEB ();
+ if (! do_debug_frames_interp)
+ {
+ printf (" DW_CFA_val_expression: r%ld (", reg);
+ decode_location_expression (start, eh_addr_size, ul, 0);
+ printf (")\n");
+ }
+ fc->col_type[reg] = DW_CFA_val_expression;
+ start += ul;
+ break;
+
case DW_CFA_offset_extended_sf:
reg = LEB ();
l = SLEB ();
fc->col_offset[reg] = l * fc->data_factor;
break;
+ case DW_CFA_val_offset_sf:
+ reg = LEB ();
+ l = SLEB ();
+ frame_need_space (fc, reg);
+ if (! do_debug_frames_interp)
+ printf (" DW_CFA_val_offset_sf: r%ld at cfa%+ld\n",
+ reg, l * fc->data_factor);
+ fc->col_type[reg] = DW_CFA_val_offset;
+ fc->col_offset[reg] = l * fc->data_factor;
+ break;
+
case DW_CFA_def_cfa_sf:
fc->cfa_reg = LEB ();
fc->cfa_offset = SLEB ();
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;
}
}