unsigned short version;
bfd_vma prologue_length;
unsigned char minimum_instruction_length;
+ unsigned char maximum_ops_per_insn;
unsigned char default_is_stmt;
int line_base;
unsigned char line_range;
return entry ? entry->head : NULL;
}
+/* Read a section, uncompress it if necessary, and relocate it. */
+
+static bfd_boolean
+read_and_uncompress_section (bfd * abfd,
+ asection * msec,
+ bfd_boolean section_is_compressed,
+ asymbol ** syms,
+ bfd_byte ** section_buffer,
+ bfd_size_type * section_size)
+{
+ /* Get the unrelocated contents of the section. */
+ *section_buffer = (bfd_byte *) bfd_malloc (*section_size);
+ if (! *section_buffer)
+ return FALSE;
+ if (! bfd_get_section_contents (abfd, msec, *section_buffer,
+ 0, *section_size))
+ return FALSE;
+
+ if (section_is_compressed)
+ {
+ if (! bfd_uncompress_section_contents (section_buffer, section_size))
+ {
+ (*_bfd_error_handler) (_("Dwarf Error: unable to decompress %s section."),
+ bfd_get_section_name (abfd, msec));
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ }
+
+ if (syms)
+ {
+ /* We want to relocate the data we've already read (and
+ decompressed), so we store a pointer to the data in
+ the bfd_section, and tell it that the contents are
+ already in memory. */
+ BFD_ASSERT (msec->contents == NULL && (msec->flags & SEC_IN_MEMORY) == 0);
+ msec->contents = *section_buffer;
+ msec->flags |= SEC_IN_MEMORY;
+ msec->size = *section_size;
+ *section_buffer
+ = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms);
+ if (! *section_buffer)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* Read a section into its appropriate place in the dwarf2_debug
struct (indicated by SECTION_BUFFER and SECTION_SIZE). If SYMS is
not NULL, use bfd_simple_get_relocated_section_contents to read the
}
*section_size = msec->rawsize ? msec->rawsize : msec->size;
- if (syms)
- {
- *section_buffer
- = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms);
- if (! *section_buffer)
- return FALSE;
- }
- else
- {
- *section_buffer = (bfd_byte *) bfd_malloc (*section_size);
- if (! *section_buffer)
- return FALSE;
- if (! bfd_get_section_contents (abfd, msec, *section_buffer,
- 0, *section_size))
- return FALSE;
- }
- if (section_is_compressed)
- {
- if (! bfd_uncompress_section_contents (section_buffer, section_size))
- {
- (*_bfd_error_handler) (_("Dwarf Error: unable to decompress %s section."), compressed_section_name);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
- }
+ if (! read_and_uncompress_section (abfd, msec, section_is_compressed,
+ syms, section_buffer, section_size))
+ return FALSE;
}
/* It is possible to get a bad value for the offset into the section
char *filename;
unsigned int line;
unsigned int column;
- int end_sequence; /* End of (sequential) code sequence. */
+ unsigned char op_index;
+ unsigned char end_sequence; /* End of (sequential) code sequence. */
};
struct fileinfo
{
return (new_line->address > line->address
|| (new_line->address == line->address
- && new_line->end_sequence < line->end_sequence));
+ && (new_line->op_index > line->op_index
+ || (new_line->op_index == line->op_index
+ && new_line->end_sequence < line->end_sequence))));
}
static bfd_boolean
add_line_info (struct line_info_table *table,
bfd_vma address,
+ unsigned char op_index,
char *filename,
unsigned int line,
unsigned int column,
/* Set member data of 'info'. */
info->address = address;
+ info->op_index = op_index;
info->line = line;
info->column = column;
info->end_sequence = end_sequence;
if (seq
&& seq->last_line->address == address
+ && seq->last_line->op_index == op_index
&& seq->last_line->end_sequence == end_sequence)
{
/* We only keep the last entry with the same address and end
if (seq1->last_line->address > seq2->last_line->address)
return -1;
+ if (seq1->last_line->op_index < seq2->last_line->op_index)
+ return 1;
+ if (seq1->last_line->op_index > seq2->last_line->op_index)
+ return -1;
+
return 0;
}
}
line_end = line_ptr + lh.total_length;
lh.version = read_2_bytes (abfd, line_ptr);
+ if (lh.version < 2 || lh.version > 4)
+ {
+ (*_bfd_error_handler)
+ (_("Dwarf Error: Unhandled .debug_line version %d."), lh.version);
+ bfd_set_error (bfd_error_bad_value);
+ return NULL;
+ }
line_ptr += 2;
if (offset_size == 4)
lh.prologue_length = read_4_bytes (abfd, line_ptr);
line_ptr += offset_size;
lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
line_ptr += 1;
+ if (lh.version >= 4)
+ {
+ lh.maximum_ops_per_insn = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ }
+ else
+ lh.maximum_ops_per_insn = 1;
+ if (lh.maximum_ops_per_insn == 0)
+ {
+ (*_bfd_error_handler)
+ (_("Dwarf Error: Invalid maximum operations per instruction."));
+ bfd_set_error (bfd_error_bad_value);
+ return NULL;
+ }
lh.default_is_stmt = read_1_byte (abfd, line_ptr);
line_ptr += 1;
lh.line_base = read_1_signed_byte (abfd, line_ptr);
{
/* State machine registers. */
bfd_vma address = 0;
+ unsigned char op_index = 0;
char * filename = table->num_files ? concat_filename (table, 1) : NULL;
unsigned int line = 1;
unsigned int column = 0;
{
/* Special operand. */
adj_opcode = op_code - lh.opcode_base;
- address += (adj_opcode / lh.line_range)
- * lh.minimum_instruction_length;
+ if (lh.maximum_ops_per_insn == 1)
+ address += (adj_opcode / lh.line_range)
+ * lh.minimum_instruction_length;
+ else
+ {
+ address += ((op_index + (adj_opcode / lh.line_range))
+ / lh.maximum_ops_per_insn)
+ * lh.minimum_instruction_length;
+ op_index = (op_index + (adj_opcode / lh.line_range))
+ % lh.maximum_ops_per_insn;
+ }
line += lh.line_base + (adj_opcode % lh.line_range);
/* Append row to matrix using current values. */
- if (!add_line_info (table, address, filename, line, column, 0))
+ if (!add_line_info (table, address, op_index, filename,
+ line, column, 0))
goto line_fail;
if (address < low_pc)
low_pc = address;
{
case DW_LNE_end_sequence:
end_sequence = 1;
- if (!add_line_info (table, address, filename, line, column,
- end_sequence))
+ if (!add_line_info (table, address, op_index, filename,
+ line, column, end_sequence))
goto line_fail;
if (address < low_pc)
low_pc = address;
break;
case DW_LNE_set_address:
address = read_address (unit, line_ptr);
+ op_index = 0;
line_ptr += unit->addr_size;
break;
case DW_LNE_define_file:
}
break;
case DW_LNS_copy:
- if (!add_line_info (table, address, filename, line, column, 0))
+ if (!add_line_info (table, address, op_index,
+ filename, line, column, 0))
goto line_fail;
if (address < low_pc)
low_pc = address;
high_pc = address;
break;
case DW_LNS_advance_pc:
- address += lh.minimum_instruction_length
- * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ if (lh.maximum_ops_per_insn == 1)
+ address += lh.minimum_instruction_length
+ * read_unsigned_leb128 (abfd, line_ptr,
+ &bytes_read);
+ else
+ {
+ bfd_vma adjust = read_unsigned_leb128 (abfd, line_ptr,
+ &bytes_read);
+ address = ((op_index + adjust) / lh.maximum_ops_per_insn)
+ * lh.minimum_instruction_length;
+ op_index = (op_index + adjust) % lh.maximum_ops_per_insn;
+ }
line_ptr += bytes_read;
break;
case DW_LNS_advance_line:
case DW_LNS_set_basic_block:
break;
case DW_LNS_const_add_pc:
- address += lh.minimum_instruction_length
- * ((255 - lh.opcode_base) / lh.line_range);
+ if (lh.maximum_ops_per_insn == 1)
+ address += lh.minimum_instruction_length
+ * ((255 - lh.opcode_base) / lh.line_range);
+ else
+ {
+ bfd_vma adjust = ((255 - lh.opcode_base) / lh.line_range);
+ address += lh.minimum_instruction_length
+ * ((op_index + adjust) / lh.maximum_ops_per_insn);
+ op_index = (op_index + adjust) % lh.maximum_ops_per_insn;
+ }
break;
case DW_LNS_fixed_advance_pc:
address += read_2_bytes (abfd, line_ptr);
+ op_index = 0;
line_ptr += 2;
break;
default:
switch (attr.name)
{
case DW_AT_name:
- /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name. */
+ /* Prefer DW_AT_MIPS_linkage_name or DW_AT_linkage_name
+ over DW_AT_name. */
if (name == NULL)
name = attr.u.str;
break;
case DW_AT_specification:
name = find_abstract_instance_name (unit, &attr);
break;
+ case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name:
name = attr.u.str;
break;
break;
case DW_AT_name:
- /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name. */
+ /* Prefer DW_AT_MIPS_linkage_name or DW_AT_linkage_name
+ over DW_AT_name. */
if (func->name == NULL)
func->name = attr.u.str;
break;
+ case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name:
func->name = attr.u.str;
break;
{
bfd_size_type size = msec->size;
bfd_byte *buffer, *tmp;
+ bfd_boolean is_compressed =
+ strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0;
if (size == 0)
continue;
- buffer = (bfd_simple_get_relocated_section_contents
- (debug_bfd, msec, NULL, symbols));
- if (! buffer)
+ if (! read_and_uncompress_section (debug_bfd, msec,
+ is_compressed, symbols,
+ &buffer, &size))
goto done;
- if (strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0)
- {
- if (! bfd_uncompress_section_contents (&buffer, &size))
- {
- free (buffer);
- goto done;
- }
- }
tmp = (bfd_byte *) bfd_realloc (stash->info_ptr_memory,
total_size + size);
if (tmp == NULL)