mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-26 10:45:42 +00:00
Compare commits
27 Commits
gdb-11.1-r
...
users/ccou
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83222732f1 | ||
|
|
c312754797 | ||
|
|
76b3c0a533 | ||
|
|
f0c3f9ad7b | ||
|
|
589778e030 | ||
|
|
b3759731e0 | ||
|
|
89442fc483 | ||
|
|
05305251ad | ||
|
|
d4c40a8552 | ||
|
|
f7318adf46 | ||
|
|
a38fe6acd2 | ||
|
|
e82144ec93 | ||
|
|
b18ad49bab | ||
|
|
285d7b5c33 | ||
|
|
2031626eb7 | ||
|
|
dc87246eb9 | ||
|
|
49e4ed79b8 | ||
|
|
c63bcc5d2d | ||
|
|
361595a3de | ||
|
|
fc0d0b62cb | ||
|
|
6a8cf4ce11 | ||
|
|
ab071889a9 | ||
|
|
af9adba57a | ||
|
|
c85ff14427 | ||
|
|
e7ca0f8d7d | ||
|
|
b274bee161 | ||
|
|
244e0772d8 |
698
binutils/dwarf.c
698
binutils/dwarf.c
@@ -381,6 +381,9 @@ typedef struct State_Machine_Registers
|
|||||||
unsigned int file;
|
unsigned int file;
|
||||||
unsigned int line;
|
unsigned int line;
|
||||||
unsigned int column;
|
unsigned int column;
|
||||||
|
unsigned int discriminator;
|
||||||
|
unsigned int context;
|
||||||
|
unsigned int subprogram;
|
||||||
int is_stmt;
|
int is_stmt;
|
||||||
int basic_block;
|
int basic_block;
|
||||||
unsigned char op_index;
|
unsigned char op_index;
|
||||||
@@ -400,19 +403,65 @@ reset_state_machine (int is_stmt)
|
|||||||
state_machine_regs.file = 1;
|
state_machine_regs.file = 1;
|
||||||
state_machine_regs.line = 1;
|
state_machine_regs.line = 1;
|
||||||
state_machine_regs.column = 0;
|
state_machine_regs.column = 0;
|
||||||
|
state_machine_regs.discriminator = 0;
|
||||||
|
state_machine_regs.context = 0;
|
||||||
|
state_machine_regs.subprogram = 0;
|
||||||
state_machine_regs.is_stmt = is_stmt;
|
state_machine_regs.is_stmt = is_stmt;
|
||||||
state_machine_regs.basic_block = 0;
|
state_machine_regs.basic_block = 0;
|
||||||
state_machine_regs.end_sequence = 0;
|
state_machine_regs.end_sequence = 0;
|
||||||
state_machine_regs.last_file_entry = 0;
|
state_machine_regs.last_file_entry = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Build a logicals table for reference when reading the actuals table. */
|
||||||
|
|
||||||
|
static SMR *logicals_table = NULL;
|
||||||
|
static unsigned int logicals_allocated = 0;
|
||||||
|
static unsigned int logicals_count = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_logicals (void)
|
||||||
|
{
|
||||||
|
free (logicals_table);
|
||||||
|
logicals_allocated = 0;
|
||||||
|
logicals_count = 0;
|
||||||
|
logicals_table = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_logical (void)
|
||||||
|
{
|
||||||
|
if (logicals_allocated == 0)
|
||||||
|
{
|
||||||
|
logicals_allocated = 4;
|
||||||
|
logicals_table = (SMR *) xmalloc (logicals_allocated * sizeof (SMR));
|
||||||
|
}
|
||||||
|
if (logicals_count >= logicals_allocated)
|
||||||
|
{
|
||||||
|
logicals_allocated *= 2;
|
||||||
|
logicals_table = (SMR *)
|
||||||
|
xrealloc (logicals_table, logicals_allocated * sizeof (SMR));
|
||||||
|
}
|
||||||
|
logicals_table[logicals_count++] = state_machine_regs;
|
||||||
|
printf (_("\t\tLogical %u: 0x%s[%u] file %u line %u discrim %u context %u subprog %u is_stmt %d\n"),
|
||||||
|
logicals_count,
|
||||||
|
dwarf_vmatoa ("x", state_machine_regs.address),
|
||||||
|
state_machine_regs.op_index,
|
||||||
|
state_machine_regs.file,
|
||||||
|
state_machine_regs.line,
|
||||||
|
state_machine_regs.discriminator,
|
||||||
|
state_machine_regs.context,
|
||||||
|
state_machine_regs.subprogram,
|
||||||
|
state_machine_regs.is_stmt);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handled an extend line op.
|
/* Handled an extend line op.
|
||||||
Returns the number of bytes read. */
|
Returns the number of bytes read. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_extended_line_op (unsigned char * data,
|
process_extended_line_op (unsigned char * data,
|
||||||
int is_stmt,
|
int is_stmt,
|
||||||
unsigned char * end)
|
unsigned char * end,
|
||||||
|
int is_logical)
|
||||||
{
|
{
|
||||||
unsigned char op_code;
|
unsigned char op_code;
|
||||||
unsigned int bytes_read;
|
unsigned int bytes_read;
|
||||||
@@ -439,6 +488,8 @@ process_extended_line_op (unsigned char * data,
|
|||||||
{
|
{
|
||||||
case DW_LNE_end_sequence:
|
case DW_LNE_end_sequence:
|
||||||
printf (_("End of Sequence\n\n"));
|
printf (_("End of Sequence\n\n"));
|
||||||
|
if (is_logical)
|
||||||
|
append_logical ();
|
||||||
reset_state_machine (is_stmt);
|
reset_state_machine (is_stmt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -473,8 +524,14 @@ process_extended_line_op (unsigned char * data,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_LNE_set_discriminator:
|
case DW_LNE_set_discriminator:
|
||||||
printf (_("set Discriminator to %s\n"),
|
{
|
||||||
dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
|
unsigned int discrim;
|
||||||
|
|
||||||
|
discrim = read_uleb128 (data, & bytes_read, end);
|
||||||
|
data += bytes_read;
|
||||||
|
printf (_("set Discriminator to %u\n"), discrim);
|
||||||
|
state_machine_regs.discriminator = discrim;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* HP extensions. */
|
/* HP extensions. */
|
||||||
@@ -587,7 +644,7 @@ fetch_indirect_string (dwarf_vma offset)
|
|||||||
if (section->start == NULL)
|
if (section->start == NULL)
|
||||||
return (const unsigned char *) _("<no .debug_str section>");
|
return (const unsigned char *) _("<no .debug_str section>");
|
||||||
|
|
||||||
if (offset > section->size)
|
if (offset >= section->size)
|
||||||
{
|
{
|
||||||
warn (_("DW_FORM_strp offset too big: %s\n"),
|
warn (_("DW_FORM_strp offset too big: %s\n"),
|
||||||
dwarf_vmatoa ("x", offset));
|
dwarf_vmatoa ("x", offset));
|
||||||
@@ -597,6 +654,24 @@ fetch_indirect_string (dwarf_vma offset)
|
|||||||
return (const unsigned char *) section->start + offset;
|
return (const unsigned char *) section->start + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const unsigned char *
|
||||||
|
fetch_indirect_line_string (dwarf_vma offset)
|
||||||
|
{
|
||||||
|
struct dwarf_section *section = &debug_displays [line_str].section;
|
||||||
|
|
||||||
|
if (section->start == NULL)
|
||||||
|
return (const unsigned char *) _("<no .debug_line_str section>");
|
||||||
|
|
||||||
|
if (offset >= section->size)
|
||||||
|
{
|
||||||
|
warn (_("DW_FORM_line_strp offset too big: %s\n"),
|
||||||
|
dwarf_vmatoa ("x", offset));
|
||||||
|
return (const unsigned char *) _("<offset is too big>");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (const unsigned char *) section->start + offset;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
|
fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
|
||||||
dwarf_vma offset_size, int dwo)
|
dwarf_vma offset_size, int dwo)
|
||||||
@@ -614,7 +689,7 @@ fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
|
|||||||
|
|
||||||
if (this_set != NULL)
|
if (this_set != NULL)
|
||||||
index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS];
|
index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS];
|
||||||
if (index_offset > index_section->size)
|
if (index_offset + offset_size > index_section->size)
|
||||||
{
|
{
|
||||||
warn (_("DW_FORM_GNU_str_index offset too big: %s\n"),
|
warn (_("DW_FORM_GNU_str_index offset too big: %s\n"),
|
||||||
dwarf_vmatoa ("x", index_offset));
|
dwarf_vmatoa ("x", index_offset));
|
||||||
@@ -627,7 +702,7 @@ fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
|
|||||||
|
|
||||||
str_offset = byte_get (index_section->start + index_offset, offset_size);
|
str_offset = byte_get (index_section->start + index_offset, offset_size);
|
||||||
str_offset -= str_section->address;
|
str_offset -= str_section->address;
|
||||||
if (str_offset > str_section->size)
|
if (str_offset >= str_section->size)
|
||||||
{
|
{
|
||||||
warn (_("DW_FORM_GNU_str_index indirect offset too big: %s\n"),
|
warn (_("DW_FORM_GNU_str_index indirect offset too big: %s\n"),
|
||||||
dwarf_vmatoa ("x", str_offset));
|
dwarf_vmatoa ("x", str_offset));
|
||||||
@@ -2670,6 +2745,10 @@ load_debug_info (void * file)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Experimental DWARF 5 extensions.
|
||||||
|
See http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables. */
|
||||||
|
#define DWARF2_LINE_EXPERIMENTAL_VERSION 0xf006
|
||||||
|
|
||||||
/* Read a DWARF .debug_line section header starting at DATA.
|
/* Read a DWARF .debug_line section header starting at DATA.
|
||||||
Upon success returns an updated DATA pointer and the LINFO
|
Upon success returns an updated DATA pointer and the LINFO
|
||||||
structure and the END_OF_SEQUENCE pointer will be filled in.
|
structure and the END_OF_SEQUENCE pointer will be filled in.
|
||||||
@@ -2680,7 +2759,9 @@ read_debug_line_header (struct dwarf_section * section,
|
|||||||
unsigned char * data,
|
unsigned char * data,
|
||||||
unsigned char * end,
|
unsigned char * end,
|
||||||
DWARF2_Internal_LineInfo * linfo,
|
DWARF2_Internal_LineInfo * linfo,
|
||||||
unsigned char ** end_of_sequence)
|
unsigned char ** end_of_sequence,
|
||||||
|
unsigned int * pinitial_length_size,
|
||||||
|
unsigned int * poffset_size)
|
||||||
{
|
{
|
||||||
unsigned char *hdrptr;
|
unsigned char *hdrptr;
|
||||||
unsigned int offset_size;
|
unsigned int offset_size;
|
||||||
@@ -2705,6 +2786,8 @@ read_debug_line_header (struct dwarf_section * section,
|
|||||||
offset_size = 4;
|
offset_size = 4;
|
||||||
initial_length_size = 4;
|
initial_length_size = 4;
|
||||||
}
|
}
|
||||||
|
*pinitial_length_size = initial_length_size;
|
||||||
|
*poffset_size = offset_size;
|
||||||
|
|
||||||
if (linfo->li_length + initial_length_size > section->size)
|
if (linfo->li_length + initial_length_size > section->size)
|
||||||
{
|
{
|
||||||
@@ -2727,15 +2810,30 @@ read_debug_line_header (struct dwarf_section * section,
|
|||||||
/* Get and check the version number. */
|
/* Get and check the version number. */
|
||||||
SAFE_BYTE_GET_AND_INC (linfo->li_version, hdrptr, 2, end);
|
SAFE_BYTE_GET_AND_INC (linfo->li_version, hdrptr, 2, end);
|
||||||
|
|
||||||
|
/* Version 0xf006 is for experimental two-level line tables. */
|
||||||
if (linfo->li_version != 2
|
if (linfo->li_version != 2
|
||||||
&& linfo->li_version != 3
|
&& linfo->li_version != 3
|
||||||
&& linfo->li_version != 4)
|
&& linfo->li_version != 4
|
||||||
|
&& linfo->li_version != 5
|
||||||
|
&& linfo->li_version != DWARF2_LINE_EXPERIMENTAL_VERSION)
|
||||||
{
|
{
|
||||||
warn (_("Only DWARF version 2, 3 and 4 line info is currently supported.\n"));
|
warn (_("Only DWARF versions 2-5 line info are currently supported.\n"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (linfo->li_version < 5)
|
||||||
|
{
|
||||||
|
linfo->li_address_size = 0;
|
||||||
|
linfo->li_segment_size = 0;
|
||||||
|
}
|
||||||
|
else if (linfo->li_version != DWARF2_LINE_EXPERIMENTAL_VERSION)
|
||||||
|
{
|
||||||
|
SAFE_BYTE_GET_AND_INC (linfo->li_address_size, hdrptr, 1, end);
|
||||||
|
SAFE_BYTE_GET_AND_INC (linfo->li_segment_size, hdrptr, 1, end);
|
||||||
|
}
|
||||||
|
|
||||||
SAFE_BYTE_GET_AND_INC (linfo->li_prologue_length, hdrptr, offset_size, end);
|
SAFE_BYTE_GET_AND_INC (linfo->li_prologue_length, hdrptr, offset_size, end);
|
||||||
|
|
||||||
SAFE_BYTE_GET_AND_INC (linfo->li_min_insn_length, hdrptr, 1, end);
|
SAFE_BYTE_GET_AND_INC (linfo->li_min_insn_length, hdrptr, 1, end);
|
||||||
|
|
||||||
if (linfo->li_version >= 4)
|
if (linfo->li_version >= 4)
|
||||||
@@ -2769,97 +2867,12 @@ read_debug_line_header (struct dwarf_section * section,
|
|||||||
return hdrptr;
|
return hdrptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
display_debug_lines_raw (struct dwarf_section *section,
|
display_directory_table_v4 (unsigned char *start, unsigned char *end,
|
||||||
unsigned char *data,
|
unsigned char **pdata)
|
||||||
unsigned char *end)
|
|
||||||
{
|
{
|
||||||
unsigned char *start = section->start;
|
unsigned char *data = *pdata;
|
||||||
|
|
||||||
printf (_("Raw dump of debug contents of section %s:\n\n"),
|
|
||||||
section->name);
|
|
||||||
|
|
||||||
while (data < end)
|
|
||||||
{
|
|
||||||
static DWARF2_Internal_LineInfo saved_linfo;
|
|
||||||
DWARF2_Internal_LineInfo linfo;
|
|
||||||
unsigned char *standard_opcodes;
|
|
||||||
unsigned char *end_of_sequence;
|
|
||||||
unsigned int last_dir_entry = 0;
|
unsigned int last_dir_entry = 0;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (const_strneq (section->name, ".debug_line.")
|
|
||||||
/* Note: the following does not apply to .debug_line.dwo sections.
|
|
||||||
These are full debug_line sections. */
|
|
||||||
&& strcmp (section->name, ".debug_line.dwo") != 0)
|
|
||||||
{
|
|
||||||
/* Sections named .debug_line.<foo> are fragments of a .debug_line
|
|
||||||
section containing just the Line Number Statements. They are
|
|
||||||
created by the assembler and intended to be used alongside gcc's
|
|
||||||
-ffunction-sections command line option. When the linker's
|
|
||||||
garbage collection decides to discard a .text.<foo> section it
|
|
||||||
can then also discard the line number information in .debug_line.<foo>.
|
|
||||||
|
|
||||||
Since the section is a fragment it does not have the details
|
|
||||||
needed to fill out a LineInfo structure, so instead we use the
|
|
||||||
details from the last full debug_line section that we processed. */
|
|
||||||
end_of_sequence = end;
|
|
||||||
standard_opcodes = NULL;
|
|
||||||
linfo = saved_linfo;
|
|
||||||
/* PR 17531: file: 0522b371. */
|
|
||||||
if (linfo.li_line_range == 0)
|
|
||||||
{
|
|
||||||
warn (_("Partial .debug_line. section encountered without a prior full .debug_line section"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
reset_state_machine (linfo.li_default_is_stmt);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned char * hdrptr;
|
|
||||||
|
|
||||||
if ((hdrptr = read_debug_line_header (section, data, end, & linfo,
|
|
||||||
& end_of_sequence)) == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
printf (_(" Offset: 0x%lx\n"), (long)(data - start));
|
|
||||||
printf (_(" Length: %ld\n"), (long) linfo.li_length);
|
|
||||||
printf (_(" DWARF Version: %d\n"), linfo.li_version);
|
|
||||||
printf (_(" Prologue Length: %d\n"), linfo.li_prologue_length);
|
|
||||||
printf (_(" Minimum Instruction Length: %d\n"), linfo.li_min_insn_length);
|
|
||||||
if (linfo.li_version >= 4)
|
|
||||||
printf (_(" Maximum Ops per Instruction: %d\n"), linfo.li_max_ops_per_insn);
|
|
||||||
printf (_(" Initial value of 'is_stmt': %d\n"), linfo.li_default_is_stmt);
|
|
||||||
printf (_(" Line Base: %d\n"), linfo.li_line_base);
|
|
||||||
printf (_(" Line Range: %d\n"), linfo.li_line_range);
|
|
||||||
printf (_(" Opcode Base: %d\n"), linfo.li_opcode_base);
|
|
||||||
|
|
||||||
/* PR 17512: file: 1665-6428-0.004. */
|
|
||||||
if (linfo.li_line_range == 0)
|
|
||||||
{
|
|
||||||
warn (_("Line range of 0 is invalid, using 1 instead\n"));
|
|
||||||
linfo.li_line_range = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_state_machine (linfo.li_default_is_stmt);
|
|
||||||
|
|
||||||
/* Display the contents of the Opcodes table. */
|
|
||||||
standard_opcodes = hdrptr;
|
|
||||||
|
|
||||||
/* PR 17512: file: 002-417945-0.004. */
|
|
||||||
if (standard_opcodes + linfo.li_opcode_base >= end)
|
|
||||||
{
|
|
||||||
warn (_("Line Base extends beyond end of section\n"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf (_("\n Opcodes:\n"));
|
|
||||||
|
|
||||||
for (i = 1; i < linfo.li_opcode_base; i++)
|
|
||||||
printf (_(" Opcode %d has %d args\n"), i, standard_opcodes[i - 1]);
|
|
||||||
|
|
||||||
/* Display the contents of the Directory table. */
|
|
||||||
data = standard_opcodes + linfo.li_opcode_base - 1;
|
|
||||||
|
|
||||||
if (*data == 0)
|
if (*data == 0)
|
||||||
printf (_("\n The Directory Table is empty.\n"));
|
printf (_("\n The Directory Table is empty.\n"));
|
||||||
@@ -2874,16 +2887,18 @@ display_debug_lines_raw (struct dwarf_section *section,
|
|||||||
|
|
||||||
data += strnlen ((char *) data, end - data) + 1;
|
data += strnlen ((char *) data, end - data) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PR 17512: file: 002-132094-0.004. */
|
|
||||||
if (data >= end - 1)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip the NUL at the end of the table. */
|
/* Skip the NUL at the end of the table. */
|
||||||
data++;
|
*pdata = data + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
display_file_name_table_v4 (unsigned char *start, unsigned char *end,
|
||||||
|
unsigned char **pdata)
|
||||||
|
{
|
||||||
|
unsigned char *data = *pdata;
|
||||||
|
|
||||||
/* Display the contents of the File Name table. */
|
|
||||||
if (*data == 0)
|
if (*data == 0)
|
||||||
printf (_("\n The File Name Table is empty.\n"));
|
printf (_("\n The File Name Table is empty.\n"));
|
||||||
else
|
else
|
||||||
@@ -2921,36 +2936,155 @@ display_debug_lines_raw (struct dwarf_section *section,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Skip the NUL at the end of the table. */
|
/* Skip the NUL at the end of the table. */
|
||||||
data++;
|
*pdata = data + 1;
|
||||||
putchar ('\n');
|
|
||||||
saved_linfo = linfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now display the statements. */
|
static int
|
||||||
if (data >= end_of_sequence)
|
display_dir_file_table_v5 (unsigned char *start, unsigned char *end,
|
||||||
printf (_(" No Line Number Statements.\n"));
|
unsigned char **pdata, char *table_name,
|
||||||
|
unsigned int offset_size)
|
||||||
|
{
|
||||||
|
unsigned char *data = *pdata;
|
||||||
|
unsigned int bytes_read;
|
||||||
|
unsigned int format_count;
|
||||||
|
unsigned int *content_types;
|
||||||
|
unsigned int *content_forms;
|
||||||
|
unsigned int entry_count;
|
||||||
|
unsigned int i, j;
|
||||||
|
const unsigned char *name;
|
||||||
|
dwarf_vma offset;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
format_count = read_uleb128 (data, & bytes_read, end);
|
||||||
|
data += bytes_read;
|
||||||
|
content_types = (unsigned int *) xmalloc (format_count *
|
||||||
|
sizeof (unsigned int));
|
||||||
|
content_forms = (unsigned int *) xmalloc (format_count *
|
||||||
|
sizeof (unsigned int));
|
||||||
|
for (j = 0; j < format_count; j++)
|
||||||
|
{
|
||||||
|
content_types[j] = read_uleb128 (data, & bytes_read, end);
|
||||||
|
data += bytes_read;
|
||||||
|
content_forms[j] = read_uleb128 (data, & bytes_read, end);
|
||||||
|
data += bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_count = read_uleb128 (data, & bytes_read, end);
|
||||||
|
data += bytes_read;
|
||||||
|
|
||||||
|
if (entry_count == 0)
|
||||||
|
printf (_("\n The %s Table is empty.\n"), table_name);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf (_(" Line Number Statements:\n"));
|
printf (_("\n The %s Table (offset 0x%lx):\n"),
|
||||||
|
table_name, (long)(data - start));
|
||||||
|
|
||||||
while (data < end_of_sequence)
|
printf (_(" Entry"));
|
||||||
|
for (j = 0; j < format_count; j++)
|
||||||
|
{
|
||||||
|
printf ("\t");
|
||||||
|
switch (content_types[j])
|
||||||
|
{
|
||||||
|
case DW_LNCT_path:
|
||||||
|
printf (_("Path"));
|
||||||
|
break;
|
||||||
|
case DW_LNCT_subprogram_name:
|
||||||
|
printf (_("Name"));
|
||||||
|
break;
|
||||||
|
case DW_LNCT_directory_index:
|
||||||
|
printf (_("Dir"));
|
||||||
|
break;
|
||||||
|
case DW_LNCT_decl_file:
|
||||||
|
printf (_("File"));
|
||||||
|
break;
|
||||||
|
case DW_LNCT_decl_line:
|
||||||
|
printf (_("Line"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < entry_count; i++)
|
||||||
|
{
|
||||||
|
printf (" %d", i + 1);
|
||||||
|
for (j = 0; j < format_count; j++)
|
||||||
|
{
|
||||||
|
if (data >= end)
|
||||||
|
break;
|
||||||
|
switch (content_forms[j])
|
||||||
|
{
|
||||||
|
case DW_FORM_string:
|
||||||
|
printf ("\t%.*s", (int) (end - data), data);
|
||||||
|
data += strnlen ((char *) data, end - data) + 1;
|
||||||
|
break;
|
||||||
|
case DW_FORM_line_strp:
|
||||||
|
SAFE_BYTE_GET_AND_INC (offset, data, offset_size, end);
|
||||||
|
name = fetch_indirect_line_string (offset);
|
||||||
|
printf ("\t%s", name);
|
||||||
|
break;
|
||||||
|
case DW_FORM_udata:
|
||||||
|
val = read_uleb128 (data, & bytes_read, end);
|
||||||
|
data += bytes_read;
|
||||||
|
printf ("\t%u", val);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf ("\t%s", _("(unrecognized FORM code)"));
|
||||||
|
data = end;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
|
||||||
|
/* PR 17512: file: 002-132094-0.004. */
|
||||||
|
if (data >= end - 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (content_types);
|
||||||
|
free (content_forms);
|
||||||
|
|
||||||
|
*pdata = data;
|
||||||
|
return entry_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
display_line_program (unsigned char *start, unsigned char *end,
|
||||||
|
unsigned char **pdata, char *table_name,
|
||||||
|
DWARF2_Internal_LineInfo *linfo,
|
||||||
|
unsigned char *standard_opcodes,
|
||||||
|
int is_logical)
|
||||||
|
{
|
||||||
|
unsigned char *data = *pdata;
|
||||||
|
|
||||||
|
if (data >= end)
|
||||||
|
{
|
||||||
|
printf (_(" No %s.\n"), table_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf (" %s:\n", table_name);
|
||||||
|
|
||||||
|
while (data < end)
|
||||||
{
|
{
|
||||||
unsigned char op_code;
|
unsigned char op_code;
|
||||||
dwarf_signed_vma adv;
|
dwarf_signed_vma adv;
|
||||||
dwarf_vma uladv;
|
dwarf_vma uladv;
|
||||||
unsigned int bytes_read;
|
unsigned int bytes_read;
|
||||||
|
unsigned int logical;
|
||||||
|
int i;
|
||||||
|
|
||||||
printf (" [0x%08lx]", (long)(data - start));
|
printf (" [0x%08lx]", (long)(data - start));
|
||||||
|
|
||||||
op_code = *data++;
|
op_code = *data++;
|
||||||
|
|
||||||
if (op_code >= linfo.li_opcode_base)
|
if (op_code >= linfo->li_opcode_base)
|
||||||
{
|
{
|
||||||
op_code -= linfo.li_opcode_base;
|
op_code -= linfo->li_opcode_base;
|
||||||
uladv = (op_code / linfo.li_line_range);
|
uladv = (op_code / linfo->li_line_range);
|
||||||
if (linfo.li_max_ops_per_insn == 1)
|
if (linfo->li_max_ops_per_insn == 1)
|
||||||
{
|
{
|
||||||
uladv *= linfo.li_min_insn_length;
|
uladv *= linfo->li_min_insn_length;
|
||||||
state_machine_regs.address += uladv;
|
state_machine_regs.address += uladv;
|
||||||
printf (_(" Special opcode %d: "
|
printf (_(" Special opcode %d: "
|
||||||
"advance Address by %s to 0x%s"),
|
"advance Address by %s to 0x%s"),
|
||||||
@@ -2961,38 +3095,47 @@ display_debug_lines_raw (struct dwarf_section *section,
|
|||||||
{
|
{
|
||||||
state_machine_regs.address
|
state_machine_regs.address
|
||||||
+= ((state_machine_regs.op_index + uladv)
|
+= ((state_machine_regs.op_index + uladv)
|
||||||
/ linfo.li_max_ops_per_insn)
|
/ linfo->li_max_ops_per_insn)
|
||||||
* linfo.li_min_insn_length;
|
* linfo->li_min_insn_length;
|
||||||
state_machine_regs.op_index
|
state_machine_regs.op_index
|
||||||
= (state_machine_regs.op_index + uladv)
|
= (state_machine_regs.op_index + uladv)
|
||||||
% linfo.li_max_ops_per_insn;
|
% linfo->li_max_ops_per_insn;
|
||||||
printf (_(" Special opcode %d: "
|
printf (_(" Special opcode %d: "
|
||||||
"advance Address by %s to 0x%s[%d]"),
|
"advance Address by %s to 0x%s[%d]"),
|
||||||
op_code, dwarf_vmatoa ("u", uladv),
|
op_code, dwarf_vmatoa ("u", uladv),
|
||||||
dwarf_vmatoa ("x", state_machine_regs.address),
|
dwarf_vmatoa ("x", state_machine_regs.address),
|
||||||
state_machine_regs.op_index);
|
state_machine_regs.op_index);
|
||||||
}
|
}
|
||||||
adv = (op_code % linfo.li_line_range) + linfo.li_line_base;
|
adv = (op_code % linfo->li_line_range) + linfo->li_line_base;
|
||||||
state_machine_regs.line += adv;
|
state_machine_regs.line += adv;
|
||||||
printf (_(" and Line by %s to %d\n"),
|
printf (_(" and Line by %s to %d\n"),
|
||||||
dwarf_vmatoa ("d", adv), state_machine_regs.line);
|
dwarf_vmatoa ("d", adv), state_machine_regs.line);
|
||||||
|
if (is_logical)
|
||||||
|
append_logical ();
|
||||||
|
state_machine_regs.discriminator = 0;
|
||||||
}
|
}
|
||||||
else switch (op_code)
|
else
|
||||||
|
{
|
||||||
|
switch (op_code)
|
||||||
{
|
{
|
||||||
case DW_LNS_extended_op:
|
case DW_LNS_extended_op:
|
||||||
data += process_extended_line_op (data, linfo.li_default_is_stmt, end);
|
data += process_extended_line_op (data, linfo->li_default_is_stmt,
|
||||||
|
end, is_logical);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_LNS_copy:
|
case DW_LNS_copy:
|
||||||
printf (_(" Copy\n"));
|
printf (_(" Copy\n"));
|
||||||
|
if (is_logical)
|
||||||
|
append_logical ();
|
||||||
|
state_machine_regs.discriminator = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_LNS_advance_pc:
|
case DW_LNS_advance_pc:
|
||||||
uladv = read_uleb128 (data, & bytes_read, end);
|
uladv = read_uleb128 (data, & bytes_read, end);
|
||||||
data += bytes_read;
|
data += bytes_read;
|
||||||
if (linfo.li_max_ops_per_insn == 1)
|
if (linfo->li_max_ops_per_insn == 1)
|
||||||
{
|
{
|
||||||
uladv *= linfo.li_min_insn_length;
|
uladv *= linfo->li_min_insn_length;
|
||||||
state_machine_regs.address += uladv;
|
state_machine_regs.address += uladv;
|
||||||
printf (_(" Advance PC by %s to 0x%s\n"),
|
printf (_(" Advance PC by %s to 0x%s\n"),
|
||||||
dwarf_vmatoa ("u", uladv),
|
dwarf_vmatoa ("u", uladv),
|
||||||
@@ -3002,11 +3145,11 @@ display_debug_lines_raw (struct dwarf_section *section,
|
|||||||
{
|
{
|
||||||
state_machine_regs.address
|
state_machine_regs.address
|
||||||
+= ((state_machine_regs.op_index + uladv)
|
+= ((state_machine_regs.op_index + uladv)
|
||||||
/ linfo.li_max_ops_per_insn)
|
/ linfo->li_max_ops_per_insn)
|
||||||
* linfo.li_min_insn_length;
|
* linfo->li_min_insn_length;
|
||||||
state_machine_regs.op_index
|
state_machine_regs.op_index
|
||||||
= (state_machine_regs.op_index + uladv)
|
= (state_machine_regs.op_index + uladv)
|
||||||
% linfo.li_max_ops_per_insn;
|
% linfo->li_max_ops_per_insn;
|
||||||
printf (_(" Advance PC by %s to 0x%s[%d]\n"),
|
printf (_(" Advance PC by %s to 0x%s[%d]\n"),
|
||||||
dwarf_vmatoa ("u", uladv),
|
dwarf_vmatoa ("u", uladv),
|
||||||
dwarf_vmatoa ("x", state_machine_regs.address),
|
dwarf_vmatoa ("x", state_machine_regs.address),
|
||||||
@@ -3052,10 +3195,10 @@ display_debug_lines_raw (struct dwarf_section *section,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_LNS_const_add_pc:
|
case DW_LNS_const_add_pc:
|
||||||
uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range);
|
uladv = ((255 - linfo->li_opcode_base) / linfo->li_line_range);
|
||||||
if (linfo.li_max_ops_per_insn)
|
if (linfo->li_max_ops_per_insn)
|
||||||
{
|
{
|
||||||
uladv *= linfo.li_min_insn_length;
|
uladv *= linfo->li_min_insn_length;
|
||||||
state_machine_regs.address += uladv;
|
state_machine_regs.address += uladv;
|
||||||
printf (_(" Advance PC by constant %s to 0x%s\n"),
|
printf (_(" Advance PC by constant %s to 0x%s\n"),
|
||||||
dwarf_vmatoa ("u", uladv),
|
dwarf_vmatoa ("u", uladv),
|
||||||
@@ -3065,11 +3208,11 @@ display_debug_lines_raw (struct dwarf_section *section,
|
|||||||
{
|
{
|
||||||
state_machine_regs.address
|
state_machine_regs.address
|
||||||
+= ((state_machine_regs.op_index + uladv)
|
+= ((state_machine_regs.op_index + uladv)
|
||||||
/ linfo.li_max_ops_per_insn)
|
/ linfo->li_max_ops_per_insn)
|
||||||
* linfo.li_min_insn_length;
|
* linfo->li_min_insn_length;
|
||||||
state_machine_regs.op_index
|
state_machine_regs.op_index
|
||||||
= (state_machine_regs.op_index + uladv)
|
= (state_machine_regs.op_index + uladv)
|
||||||
% linfo.li_max_ops_per_insn;
|
% linfo->li_max_ops_per_insn;
|
||||||
printf (_(" Advance PC by constant %s to 0x%s[%d]\n"),
|
printf (_(" Advance PC by constant %s to 0x%s[%d]\n"),
|
||||||
dwarf_vmatoa ("u", uladv),
|
dwarf_vmatoa ("u", uladv),
|
||||||
dwarf_vmatoa ("x", state_machine_regs.address),
|
dwarf_vmatoa ("x", state_machine_regs.address),
|
||||||
@@ -3100,6 +3243,68 @@ display_debug_lines_raw (struct dwarf_section *section,
|
|||||||
printf (_(" Set ISA to %s\n"), dwarf_vmatoa ("u", uladv));
|
printf (_(" Set ISA to %s\n"), dwarf_vmatoa ("u", uladv));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DW_LNS_set_subprogram:
|
||||||
|
/* This opcode is aliased with: */
|
||||||
|
/* case DW_LNS_set_address_from_logical: */
|
||||||
|
if (is_logical)
|
||||||
|
{
|
||||||
|
/* DW_LNS_set_subprogram */
|
||||||
|
state_machine_regs.context = 0;
|
||||||
|
state_machine_regs.subprogram = read_uleb128 (data, & bytes_read, end);
|
||||||
|
data += bytes_read;
|
||||||
|
printf (_(" Set subprogram to %u and reset context to 0\n"),
|
||||||
|
state_machine_regs.subprogram);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* DW_LNS_set_address_from_logical */
|
||||||
|
adv = read_sleb128 (data, & bytes_read, end);
|
||||||
|
data += bytes_read;
|
||||||
|
state_machine_regs.line += adv;
|
||||||
|
logical = state_machine_regs.line;
|
||||||
|
if (logical - 1 < logicals_count)
|
||||||
|
{
|
||||||
|
state_machine_regs.address = logicals_table[logical - 1].address;
|
||||||
|
state_machine_regs.op_index = logicals_table[logical - 1].op_index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
warn (_("Logical row number outside range of logicals table\n"));
|
||||||
|
printf (_(" Advance Line by %s to %u and set address from logical to 0x%s[%u]\n"),
|
||||||
|
dwarf_vmatoa ("d", adv),
|
||||||
|
logical,
|
||||||
|
dwarf_vmatoa ("x", state_machine_regs.address),
|
||||||
|
state_machine_regs.op_index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_LNS_inlined_call:
|
||||||
|
adv = read_sleb128 (data, & bytes_read, end);
|
||||||
|
data += bytes_read;
|
||||||
|
state_machine_regs.context = logicals_count + adv;
|
||||||
|
state_machine_regs.subprogram = read_uleb128 (data, & bytes_read, end);
|
||||||
|
data += bytes_read;
|
||||||
|
printf (_(" Set context to %u and subprogram to %u\n"),
|
||||||
|
state_machine_regs.context,
|
||||||
|
state_machine_regs.subprogram);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_LNS_pop_context:
|
||||||
|
logical = state_machine_regs.context;
|
||||||
|
printf (_(" Pop context to logical %u\n"), logical);
|
||||||
|
if (logical - 1 < logicals_count)
|
||||||
|
{
|
||||||
|
state_machine_regs.file = logicals_table[logical - 1].file;
|
||||||
|
state_machine_regs.line = logicals_table[logical - 1].line;
|
||||||
|
state_machine_regs.column = logicals_table[logical - 1].column;
|
||||||
|
state_machine_regs.discriminator = logicals_table[logical - 1].discriminator;
|
||||||
|
state_machine_regs.is_stmt = logicals_table[logical - 1].is_stmt;
|
||||||
|
state_machine_regs.context = logicals_table[logical - 1].context;
|
||||||
|
state_machine_regs.subprogram = logicals_table[logical - 1].subprogram;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
warn (_("Context register outside range of logicals table\n"));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf (_(" Unknown opcode %d with operands: "), op_code);
|
printf (_(" Unknown opcode %d with operands: "), op_code);
|
||||||
|
|
||||||
@@ -3115,8 +3320,217 @@ display_debug_lines_raw (struct dwarf_section *section,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
putchar ('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
putchar ('\n');
|
||||||
|
*pdata = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
display_debug_lines_raw (struct dwarf_section *section,
|
||||||
|
unsigned char *data,
|
||||||
|
unsigned char *end)
|
||||||
|
{
|
||||||
|
unsigned char *start = section->start;
|
||||||
|
unsigned int initial_length_size;
|
||||||
|
unsigned int offset_size;
|
||||||
|
|
||||||
|
printf (_("Raw dump of debug contents of section %s:\n\n"),
|
||||||
|
section->name);
|
||||||
|
|
||||||
|
while (data < end)
|
||||||
|
{
|
||||||
|
static DWARF2_Internal_LineInfo saved_linfo;
|
||||||
|
DWARF2_Internal_LineInfo linfo;
|
||||||
|
unsigned int logicals_table_offset = 0;
|
||||||
|
unsigned int actuals_table_offset = 0;
|
||||||
|
unsigned char *end_of_header_length;
|
||||||
|
unsigned char *standard_opcodes;
|
||||||
|
unsigned char *start_of_line_program;
|
||||||
|
unsigned char *end_of_logicals;
|
||||||
|
unsigned char *end_of_sequence;
|
||||||
|
int i;
|
||||||
|
unsigned char *hdrptr = NULL;
|
||||||
|
|
||||||
|
if (const_strneq (section->name, ".debug_line.")
|
||||||
|
/* Note: the following does not apply to .debug_line.dwo sections.
|
||||||
|
These are full debug_line sections. */
|
||||||
|
&& strcmp (section->name, ".debug_line.dwo") != 0)
|
||||||
|
{
|
||||||
|
/* Sections named .debug_line.<foo> are fragments of a .debug_line
|
||||||
|
section containing just the Line Number Statements. They are
|
||||||
|
created by the assembler and intended to be used alongside gcc's
|
||||||
|
-ffunction-sections command line option. When the linker's
|
||||||
|
garbage collection decides to discard a .text.<foo> section it
|
||||||
|
can then also discard the line number information in .debug_line.<foo>.
|
||||||
|
|
||||||
|
Since the section is a fragment it does not have the details
|
||||||
|
needed to fill out a LineInfo structure, so instead we use the
|
||||||
|
details from the last full debug_line section that we processed. */
|
||||||
|
start_of_line_program = data;
|
||||||
|
end_of_sequence = end;
|
||||||
|
end_of_logicals = end;
|
||||||
|
standard_opcodes = NULL;
|
||||||
|
linfo = saved_linfo;
|
||||||
|
/* PR 17531: file: 0522b371. */
|
||||||
|
if (linfo.li_line_range == 0)
|
||||||
|
{
|
||||||
|
warn (_("Partial .debug_line. section encountered without a prior full .debug_line section\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
reset_state_machine (linfo.li_default_is_stmt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((hdrptr = read_debug_line_header (section, data, end, & linfo,
|
||||||
|
& end_of_sequence,
|
||||||
|
& initial_length_size,
|
||||||
|
& offset_size)) == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
printf (_(" Offset: 0x%lx\n"), (long)(data - start));
|
||||||
|
printf (_(" Length: %ld\n"), (long) linfo.li_length);
|
||||||
|
printf (_(" DWARF Version: %d\n"), linfo.li_version);
|
||||||
|
if (linfo.li_version >= 5
|
||||||
|
&& linfo.li_version != DWARF2_LINE_EXPERIMENTAL_VERSION)
|
||||||
|
{
|
||||||
|
printf (_(" Address Size: %u\n"), linfo.li_address_size);
|
||||||
|
printf (_(" Segment Size: %u\n"), linfo.li_segment_size);
|
||||||
|
}
|
||||||
|
printf (_(" Prologue Length: %d\n"), linfo.li_prologue_length);
|
||||||
|
printf (_(" Minimum Instruction Length: %d\n"), linfo.li_min_insn_length);
|
||||||
|
if (linfo.li_version >= 4)
|
||||||
|
printf (_(" Maximum Ops per Instruction: %d\n"), linfo.li_max_ops_per_insn);
|
||||||
|
printf (_(" Initial value of 'is_stmt': %d\n"), linfo.li_default_is_stmt);
|
||||||
|
printf (_(" Line Base: %d\n"), linfo.li_line_base);
|
||||||
|
printf (_(" Line Range: %d\n"), linfo.li_line_range);
|
||||||
|
printf (_(" Opcode Base: %d\n"), linfo.li_opcode_base);
|
||||||
|
|
||||||
|
end_of_header_length = data + initial_length_size + 2 + offset_size;
|
||||||
|
if (linfo.li_version >= 5
|
||||||
|
&& linfo.li_version != DWARF2_LINE_EXPERIMENTAL_VERSION)
|
||||||
|
end_of_header_length += 2;
|
||||||
|
start_of_line_program = end_of_header_length + linfo.li_prologue_length;
|
||||||
|
end_of_logicals = end;
|
||||||
|
|
||||||
|
/* PR 17512: file: 1665-6428-0.004. */
|
||||||
|
if (linfo.li_line_range == 0)
|
||||||
|
{
|
||||||
|
warn (_("Line range of 0 is invalid, using 1 instead\n"));
|
||||||
|
linfo.li_line_range = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_state_machine (linfo.li_default_is_stmt);
|
||||||
|
|
||||||
|
/* Display the contents of the Opcodes table. */
|
||||||
|
standard_opcodes = hdrptr;
|
||||||
|
|
||||||
|
/* PR 17512: file: 002-417945-0.004. */
|
||||||
|
if (standard_opcodes + linfo.li_opcode_base >= end)
|
||||||
|
{
|
||||||
|
warn (_("Line Base extends beyond end of section\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf (_("\n Opcodes:\n"));
|
||||||
|
|
||||||
|
for (i = 1; i < linfo.li_opcode_base; i++)
|
||||||
|
printf (_(" Opcode %d has %d args\n"), i, standard_opcodes[i - 1]);
|
||||||
|
|
||||||
|
data = standard_opcodes + linfo.li_opcode_base - 1;
|
||||||
|
|
||||||
|
if (linfo.li_version == DWARF2_LINE_EXPERIMENTAL_VERSION)
|
||||||
|
{
|
||||||
|
/* Skip the fake directory and filename table. */
|
||||||
|
data += 2;
|
||||||
|
|
||||||
|
/* Skip the fake extended opcode that wraps the rest
|
||||||
|
of the section. */
|
||||||
|
data += 5;
|
||||||
|
|
||||||
|
/* Read the logicals table offset and actuals table offset. */
|
||||||
|
SAFE_BYTE_GET_AND_INC (logicals_table_offset, data, offset_size, end);
|
||||||
|
SAFE_BYTE_GET_AND_INC (actuals_table_offset, data, offset_size, end);
|
||||||
|
|
||||||
|
start_of_line_program = end_of_header_length + logicals_table_offset;
|
||||||
|
|
||||||
|
if (actuals_table_offset > 0)
|
||||||
|
end_of_logicals = end_of_header_length + actuals_table_offset;
|
||||||
|
|
||||||
|
putchar ('\n');
|
||||||
|
printf (_(" Logicals Table Offset: 0x%x\n"), logicals_table_offset);
|
||||||
|
printf (_(" Actuals Table Offset: 0x%x\n"), actuals_table_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display the contents of the Directory table. */
|
||||||
|
if (linfo.li_version >= 5)
|
||||||
|
display_dir_file_table_v5 (start, end, &data, _("Directory"),
|
||||||
|
offset_size);
|
||||||
|
else
|
||||||
|
display_directory_table_v4 (start, end, &data);
|
||||||
|
|
||||||
|
/* PR 17512: file: 002-132094-0.004. */
|
||||||
|
if (data >= end - 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Display the contents of the File Name table. */
|
||||||
|
if (linfo.li_version >= 5)
|
||||||
|
{
|
||||||
|
unsigned int count;
|
||||||
|
|
||||||
|
count = display_dir_file_table_v5 (start, end, &data,
|
||||||
|
_("File Name"), offset_size);
|
||||||
|
state_machine_regs.last_file_entry = count - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
display_file_name_table_v4 (start, end, &data);
|
||||||
|
|
||||||
|
/* Display the contents of the Subprogram table. */
|
||||||
|
if (linfo.li_version == DWARF2_LINE_EXPERIMENTAL_VERSION)
|
||||||
|
display_dir_file_table_v5 (start, end, &data, _("Subprogram"),
|
||||||
|
offset_size);
|
||||||
|
|
||||||
|
putchar ('\n');
|
||||||
|
saved_linfo = linfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data > start_of_line_program)
|
||||||
|
warn (_("Line table header is longer than header_length indicates\n"));
|
||||||
|
else if (data < start_of_line_program)
|
||||||
|
warn (_("Line table header is shorter than header_length indicates\n"));
|
||||||
|
data = start_of_line_program;
|
||||||
|
|
||||||
|
if (linfo.li_version == DWARF2_LINE_EXPERIMENTAL_VERSION
|
||||||
|
&& hdrptr != NULL
|
||||||
|
&& actuals_table_offset > 0)
|
||||||
|
{
|
||||||
|
if (end_of_logicals > end)
|
||||||
|
{
|
||||||
|
warn (_("Actuals table offset %s extends beyond end of section\n"),
|
||||||
|
dwarf_vmatoa ("u", actuals_table_offset));
|
||||||
|
end_of_logicals = end;
|
||||||
|
}
|
||||||
|
display_line_program (start, end_of_logicals, &data,
|
||||||
|
_("Logicals Statements"),
|
||||||
|
&linfo, standard_opcodes, 1);
|
||||||
|
if (data > end_of_logicals)
|
||||||
|
warn (_("Logicals table is longer than actuals_table_offset indicates\n"));
|
||||||
|
else if (data < end_of_logicals)
|
||||||
|
warn (_("Line table header is shorter than actuals_table_offset indicates\n"));
|
||||||
|
data = end_of_logicals;
|
||||||
|
reset_state_machine (linfo.li_default_is_stmt);
|
||||||
|
display_line_program (start, end_of_sequence, &data,
|
||||||
|
_("Actuals Statements"),
|
||||||
|
&linfo, standard_opcodes, 0);
|
||||||
|
free_logicals ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
display_line_program (start, end_of_sequence, &data,
|
||||||
|
_("Line Number Statements"),
|
||||||
|
&linfo, standard_opcodes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -3138,6 +3552,8 @@ display_debug_lines_decoded (struct dwarf_section *section,
|
|||||||
unsigned char *end)
|
unsigned char *end)
|
||||||
{
|
{
|
||||||
static DWARF2_Internal_LineInfo saved_linfo;
|
static DWARF2_Internal_LineInfo saved_linfo;
|
||||||
|
unsigned int initial_length_size;
|
||||||
|
unsigned int offset_size;
|
||||||
|
|
||||||
printf (_("Decoded dump of debug contents of section %s:\n\n"),
|
printf (_("Decoded dump of debug contents of section %s:\n\n"),
|
||||||
section->name);
|
section->name);
|
||||||
@@ -3166,7 +3582,7 @@ display_debug_lines_decoded (struct dwarf_section *section,
|
|||||||
/* PR 17531: file: 0522b371. */
|
/* PR 17531: file: 0522b371. */
|
||||||
if (linfo.li_line_range == 0)
|
if (linfo.li_line_range == 0)
|
||||||
{
|
{
|
||||||
warn (_("Partial .debug_line. section encountered without a prior full .debug_line section"));
|
warn (_("Partial .debug_line. section encountered without a prior full .debug_line section\n"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
reset_state_machine (linfo.li_default_is_stmt);
|
reset_state_machine (linfo.li_default_is_stmt);
|
||||||
@@ -3176,7 +3592,9 @@ display_debug_lines_decoded (struct dwarf_section *section,
|
|||||||
unsigned char *hdrptr;
|
unsigned char *hdrptr;
|
||||||
|
|
||||||
if ((hdrptr = read_debug_line_header (section, data, end, & linfo,
|
if ((hdrptr = read_debug_line_header (section, data, end, & linfo,
|
||||||
& end_of_sequence)) == NULL)
|
& end_of_sequence,
|
||||||
|
& initial_length_size,
|
||||||
|
& offset_size)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* PR 17531: file: 0522b371. */
|
/* PR 17531: file: 0522b371. */
|
||||||
@@ -3600,7 +4018,7 @@ display_debug_lines_decoded (struct dwarf_section *section,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
display_debug_lines (struct dwarf_section *section, void *file ATTRIBUTE_UNUSED)
|
display_debug_lines (struct dwarf_section *section, void *file)
|
||||||
{
|
{
|
||||||
unsigned char *data = section->start;
|
unsigned char *data = section->start;
|
||||||
unsigned char *end = data + section->size;
|
unsigned char *end = data + section->size;
|
||||||
@@ -3610,6 +4028,8 @@ display_debug_lines (struct dwarf_section *section, void *file ATTRIBUTE_UNUSED)
|
|||||||
if (do_debug_lines == 0)
|
if (do_debug_lines == 0)
|
||||||
do_debug_lines |= FLAG_DEBUG_LINES_RAW;
|
do_debug_lines |= FLAG_DEBUG_LINES_RAW;
|
||||||
|
|
||||||
|
load_debug_section (line_str, file);
|
||||||
|
|
||||||
if (do_debug_lines & FLAG_DEBUG_LINES_RAW)
|
if (do_debug_lines & FLAG_DEBUG_LINES_RAW)
|
||||||
retValRaw = display_debug_lines_raw (section, data, end);
|
retValRaw = display_debug_lines_raw (section, data, end);
|
||||||
|
|
||||||
@@ -7353,6 +7773,8 @@ struct dwarf_section_display debug_displays[] =
|
|||||||
display_debug_macro, &do_debug_macinfo, 1 },
|
display_debug_macro, &do_debug_macinfo, 1 },
|
||||||
{ { ".debug_str", ".zdebug_str", NULL, NULL, 0, 0, 0, NULL },
|
{ { ".debug_str", ".zdebug_str", NULL, NULL, 0, 0, 0, NULL },
|
||||||
display_debug_str, &do_debug_str, 0 },
|
display_debug_str, &do_debug_str, 0 },
|
||||||
|
{ { ".debug_line_str", ".zdebug_line_str", NULL, NULL, 0, 0, 0, NULL },
|
||||||
|
display_debug_str, &do_debug_str, 0 },
|
||||||
{ { ".debug_loc", ".zdebug_loc", NULL, NULL, 0, 0, 0, NULL },
|
{ { ".debug_loc", ".zdebug_loc", NULL, NULL, 0, 0, 0, NULL },
|
||||||
display_debug_loc, &do_debug_loc, 1 },
|
display_debug_loc, &do_debug_loc, 1 },
|
||||||
{ { ".debug_pubtypes", ".zdebug_pubtypes", NULL, NULL, 0, 0, 0, NULL },
|
{ { ".debug_pubtypes", ".zdebug_pubtypes", NULL, NULL, 0, 0, 0, NULL },
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ typedef struct
|
|||||||
{
|
{
|
||||||
dwarf_vma li_length;
|
dwarf_vma li_length;
|
||||||
unsigned short li_version;
|
unsigned short li_version;
|
||||||
|
unsigned char li_address_size;
|
||||||
|
unsigned char li_segment_size;
|
||||||
unsigned int li_prologue_length;
|
unsigned int li_prologue_length;
|
||||||
unsigned char li_min_insn_length;
|
unsigned char li_min_insn_length;
|
||||||
unsigned char li_max_ops_per_insn;
|
unsigned char li_max_ops_per_insn;
|
||||||
@@ -123,6 +125,7 @@ enum dwarf_section_display_enum
|
|||||||
macinfo,
|
macinfo,
|
||||||
macro,
|
macro,
|
||||||
str,
|
str,
|
||||||
|
line_str,
|
||||||
loc,
|
loc,
|
||||||
pubtypes,
|
pubtypes,
|
||||||
gnu_pubtypes,
|
gnu_pubtypes,
|
||||||
|
|||||||
@@ -5503,6 +5503,7 @@ process_section_headers (FILE * file)
|
|||||||
|| (do_debug_macinfo && const_strneq (name, "macinfo"))
|
|| (do_debug_macinfo && const_strneq (name, "macinfo"))
|
||||||
|| (do_debug_macinfo && const_strneq (name, "macro"))
|
|| (do_debug_macinfo && const_strneq (name, "macro"))
|
||||||
|| (do_debug_str && const_strneq (name, "str"))
|
|| (do_debug_str && const_strneq (name, "str"))
|
||||||
|
|| (do_debug_str && const_strneq (name, "line_str"))
|
||||||
|| (do_debug_loc && const_strneq (name, "loc"))
|
|| (do_debug_loc && const_strneq (name, "loc"))
|
||||||
|| (do_debug_addr && const_strneq (name, "addr"))
|
|| (do_debug_addr && const_strneq (name, "addr"))
|
||||||
|| (do_debug_cu_index && const_strneq (name, "cu_index"))
|
|| (do_debug_cu_index && const_strneq (name, "cu_index"))
|
||||||
|
|||||||
@@ -147,7 +147,13 @@ enum DW_LINE_OPS
|
|||||||
// DWARF 3.
|
// DWARF 3.
|
||||||
DW_LNS_set_prologue_end = 10,
|
DW_LNS_set_prologue_end = 10,
|
||||||
DW_LNS_set_epilogue_begin = 11,
|
DW_LNS_set_epilogue_begin = 11,
|
||||||
DW_LNS_set_isa = 12
|
DW_LNS_set_isa = 12,
|
||||||
|
/* Experimental DWARF 5 extensions.
|
||||||
|
See http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables. */
|
||||||
|
DW_LNS_set_address_from_logical = 13, /* Actuals table only. */
|
||||||
|
DW_LNS_set_subprogram = 13, /* Logicals table only. */
|
||||||
|
DW_LNS_inlined_call = 14, /* Logicals table only. */
|
||||||
|
DW_LNS_pop_context = 15 /* Logicals table only. */
|
||||||
};
|
};
|
||||||
|
|
||||||
// Line number extended opcodes.
|
// Line number extended opcodes.
|
||||||
@@ -235,6 +241,20 @@ enum DW_SECT
|
|||||||
DW_SECT_MAX = DW_SECT_MACRO,
|
DW_SECT_MAX = DW_SECT_MACRO,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum DW_LNCT
|
||||||
|
{
|
||||||
|
DW_LNCT_path = 1,
|
||||||
|
DW_LNCT_directory_index = 2,
|
||||||
|
DW_LNCT_timestamp = 3,
|
||||||
|
DW_LNCT_size = 4,
|
||||||
|
DW_LNCT_MD5 = 5,
|
||||||
|
/* Experimental DWARF 5 extensions.
|
||||||
|
See http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables. */
|
||||||
|
DW_LNCT_subprogram_name = 6,
|
||||||
|
DW_LNCT_decl_file = 7,
|
||||||
|
DW_LNCT_decl_line = 8
|
||||||
|
};
|
||||||
|
|
||||||
} // End namespace elfcpp.
|
} // End namespace elfcpp.
|
||||||
|
|
||||||
#endif // !defined(ELFCPP_DWARF_H)
|
#endif // !defined(ELFCPP_DWARF_H)
|
||||||
|
|||||||
@@ -127,6 +127,8 @@ static const pseudo_typeS elf_pseudo_table[] =
|
|||||||
{ "file", (void (*) (int)) dwarf2_directive_file, 0 },
|
{ "file", (void (*) (int)) dwarf2_directive_file, 0 },
|
||||||
{ "loc", dwarf2_directive_loc, 0 },
|
{ "loc", dwarf2_directive_loc, 0 },
|
||||||
{ "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
|
{ "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
|
||||||
|
{ "lloc", dwarf2_directive_loc, 1 },
|
||||||
|
{ "subprog", dwarf2_directive_subprog, 0 },
|
||||||
|
|
||||||
/* We need to trap the section changing calls to handle .previous. */
|
/* We need to trap the section changing calls to handle .previous. */
|
||||||
{"data", obj_elf_data, 0},
|
{"data", obj_elf_data, 0},
|
||||||
|
|||||||
734
gas/dwarf2dbg.c
734
gas/dwarf2dbg.c
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,7 @@ struct dwarf2_line_info {
|
|||||||
unsigned int isa;
|
unsigned int isa;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int discriminator;
|
unsigned int discriminator;
|
||||||
|
unsigned int logical;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Implements the .file FILENO "FILENAME" directive. FILENO can be 0
|
/* Implements the .file FILENO "FILENAME" directive. FILENO can be 0
|
||||||
@@ -42,13 +43,29 @@ struct dwarf2_line_info {
|
|||||||
number must be >0. */
|
number must be >0. */
|
||||||
extern char *dwarf2_directive_file (int dummy);
|
extern char *dwarf2_directive_file (int dummy);
|
||||||
|
|
||||||
|
/* Experimental DWARF-5 extension:
|
||||||
|
Implements the .subprog SUBPNO ["SUBPROG" [FILENO LINENO]] directive.
|
||||||
|
FILENO is the file number, LINENO the line number and the
|
||||||
|
(optional) COLUMN the column of the source code that the following
|
||||||
|
instruction corresponds to. FILENO can be 0 to indicate that the
|
||||||
|
filename specified by the textually most recent .file directive
|
||||||
|
should be used. */
|
||||||
|
extern void dwarf2_directive_subprog (int dummy);
|
||||||
|
|
||||||
/* Implements the .loc FILENO LINENO [COLUMN] directive. FILENO is
|
/* Implements the .loc FILENO LINENO [COLUMN] directive. FILENO is
|
||||||
the file number, LINENO the line number and the (optional) COLUMN
|
the file number, LINENO the line number and the (optional) COLUMN
|
||||||
the column of the source code that the following instruction
|
the column of the source code that the following instruction
|
||||||
corresponds to. FILENO can be 0 to indicate that the filename
|
corresponds to. FILENO can be 0 to indicate that the filename
|
||||||
specified by the textually most recent .file directive should be
|
specified by the textually most recent .file directive should be
|
||||||
used. */
|
used. */
|
||||||
extern void dwarf2_directive_loc (int dummy);
|
/* Experimental DWARF-5 extension:
|
||||||
|
If IS_LLOC is true, implements the .lloc LOGICAL [FILENO LINENO [COLUMN]]
|
||||||
|
directive. FILENO is the file number, LINENO the line number and the
|
||||||
|
(optional) COLUMN the column of the source code that the following
|
||||||
|
instruction corresponds to. FILENO can be 0 to indicate that the
|
||||||
|
filename specified by the textually most recent .file directive
|
||||||
|
should be used. */
|
||||||
|
extern void dwarf2_directive_loc (int is_lloc);
|
||||||
|
|
||||||
/* Implements the .loc_mark_labels {0,1} directive. */
|
/* Implements the .loc_mark_labels {0,1} directive. */
|
||||||
extern void dwarf2_directive_loc_mark_labels (int dummy);
|
extern void dwarf2_directive_loc_mark_labels (int dummy);
|
||||||
|
|||||||
@@ -38,9 +38,11 @@ const int DEBUG_SCRIPT = 0x2;
|
|||||||
const int DEBUG_FILES = 0x4;
|
const int DEBUG_FILES = 0x4;
|
||||||
const int DEBUG_RELAXATION = 0x8;
|
const int DEBUG_RELAXATION = 0x8;
|
||||||
const int DEBUG_INCREMENTAL = 0x10;
|
const int DEBUG_INCREMENTAL = 0x10;
|
||||||
|
const int DEBUG_LOCATION = 0x20;
|
||||||
|
|
||||||
const int DEBUG_ALL = (DEBUG_TASK | DEBUG_SCRIPT | DEBUG_FILES
|
const int DEBUG_ALL = (DEBUG_TASK | DEBUG_SCRIPT | DEBUG_FILES
|
||||||
| DEBUG_RELAXATION | DEBUG_INCREMENTAL);
|
| DEBUG_RELAXATION | DEBUG_INCREMENTAL
|
||||||
|
| DEBUG_LOCATION);
|
||||||
|
|
||||||
// Convert a debug string to the appropriate enum.
|
// Convert a debug string to the appropriate enum.
|
||||||
inline int
|
inline int
|
||||||
@@ -54,6 +56,7 @@ debug_string_to_enum(const char* arg)
|
|||||||
{ "files", DEBUG_FILES },
|
{ "files", DEBUG_FILES },
|
||||||
{ "relaxation", DEBUG_RELAXATION },
|
{ "relaxation", DEBUG_RELAXATION },
|
||||||
{ "incremental", DEBUG_INCREMENTAL },
|
{ "incremental", DEBUG_INCREMENTAL },
|
||||||
|
{ "location", DEBUG_LOCATION },
|
||||||
{ "all", DEBUG_ALL }
|
{ "all", DEBUG_ALL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
#include "elfcpp_swap.h"
|
#include "elfcpp_swap.h"
|
||||||
#include "dwarf.h"
|
#include "dwarf.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
@@ -1526,6 +1527,7 @@ struct LineStateMachine
|
|||||||
bool is_stmt; // stmt means statement.
|
bool is_stmt; // stmt means statement.
|
||||||
bool basic_block;
|
bool basic_block;
|
||||||
bool end_sequence;
|
bool end_sequence;
|
||||||
|
unsigned int context;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1539,6 +1541,7 @@ ResetLineStateMachine(struct LineStateMachine* lsm, bool default_is_stmt)
|
|||||||
lsm->is_stmt = default_is_stmt;
|
lsm->is_stmt = default_is_stmt;
|
||||||
lsm->basic_block = false;
|
lsm->basic_block = false;
|
||||||
lsm->end_sequence = false;
|
lsm->end_sequence = false;
|
||||||
|
lsm->context = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
@@ -1546,27 +1549,40 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(
|
|||||||
Object* object,
|
Object* object,
|
||||||
unsigned int read_shndx)
|
unsigned int read_shndx)
|
||||||
: data_valid_(false), buffer_(NULL), buffer_start_(NULL),
|
: data_valid_(false), buffer_(NULL), buffer_start_(NULL),
|
||||||
|
str_buffer_(NULL), str_buffer_start_(NULL),
|
||||||
reloc_mapper_(NULL), symtab_buffer_(NULL), directories_(), files_(),
|
reloc_mapper_(NULL), symtab_buffer_(NULL), directories_(), files_(),
|
||||||
current_header_index_(-1)
|
current_header_index_(-1), reloc_map_(), line_number_map_()
|
||||||
{
|
{
|
||||||
unsigned int debug_shndx;
|
unsigned int debug_line_shndx = 0;
|
||||||
|
unsigned int debug_line_str_shndx = 0;
|
||||||
|
|
||||||
for (debug_shndx = 1; debug_shndx < object->shnum(); ++debug_shndx)
|
for (unsigned int i = 1; i < object->shnum(); ++i)
|
||||||
{
|
|
||||||
// FIXME: do this more efficiently: section_name() isn't super-fast
|
|
||||||
std::string name = object->section_name(debug_shndx);
|
|
||||||
if (name == ".debug_line" || name == ".zdebug_line")
|
|
||||||
{
|
{
|
||||||
section_size_type buffer_size;
|
section_size_type buffer_size;
|
||||||
bool is_new = false;
|
bool is_new = false;
|
||||||
this->buffer_ = object->decompressed_section_contents(debug_shndx,
|
|
||||||
&buffer_size,
|
// FIXME: do this more efficiently: section_name() isn't super-fast
|
||||||
&is_new);
|
std::string name = object->section_name(i);
|
||||||
|
if (name == ".debug_line" || name == ".zdebug_line")
|
||||||
|
{
|
||||||
|
this->buffer_ =
|
||||||
|
object->decompressed_section_contents(i, &buffer_size, &is_new);
|
||||||
if (is_new)
|
if (is_new)
|
||||||
this->buffer_start_ = this->buffer_;
|
this->buffer_start_ = this->buffer_;
|
||||||
this->buffer_end_ = this->buffer_ + buffer_size;
|
this->buffer_end_ = this->buffer_ + buffer_size;
|
||||||
break;
|
debug_line_shndx = i;
|
||||||
}
|
}
|
||||||
|
else if (name == ".debug_line_str" || name == ".zdebug_line_str")
|
||||||
|
{
|
||||||
|
this->str_buffer_ =
|
||||||
|
object->decompressed_section_contents(i, &buffer_size, &is_new);
|
||||||
|
if (is_new)
|
||||||
|
this->str_buffer_start_ = this->str_buffer_;
|
||||||
|
this->str_buffer_end_ = this->str_buffer_ + buffer_size;
|
||||||
|
debug_line_str_shndx = i;
|
||||||
|
}
|
||||||
|
if (debug_line_shndx > 0 && debug_line_str_shndx > 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (this->buffer_ == NULL)
|
if (this->buffer_ == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -1579,7 +1595,7 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(
|
|||||||
unsigned int reloc_sh_type = object->section_type(i);
|
unsigned int reloc_sh_type = object->section_type(i);
|
||||||
if ((reloc_sh_type == elfcpp::SHT_REL
|
if ((reloc_sh_type == elfcpp::SHT_REL
|
||||||
|| reloc_sh_type == elfcpp::SHT_RELA)
|
|| reloc_sh_type == elfcpp::SHT_RELA)
|
||||||
&& object->section_info(i) == debug_shndx)
|
&& object->section_info(i) == debug_line_shndx)
|
||||||
{
|
{
|
||||||
reloc_shndx = i;
|
reloc_shndx = i;
|
||||||
this->track_relocs_type_ = reloc_sh_type;
|
this->track_relocs_type_ = reloc_sh_type;
|
||||||
@@ -1612,6 +1628,8 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(
|
|||||||
// Now that we have successfully read all the data, parse the debug
|
// Now that we have successfully read all the data, parse the debug
|
||||||
// info.
|
// info.
|
||||||
this->data_valid_ = true;
|
this->data_valid_ = true;
|
||||||
|
gold_debug(DEBUG_LOCATION, "read_line_mappings: %s shndx %u",
|
||||||
|
object->name().c_str(), read_shndx);
|
||||||
this->read_line_mappings(read_shndx);
|
this->read_line_mappings(read_shndx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1638,20 +1656,39 @@ Sized_dwarf_line_info<size, big_endian>::read_header_prolog(
|
|||||||
|
|
||||||
header_.total_length = initial_length;
|
header_.total_length = initial_length;
|
||||||
|
|
||||||
gold_assert(lineptr + header_.total_length <= buffer_end_);
|
this->end_of_unit_ = lineptr + initial_length;
|
||||||
|
gold_assert(this->end_of_unit_ <= buffer_end_);
|
||||||
|
|
||||||
header_.version = elfcpp::Swap_unaligned<16, big_endian>::readval(lineptr);
|
header_.version = elfcpp::Swap_unaligned<16, big_endian>::readval(lineptr);
|
||||||
lineptr += 2;
|
lineptr += 2;
|
||||||
|
|
||||||
|
// We can only read versions 2 and 3 of the DWARF line number table.
|
||||||
|
// For other versions, just skip the entire line number table.
|
||||||
|
if ((header_.version < 2 || header_.version > 4)
|
||||||
|
&& header_.version != DWARF5_EXPERIMENTAL_LINE_TABLE)
|
||||||
|
return this->end_of_unit_;
|
||||||
|
|
||||||
if (header_.offset_size == 4)
|
if (header_.offset_size == 4)
|
||||||
header_.prologue_length = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
|
header_.prologue_length = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
|
||||||
else
|
else
|
||||||
header_.prologue_length = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
|
header_.prologue_length = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
|
||||||
lineptr += header_.offset_size;
|
lineptr += header_.offset_size;
|
||||||
|
|
||||||
|
this->end_of_header_length_ = lineptr;
|
||||||
|
|
||||||
|
// If this is a two-level line table, we'll adjust these below.
|
||||||
|
this->logicals_start_ = lineptr + header_.prologue_length;
|
||||||
|
this->actuals_start_ = NULL;
|
||||||
|
|
||||||
header_.min_insn_length = *lineptr;
|
header_.min_insn_length = *lineptr;
|
||||||
lineptr += 1;
|
lineptr += 1;
|
||||||
|
|
||||||
|
if (header_.version >= 4)
|
||||||
|
{
|
||||||
|
header_.max_ops_per_insn = *lineptr;
|
||||||
|
lineptr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
header_.default_is_stmt = *lineptr;
|
header_.default_is_stmt = *lineptr;
|
||||||
lineptr += 1;
|
lineptr += 1;
|
||||||
|
|
||||||
@@ -1672,6 +1709,32 @@ Sized_dwarf_line_info<size, big_endian>::read_header_prolog(
|
|||||||
lineptr += 1;
|
lineptr += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (header_.version == DWARF5_EXPERIMENTAL_LINE_TABLE)
|
||||||
|
{
|
||||||
|
// Skip over fake empty directory and filename tables,
|
||||||
|
// and fake extended opcode that hides the rest of the
|
||||||
|
// section from old consumers.
|
||||||
|
lineptr += 7;
|
||||||
|
|
||||||
|
// Offsets to logicals and actuals tables.
|
||||||
|
off_t logicals_offset;
|
||||||
|
off_t actuals_offset;
|
||||||
|
if (header_.offset_size == 4)
|
||||||
|
logicals_offset = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
|
||||||
|
else
|
||||||
|
logicals_offset = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
|
||||||
|
lineptr += header_.offset_size;
|
||||||
|
if (header_.offset_size == 4)
|
||||||
|
actuals_offset = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
|
||||||
|
else
|
||||||
|
actuals_offset = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
|
||||||
|
lineptr += header_.offset_size;
|
||||||
|
|
||||||
|
this->logicals_start_ = this->end_of_header_length_ + logicals_offset;
|
||||||
|
if (actuals_offset > 0)
|
||||||
|
this->actuals_start_ = this->end_of_header_length_ + actuals_offset;
|
||||||
|
}
|
||||||
|
|
||||||
return lineptr;
|
return lineptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1745,12 +1808,180 @@ Sized_dwarf_line_info<size, big_endian>::read_header_tables(
|
|||||||
return lineptr;
|
return lineptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
const unsigned char*
|
||||||
|
Sized_dwarf_line_info<size, big_endian>::read_header_tables_v5(
|
||||||
|
const unsigned char* lineptr)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
++this->current_header_index_;
|
||||||
|
|
||||||
|
// Create a new directories_ entry and a new files_ entry for our new
|
||||||
|
// header. We initialize each with a single empty element, because
|
||||||
|
// dwarf indexes directory and filenames starting at 1.
|
||||||
|
gold_assert(static_cast<int>(this->directories_.size())
|
||||||
|
== this->current_header_index_);
|
||||||
|
gold_assert(static_cast<int>(this->files_.size())
|
||||||
|
== this->current_header_index_);
|
||||||
|
|
||||||
|
// Read the directory list.
|
||||||
|
uint64_t format_count = read_unsigned_LEB_128(lineptr, &len);
|
||||||
|
lineptr += len;
|
||||||
|
|
||||||
|
unsigned int *types = new unsigned int[format_count];
|
||||||
|
unsigned int *forms = new unsigned int[format_count];
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < format_count; i++)
|
||||||
|
{
|
||||||
|
types[i] = read_unsigned_LEB_128(lineptr, &len);
|
||||||
|
lineptr += len;
|
||||||
|
forms[i] = read_unsigned_LEB_128(lineptr, &len);
|
||||||
|
lineptr += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t entry_count = read_unsigned_LEB_128(lineptr, &len);
|
||||||
|
lineptr += len;
|
||||||
|
this->directories_.push_back(std::vector<std::string>(1));
|
||||||
|
std::vector<std::string>& dir_list = this->directories_.back();
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < entry_count; j++)
|
||||||
|
{
|
||||||
|
std::string dirname;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < format_count; i++)
|
||||||
|
{
|
||||||
|
if (types[i] == elfcpp::DW_LNCT_path)
|
||||||
|
{
|
||||||
|
if (forms[i] == elfcpp::DW_FORM_string)
|
||||||
|
{
|
||||||
|
dirname = reinterpret_cast<const char*>(lineptr);
|
||||||
|
lineptr += dirname.size() + 1;
|
||||||
|
}
|
||||||
|
else if (forms[i] == elfcpp::DW_FORM_line_strp)
|
||||||
|
{
|
||||||
|
uint64_t offset;
|
||||||
|
if (header_.offset_size == 4)
|
||||||
|
offset = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
|
||||||
|
else
|
||||||
|
offset = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
|
||||||
|
typename Reloc_map::const_iterator it
|
||||||
|
= this->reloc_map_.find(lineptr - this->buffer_);
|
||||||
|
if (it != reloc_map_.end())
|
||||||
|
{
|
||||||
|
if (this->track_relocs_type_ == elfcpp::SHT_RELA)
|
||||||
|
offset = 0;
|
||||||
|
offset += it->second.second;
|
||||||
|
}
|
||||||
|
lineptr += header_.offset_size;
|
||||||
|
dirname = reinterpret_cast<const char*>(this->str_buffer_
|
||||||
|
+ offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return lineptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return lineptr;
|
||||||
|
}
|
||||||
|
dir_list.push_back(dirname);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] types;
|
||||||
|
delete[] forms;
|
||||||
|
|
||||||
|
// Read the filenames list.
|
||||||
|
format_count = read_unsigned_LEB_128(lineptr, &len);
|
||||||
|
lineptr += len;
|
||||||
|
|
||||||
|
types = new unsigned int[format_count];
|
||||||
|
forms = new unsigned int[format_count];
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < format_count; i++)
|
||||||
|
{
|
||||||
|
types[i] = read_unsigned_LEB_128(lineptr, &len);
|
||||||
|
lineptr += len;
|
||||||
|
forms[i] = read_unsigned_LEB_128(lineptr, &len);
|
||||||
|
lineptr += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_count = read_unsigned_LEB_128(lineptr, &len);
|
||||||
|
lineptr += len;
|
||||||
|
this->files_.push_back(
|
||||||
|
std::vector<std::pair<int, std::string> >(1));
|
||||||
|
std::vector<std::pair<int, std::string> >& file_list = this->files_.back();
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < entry_count; j++)
|
||||||
|
{
|
||||||
|
const char* path = NULL;
|
||||||
|
int dirindex = 0;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < format_count; i++)
|
||||||
|
{
|
||||||
|
if (types[i] == elfcpp::DW_LNCT_path)
|
||||||
|
{
|
||||||
|
if (forms[i] == elfcpp::DW_FORM_string)
|
||||||
|
{
|
||||||
|
path = reinterpret_cast<const char*>(lineptr);
|
||||||
|
lineptr += strlen(path) + 1;
|
||||||
|
}
|
||||||
|
else if (forms[i] == elfcpp::DW_FORM_line_strp)
|
||||||
|
{
|
||||||
|
uint64_t offset;
|
||||||
|
if (header_.offset_size == 4)
|
||||||
|
offset = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
|
||||||
|
else
|
||||||
|
offset = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
|
||||||
|
typename Reloc_map::const_iterator it
|
||||||
|
= this->reloc_map_.find(lineptr - this->buffer_);
|
||||||
|
if (it != reloc_map_.end())
|
||||||
|
{
|
||||||
|
if (this->track_relocs_type_ == elfcpp::SHT_RELA)
|
||||||
|
offset = 0;
|
||||||
|
offset += it->second.second;
|
||||||
|
}
|
||||||
|
lineptr += header_.offset_size;
|
||||||
|
path = reinterpret_cast<const char*>(this->str_buffer_
|
||||||
|
+ offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return lineptr;
|
||||||
|
}
|
||||||
|
else if (types[i] == elfcpp::DW_LNCT_directory_index)
|
||||||
|
{
|
||||||
|
if (forms[i] == elfcpp::DW_FORM_udata)
|
||||||
|
{
|
||||||
|
dirindex = read_unsigned_LEB_128(lineptr, &len);
|
||||||
|
lineptr += len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return lineptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return lineptr;
|
||||||
|
}
|
||||||
|
gold_debug(DEBUG_LOCATION, "File %3d: %s",
|
||||||
|
static_cast<int>(file_list.size()), path);
|
||||||
|
file_list.push_back(std::make_pair<int, std::string>(dirindex, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] types;
|
||||||
|
delete[] forms;
|
||||||
|
|
||||||
|
// Ignore the subprograms table; we don't need it for now.
|
||||||
|
// Because it's the last thing in the header, we don't need
|
||||||
|
// to figure out how long it is to skip over it.
|
||||||
|
|
||||||
|
return lineptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Process a single opcode in the .debug.line structure.
|
// Process a single opcode in the .debug.line structure.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
bool
|
bool
|
||||||
Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
|
Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
|
||||||
const unsigned char* start, struct LineStateMachine* lsm, size_t* len)
|
const unsigned char* start, struct LineStateMachine* lsm, size_t* len,
|
||||||
|
std::vector<LineStateMachine>* logicals,
|
||||||
|
bool is_logicals_table, bool is_actuals_table)
|
||||||
{
|
{
|
||||||
size_t oplen = 0;
|
size_t oplen = 0;
|
||||||
size_t templen;
|
size_t templen;
|
||||||
@@ -1794,7 +2025,7 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
|
|||||||
|
|
||||||
case elfcpp::DW_LNS_advance_line:
|
case elfcpp::DW_LNS_advance_line:
|
||||||
{
|
{
|
||||||
const uint64_t advance_line = read_signed_LEB_128(start, &templen);
|
const int64_t advance_line = read_signed_LEB_128(start, &templen);
|
||||||
oplen += templen;
|
oplen += templen;
|
||||||
lsm->line_num += advance_line;
|
lsm->line_num += advance_line;
|
||||||
}
|
}
|
||||||
@@ -1842,6 +2073,61 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case elfcpp::DW_LNS_set_subprogram:
|
||||||
|
// aliased with elfcpp::DW_LNS_set_address_from_logical
|
||||||
|
if (is_actuals_table)
|
||||||
|
{
|
||||||
|
// elfcpp::DW_LNS_set_address_from_logical
|
||||||
|
const int64_t advance_line = read_signed_LEB_128(start, &templen);
|
||||||
|
oplen += templen;
|
||||||
|
lsm->line_num += advance_line;
|
||||||
|
if (lsm->line_num >= 1
|
||||||
|
&& lsm->line_num <= static_cast<int64_t>(logicals->size()))
|
||||||
|
{
|
||||||
|
const LineStateMachine& logical = (*logicals)[lsm->line_num - 1];
|
||||||
|
lsm->address = logical.address;
|
||||||
|
lsm->shndx = logical.shndx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_logicals_table)
|
||||||
|
{
|
||||||
|
// elfcpp::DW_LNS_set_subprogram
|
||||||
|
// Ignore the subprogram number for now.
|
||||||
|
read_unsigned_LEB_128(start, &templen);
|
||||||
|
oplen += templen;
|
||||||
|
lsm->context = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case elfcpp::DW_LNS_inlined_call:
|
||||||
|
if (is_logicals_table)
|
||||||
|
{
|
||||||
|
const int64_t advance_line = read_signed_LEB_128(start, &templen);
|
||||||
|
oplen += templen;
|
||||||
|
start += templen;
|
||||||
|
// Ignore the subprogram number for now.
|
||||||
|
read_unsigned_LEB_128(start, &templen);
|
||||||
|
oplen += templen;
|
||||||
|
lsm->context = logicals->size() + advance_line;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case elfcpp::DW_LNS_pop_context:
|
||||||
|
if (is_logicals_table)
|
||||||
|
{
|
||||||
|
const unsigned int context = lsm->context;
|
||||||
|
if (context >= 1 && context <= logicals->size())
|
||||||
|
{
|
||||||
|
const LineStateMachine& logical = (*logicals)[context - 1];
|
||||||
|
lsm->file_num = logical.file_num;
|
||||||
|
lsm->line_num = logical.line_num;
|
||||||
|
lsm->column_num = logical.column_num;
|
||||||
|
lsm->is_stmt = logical.is_stmt;
|
||||||
|
lsm->context = logical.context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case elfcpp::DW_LNS_extended_op:
|
case elfcpp::DW_LNS_extended_op:
|
||||||
{
|
{
|
||||||
const uint64_t extended_op_len
|
const uint64_t extended_op_len
|
||||||
@@ -1939,37 +2225,74 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
|
|||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
unsigned const char*
|
unsigned const char*
|
||||||
Sized_dwarf_line_info<size, big_endian>::read_lines(unsigned const char* lineptr,
|
Sized_dwarf_line_info<size, big_endian>::read_lines(
|
||||||
|
unsigned const char* lineptr,
|
||||||
|
unsigned const char* endptr,
|
||||||
|
std::vector<LineStateMachine>* logicals,
|
||||||
|
bool is_logicals_table,
|
||||||
|
bool is_actuals_table,
|
||||||
unsigned int shndx)
|
unsigned int shndx)
|
||||||
{
|
{
|
||||||
struct LineStateMachine lsm;
|
struct LineStateMachine lsm;
|
||||||
|
|
||||||
// LENGTHSTART is the place the length field is based on. It is the
|
while (lineptr < endptr)
|
||||||
// point in the header after the initial length field.
|
|
||||||
const unsigned char* lengthstart = buffer_;
|
|
||||||
|
|
||||||
// In 64 bit dwarf, the initial length is 12 bytes, because of the
|
|
||||||
// 0xffffffff at the start.
|
|
||||||
if (header_.offset_size == 8)
|
|
||||||
lengthstart += 12;
|
|
||||||
else
|
|
||||||
lengthstart += 4;
|
|
||||||
|
|
||||||
while (lineptr < lengthstart + header_.total_length)
|
|
||||||
{
|
{
|
||||||
ResetLineStateMachine(&lsm, header_.default_is_stmt);
|
ResetLineStateMachine(&lsm, header_.default_is_stmt);
|
||||||
while (!lsm.end_sequence)
|
while (!lsm.end_sequence)
|
||||||
{
|
{
|
||||||
size_t oplength;
|
size_t oplength;
|
||||||
bool add_line = this->process_one_opcode(lineptr, &lsm, &oplength);
|
if (lineptr >= endptr)
|
||||||
if (add_line
|
break;
|
||||||
&& (shndx == -1U || lsm.shndx == -1U || shndx == lsm.shndx))
|
|
||||||
|
bool add_line = this->process_one_opcode(lineptr, &lsm, &oplength,
|
||||||
|
logicals,
|
||||||
|
is_logicals_table,
|
||||||
|
is_actuals_table);
|
||||||
|
lineptr += oplength;
|
||||||
|
|
||||||
|
if (add_line)
|
||||||
{
|
{
|
||||||
Offset_to_lineno_entry entry
|
if (is_logicals_table)
|
||||||
= { static_cast<off_t>(lsm.address),
|
{
|
||||||
this->current_header_index_,
|
logicals->push_back(lsm);
|
||||||
static_cast<unsigned int>(lsm.file_num),
|
gold_debug(DEBUG_LOCATION, "Logical %d [%3u:%08x]: "
|
||||||
true, lsm.line_num };
|
"file %d line %d context %u",
|
||||||
|
static_cast<int>(logicals->size()),
|
||||||
|
lsm.shndx, static_cast<int>(lsm.address),
|
||||||
|
lsm.file_num, lsm.line_num, lsm.context);
|
||||||
|
}
|
||||||
|
else if (shndx == -1U || lsm.shndx == -1U || shndx == lsm.shndx)
|
||||||
|
{
|
||||||
|
Offset_to_lineno_entry entry;
|
||||||
|
|
||||||
|
if (is_actuals_table && lsm.line_num != -1)
|
||||||
|
{
|
||||||
|
if (lsm.line_num < 1
|
||||||
|
|| lsm.line_num > static_cast<int64_t>(logicals->size()))
|
||||||
|
continue;
|
||||||
|
const LineStateMachine& logical =
|
||||||
|
(*logicals)[lsm.line_num - 1];
|
||||||
|
gold_debug(DEBUG_LOCATION, "Actual [%3u:%08x]: "
|
||||||
|
"logical %u file %d line %d context %u",
|
||||||
|
lsm.shndx, static_cast<int>(lsm.address),
|
||||||
|
lsm.line_num, logical.file_num,
|
||||||
|
logical.line_num, logical.context);
|
||||||
|
entry.offset = static_cast<off_t>(lsm.address);
|
||||||
|
entry.header_num = this->current_header_index_;
|
||||||
|
entry.file_num =
|
||||||
|
static_cast<unsigned int>(logical.file_num);
|
||||||
|
entry.last_line_for_offset = true;
|
||||||
|
entry.line_num = logical.line_num;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry.offset = static_cast<off_t>(lsm.address);
|
||||||
|
entry.header_num = this->current_header_index_;
|
||||||
|
entry.file_num = static_cast<unsigned int>(lsm.file_num);
|
||||||
|
entry.last_line_for_offset = true;
|
||||||
|
entry.line_num = lsm.line_num;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Offset_to_lineno_entry>&
|
std::vector<Offset_to_lineno_entry>&
|
||||||
map(this->line_number_map_[lsm.shndx]);
|
map(this->line_number_map_[lsm.shndx]);
|
||||||
// If we see two consecutive entries with the same
|
// If we see two consecutive entries with the same
|
||||||
@@ -1982,11 +2305,12 @@ Sized_dwarf_line_info<size, big_endian>::read_lines(unsigned const char* lineptr
|
|||||||
map.back().last_line_for_offset = false;
|
map.back().last_line_for_offset = false;
|
||||||
map.push_back(entry);
|
map.push_back(entry);
|
||||||
}
|
}
|
||||||
lineptr += oplength;
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lengthstart + header_.total_length;
|
return endptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the relocations into a Reloc_map.
|
// Read the relocations into a Reloc_map.
|
||||||
@@ -2026,10 +2350,48 @@ Sized_dwarf_line_info<size, big_endian>::read_line_mappings(unsigned int shndx)
|
|||||||
while (this->buffer_ < this->buffer_end_)
|
while (this->buffer_ < this->buffer_end_)
|
||||||
{
|
{
|
||||||
const unsigned char* lineptr = this->buffer_;
|
const unsigned char* lineptr = this->buffer_;
|
||||||
|
std::vector<LineStateMachine> logicals;
|
||||||
|
|
||||||
lineptr = this->read_header_prolog(lineptr);
|
lineptr = this->read_header_prolog(lineptr);
|
||||||
|
if (header_.version >= 2 && header_.version <= 4)
|
||||||
|
{
|
||||||
lineptr = this->read_header_tables(lineptr);
|
lineptr = this->read_header_tables(lineptr);
|
||||||
lineptr = this->read_lines(lineptr, shndx);
|
lineptr = this->read_lines(this->logicals_start_,
|
||||||
this->buffer_ = lineptr;
|
this->end_of_unit_,
|
||||||
|
NULL,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
shndx);
|
||||||
|
}
|
||||||
|
else if (header_.version == DWARF5_EXPERIMENTAL_LINE_TABLE)
|
||||||
|
{
|
||||||
|
lineptr = this->read_header_tables_v5(lineptr);
|
||||||
|
if (this->actuals_start_ != NULL)
|
||||||
|
{
|
||||||
|
lineptr = this->read_lines(this->logicals_start_,
|
||||||
|
this->actuals_start_,
|
||||||
|
&logicals,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
shndx);
|
||||||
|
lineptr = this->read_lines(this->actuals_start_,
|
||||||
|
this->end_of_unit_,
|
||||||
|
&logicals,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
shndx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lineptr = this->read_lines(this->logicals_start_,
|
||||||
|
this->end_of_unit_,
|
||||||
|
NULL,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
shndx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->buffer_ = this->end_of_unit_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the lines numbers, so addr2line can use binary search.
|
// Sort the lines numbers, so addr2line can use binary search.
|
||||||
@@ -2185,6 +2547,9 @@ Sized_dwarf_line_info<size, big_endian>::do_addr2line(
|
|||||||
off_t offset,
|
off_t offset,
|
||||||
std::vector<std::string>* other_lines)
|
std::vector<std::string>* other_lines)
|
||||||
{
|
{
|
||||||
|
gold_debug(DEBUG_LOCATION, "do_addr2line: shndx %u offset %08x",
|
||||||
|
shndx, static_cast<int>(offset));
|
||||||
|
|
||||||
if (this->data_valid_ == false)
|
if (this->data_valid_ == false)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
@@ -2205,13 +2570,33 @@ Sized_dwarf_line_info<size, big_endian>::do_addr2line(
|
|||||||
return "";
|
return "";
|
||||||
|
|
||||||
std::string result = this->format_file_lineno(*it);
|
std::string result = this->format_file_lineno(*it);
|
||||||
|
gold_debug(DEBUG_LOCATION, "do_addr2line: canonical result: %s",
|
||||||
|
result.c_str());
|
||||||
if (other_lines != NULL)
|
if (other_lines != NULL)
|
||||||
for (++it; it != offsets->end() && it->offset == offset; ++it)
|
|
||||||
{
|
{
|
||||||
if (it->line_num == -1)
|
unsigned int last_file_num = it->file_num;
|
||||||
|
int last_line_num = it->line_num;
|
||||||
|
// Return up to 4 more locations from the beginning of the function
|
||||||
|
// for fuzzy matching.
|
||||||
|
for (++it; it != offsets->end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->offset == offset && it->line_num == -1)
|
||||||
continue; // The end of a previous function.
|
continue; // The end of a previous function.
|
||||||
|
if (it->line_num == -1)
|
||||||
|
break; // The end of the current function.
|
||||||
|
if (it->file_num != last_file_num || it->line_num != last_line_num)
|
||||||
|
{
|
||||||
other_lines->push_back(this->format_file_lineno(*it));
|
other_lines->push_back(this->format_file_lineno(*it));
|
||||||
|
gold_debug(DEBUG_LOCATION, "do_addr2line: other: %s",
|
||||||
|
other_lines->back().c_str());
|
||||||
|
last_file_num = it->file_num;
|
||||||
|
last_line_num = it->line_num;
|
||||||
}
|
}
|
||||||
|
if (it->offset > offset && other_lines->size() >= 4)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1001,9 +1001,13 @@ class Sized_dwarf_line_info : public Dwarf_line_info
|
|||||||
{
|
{
|
||||||
if (this->buffer_start_ != NULL)
|
if (this->buffer_start_ != NULL)
|
||||||
delete[] this->buffer_start_;
|
delete[] this->buffer_start_;
|
||||||
|
if (this->str_buffer_start_ != NULL)
|
||||||
|
delete[] this->str_buffer_start_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const static int DWARF5_EXPERIMENTAL_LINE_TABLE = 0xf006;
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
do_addr2line(unsigned int shndx, off_t offset,
|
do_addr2line(unsigned int shndx, off_t offset,
|
||||||
std::vector<std::string>* other_lines);
|
std::vector<std::string>* other_lines);
|
||||||
@@ -1031,11 +1035,17 @@ class Sized_dwarf_line_info : public Dwarf_line_info
|
|||||||
const unsigned char*
|
const unsigned char*
|
||||||
read_header_tables(const unsigned char* lineptr);
|
read_header_tables(const unsigned char* lineptr);
|
||||||
|
|
||||||
|
const unsigned char*
|
||||||
|
read_header_tables_v5(const unsigned char* lineptr);
|
||||||
|
|
||||||
// Reads the DWARF2/3 line information. If shndx is non-negative,
|
// Reads the DWARF2/3 line information. If shndx is non-negative,
|
||||||
// discard all line information that doesn't pertain to the given
|
// discard all line information that doesn't pertain to the given
|
||||||
// section.
|
// section.
|
||||||
const unsigned char*
|
const unsigned char*
|
||||||
read_lines(const unsigned char* lineptr, unsigned int shndx);
|
read_lines(const unsigned char* lineptr, const unsigned char* endptr,
|
||||||
|
std::vector<LineStateMachine>* logicals,
|
||||||
|
bool is_logicals_table, bool is_actuals_table,
|
||||||
|
unsigned int shndx);
|
||||||
|
|
||||||
// Process a single line info opcode at START using the state
|
// Process a single line info opcode at START using the state
|
||||||
// machine at LSM. Return true if we should define a line using the
|
// machine at LSM. Return true if we should define a line using the
|
||||||
@@ -1043,7 +1053,9 @@ class Sized_dwarf_line_info : public Dwarf_line_info
|
|||||||
// opcode in LEN.
|
// opcode in LEN.
|
||||||
bool
|
bool
|
||||||
process_one_opcode(const unsigned char* start,
|
process_one_opcode(const unsigned char* start,
|
||||||
struct LineStateMachine* lsm, size_t* len);
|
struct LineStateMachine* lsm, size_t* len,
|
||||||
|
std::vector<LineStateMachine>* logicals,
|
||||||
|
bool is_logicals_table, bool is_actuals_table);
|
||||||
|
|
||||||
// Some parts of processing differ depending on whether the input
|
// Some parts of processing differ depending on whether the input
|
||||||
// was a .o file or not.
|
// was a .o file or not.
|
||||||
@@ -1064,6 +1076,7 @@ class Sized_dwarf_line_info : public Dwarf_line_info
|
|||||||
int version;
|
int version;
|
||||||
off_t prologue_length;
|
off_t prologue_length;
|
||||||
int min_insn_length; // insn stands for instructin
|
int min_insn_length; // insn stands for instructin
|
||||||
|
int max_ops_per_insn;
|
||||||
bool default_is_stmt; // stmt stands for statement
|
bool default_is_stmt; // stmt stands for statement
|
||||||
signed char line_base;
|
signed char line_base;
|
||||||
int line_range;
|
int line_range;
|
||||||
@@ -1081,6 +1094,26 @@ class Sized_dwarf_line_info : public Dwarf_line_info
|
|||||||
// of the buffer.
|
// of the buffer.
|
||||||
const unsigned char* buffer_start_;
|
const unsigned char* buffer_start_;
|
||||||
|
|
||||||
|
// buffer is the buffer for our line info, starting at exactly where
|
||||||
|
// the line info to read is.
|
||||||
|
const unsigned char* str_buffer_;
|
||||||
|
const unsigned char* str_buffer_end_;
|
||||||
|
// If the buffer was allocated temporarily, and therefore must be
|
||||||
|
// deallocated in the dtor, this contains a pointer to the start
|
||||||
|
// of the buffer.
|
||||||
|
const unsigned char* str_buffer_start_;
|
||||||
|
|
||||||
|
// Pointer to the end of the header_length field (aka prologue_length).
|
||||||
|
// The offsets to the line number programs are relative to this point.
|
||||||
|
const unsigned char* end_of_header_length_;
|
||||||
|
|
||||||
|
// Pointers to the start of the line number programs.
|
||||||
|
const unsigned char* logicals_start_;
|
||||||
|
const unsigned char* actuals_start_;
|
||||||
|
|
||||||
|
// Pointer to the end of the current compilation unit.
|
||||||
|
const unsigned char* end_of_unit_;
|
||||||
|
|
||||||
// This has relocations that point into buffer.
|
// This has relocations that point into buffer.
|
||||||
Sized_elf_reloc_mapper<size, big_endian>* reloc_mapper_;
|
Sized_elf_reloc_mapper<size, big_endian>* reloc_mapper_;
|
||||||
// The type of the reloc section in track_relocs_--SHT_REL or SHT_RELA.
|
// The type of the reloc section in track_relocs_--SHT_REL or SHT_RELA.
|
||||||
|
|||||||
74
gold/dwp.cc
74
gold/dwp.cc
@@ -284,14 +284,6 @@ class Sized_relobj_dwo : public Sized_relobj<size, big_endian>
|
|||||||
const unsigned char*
|
const unsigned char*
|
||||||
do_section_contents(unsigned int, section_size_type*, bool);
|
do_section_contents(unsigned int, section_size_type*, bool);
|
||||||
|
|
||||||
// Return a view of the uncompressed contents of a section. Set *PLEN
|
|
||||||
// to the size. Set *IS_NEW to true if the contents need to be deleted
|
|
||||||
// by the caller.
|
|
||||||
const unsigned char*
|
|
||||||
do_decompressed_section_contents(unsigned int shndx,
|
|
||||||
section_size_type* plen,
|
|
||||||
bool* is_new);
|
|
||||||
|
|
||||||
// The following virtual functions are abstract in the base classes,
|
// The following virtual functions are abstract in the base classes,
|
||||||
// but are not used here.
|
// but are not used here.
|
||||||
|
|
||||||
@@ -781,9 +773,36 @@ template <int size, bool big_endian>
|
|||||||
void
|
void
|
||||||
Sized_relobj_dwo<size, big_endian>::setup()
|
Sized_relobj_dwo<size, big_endian>::setup()
|
||||||
{
|
{
|
||||||
|
const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
|
||||||
|
const off_t shoff = this->elf_file_.shoff();
|
||||||
const unsigned int shnum = this->elf_file_.shnum();
|
const unsigned int shnum = this->elf_file_.shnum();
|
||||||
|
|
||||||
this->set_shnum(shnum);
|
this->set_shnum(shnum);
|
||||||
this->section_offsets().resize(shnum);
|
this->section_offsets().resize(shnum);
|
||||||
|
|
||||||
|
// Read the section headers.
|
||||||
|
const unsigned char* const pshdrs = this->get_view(shoff, shnum * shdr_size,
|
||||||
|
true, false);
|
||||||
|
|
||||||
|
// Read the section names.
|
||||||
|
const unsigned char* pshdrnames =
|
||||||
|
pshdrs + this->elf_file_.shstrndx() * shdr_size;
|
||||||
|
typename elfcpp::Shdr<size, big_endian> shdrnames(pshdrnames);
|
||||||
|
if (shdrnames.get_sh_type() != elfcpp::SHT_STRTAB)
|
||||||
|
this->error(_("section name section has wrong type: %u"),
|
||||||
|
static_cast<unsigned int>(shdrnames.get_sh_type()));
|
||||||
|
section_size_type section_names_size =
|
||||||
|
convert_to_section_size_type(shdrnames.get_sh_size());
|
||||||
|
const unsigned char* namesu = this->get_view(shdrnames.get_sh_offset(),
|
||||||
|
section_names_size, false,
|
||||||
|
false);
|
||||||
|
const char* names = reinterpret_cast<const char*>(namesu);
|
||||||
|
|
||||||
|
Compressed_section_map* compressed_sections =
|
||||||
|
build_compressed_section_map<size, big_endian>(
|
||||||
|
pshdrs, this->shnum(), names, section_names_size, this, true);
|
||||||
|
if (compressed_sections != NULL && !compressed_sections->empty())
|
||||||
|
this->set_compressed_sections(compressed_sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a view of the contents of a section.
|
// Return a view of the contents of a section.
|
||||||
@@ -805,43 +824,6 @@ Sized_relobj_dwo<size, big_endian>::do_section_contents(
|
|||||||
return this->get_view(loc.file_offset, *plen, true, cache);
|
return this->get_view(loc.file_offset, *plen, true, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a view of the uncompressed contents of a section. Set *PLEN
|
|
||||||
// to the size. Set *IS_NEW to true if the contents need to be deleted
|
|
||||||
// by the caller.
|
|
||||||
|
|
||||||
template <int size, bool big_endian>
|
|
||||||
const unsigned char*
|
|
||||||
Sized_relobj_dwo<size, big_endian>::do_decompressed_section_contents(
|
|
||||||
unsigned int shndx,
|
|
||||||
section_size_type* plen,
|
|
||||||
bool* is_new)
|
|
||||||
{
|
|
||||||
section_size_type buffer_size;
|
|
||||||
const unsigned char* buffer = this->do_section_contents(shndx, &buffer_size,
|
|
||||||
false);
|
|
||||||
|
|
||||||
std::string sect_name = this->do_section_name(shndx);
|
|
||||||
if (!is_prefix_of(".zdebug_", sect_name.c_str()))
|
|
||||||
{
|
|
||||||
*plen = buffer_size;
|
|
||||||
*is_new = false;
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
section_size_type uncompressed_size = get_uncompressed_size(buffer,
|
|
||||||
buffer_size);
|
|
||||||
unsigned char* uncompressed_data = new unsigned char[uncompressed_size];
|
|
||||||
if (!decompress_input_section(buffer,
|
|
||||||
buffer_size,
|
|
||||||
uncompressed_data,
|
|
||||||
uncompressed_size))
|
|
||||||
this->error(_("could not decompress section %s"),
|
|
||||||
this->section_name(shndx).c_str());
|
|
||||||
*plen = uncompressed_size;
|
|
||||||
*is_new = true;
|
|
||||||
return uncompressed_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Class Dwo_file.
|
// Class Dwo_file.
|
||||||
|
|
||||||
Dwo_file::~Dwo_file()
|
Dwo_file::~Dwo_file()
|
||||||
@@ -2352,7 +2334,7 @@ print_version()
|
|||||||
{
|
{
|
||||||
// This output is intended to follow the GNU standards.
|
// This output is intended to follow the GNU standards.
|
||||||
printf("GNU dwp %s\n", BFD_VERSION_STRING);
|
printf("GNU dwp %s\n", BFD_VERSION_STRING);
|
||||||
printf(_("Copyright (C) 2014-2015 Free Software Foundation, Inc.\n"));
|
printf(_("Copyright (C) 2015 Free Software Foundation, Inc.\n"));
|
||||||
printf(_("\
|
printf(_("\
|
||||||
This program is free software; you may redistribute it under the terms of\n\
|
This program is free software; you may redistribute it under the terms of\n\
|
||||||
the GNU General Public License version 3 or (at your option) any later version.\n\
|
the GNU General Public License version 3 or (at your option) any later version.\n\
|
||||||
|
|||||||
@@ -374,6 +374,17 @@ Sized_dynobj<size, big_endian>::base_read_symbols(Read_symbols_data* sd)
|
|||||||
sd->verneed_size = 0;
|
sd->verneed_size = 0;
|
||||||
sd->verneed_info = 0;
|
sd->verneed_info = 0;
|
||||||
|
|
||||||
|
const unsigned char* namesu = sd->section_names->data();
|
||||||
|
const char* names = reinterpret_cast<const char*>(namesu);
|
||||||
|
if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
|
||||||
|
{
|
||||||
|
Compressed_section_map* compressed_sections =
|
||||||
|
build_compressed_section_map<size, big_endian>(
|
||||||
|
pshdrs, this->shnum(), names, sd->section_names_size, this, true);
|
||||||
|
if (compressed_sections != NULL)
|
||||||
|
this->set_compressed_sections(compressed_sections);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->dynsym_shndx_ != -1U)
|
if (this->dynsym_shndx_ != -1U)
|
||||||
{
|
{
|
||||||
// Get the dynamic symbols.
|
// Get the dynamic symbols.
|
||||||
|
|||||||
@@ -432,8 +432,7 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file(
|
|||||||
discarded_eh_frame_shndx_(-1U),
|
discarded_eh_frame_shndx_(-1U),
|
||||||
is_deferred_layout_(false),
|
is_deferred_layout_(false),
|
||||||
deferred_layout_(),
|
deferred_layout_(),
|
||||||
deferred_layout_relocs_(),
|
deferred_layout_relocs_()
|
||||||
compressed_sections_()
|
|
||||||
{
|
{
|
||||||
this->e_type_ = ehdr.get_e_type();
|
this->e_type_ = ehdr.get_e_type();
|
||||||
}
|
}
|
||||||
@@ -675,7 +674,8 @@ build_compressed_section_map(
|
|||||||
unsigned int shnum,
|
unsigned int shnum,
|
||||||
const char* names,
|
const char* names,
|
||||||
section_size_type names_size,
|
section_size_type names_size,
|
||||||
Sized_relobj_file<size, big_endian>* obj)
|
Object* obj,
|
||||||
|
bool decompress_if_needed)
|
||||||
{
|
{
|
||||||
Compressed_section_map* uncompressed_map = new Compressed_section_map();
|
Compressed_section_map* uncompressed_map = new Compressed_section_map();
|
||||||
const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
|
const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
|
||||||
@@ -707,7 +707,7 @@ build_compressed_section_map(
|
|||||||
if (uncompressed_size != -1ULL)
|
if (uncompressed_size != -1ULL)
|
||||||
{
|
{
|
||||||
unsigned char* uncompressed_data = NULL;
|
unsigned char* uncompressed_data = NULL;
|
||||||
if (need_decompressed_section(name))
|
if (decompress_if_needed && need_decompressed_section(name))
|
||||||
{
|
{
|
||||||
uncompressed_data = new unsigned char[uncompressed_size];
|
uncompressed_data = new unsigned char[uncompressed_size];
|
||||||
if (decompress_input_section(contents, len,
|
if (decompress_input_section(contents, len,
|
||||||
@@ -741,9 +741,14 @@ Sized_relobj_file<size, big_endian>::do_find_special_sections(
|
|||||||
this->has_eh_frame_ = true;
|
this->has_eh_frame_ = true;
|
||||||
|
|
||||||
if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
|
if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
|
||||||
this->compressed_sections_
|
{
|
||||||
= build_compressed_section_map(pshdrs, this->shnum(), names,
|
Compressed_section_map* compressed_sections =
|
||||||
sd->section_names_size, this);
|
build_compressed_section_map<size, big_endian>(
|
||||||
|
pshdrs, this->shnum(), names, sd->section_names_size, this, true);
|
||||||
|
if (compressed_sections != NULL)
|
||||||
|
this->set_compressed_sections(compressed_sections);
|
||||||
|
}
|
||||||
|
|
||||||
return (this->has_eh_frame_
|
return (this->has_eh_frame_
|
||||||
|| (!parameters->options().relocatable()
|
|| (!parameters->options().relocatable()
|
||||||
&& parameters->options().gdb_index()
|
&& parameters->options().gdb_index()
|
||||||
@@ -2804,9 +2809,8 @@ Sized_relobj_file<size, big_endian>::do_get_global_symbol_counts(
|
|||||||
// to the size. Set *IS_NEW to true if the contents need to be freed
|
// to the size. Set *IS_NEW to true if the contents need to be freed
|
||||||
// by the caller.
|
// by the caller.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
|
||||||
const unsigned char*
|
const unsigned char*
|
||||||
Sized_relobj_file<size, big_endian>::do_decompressed_section_contents(
|
Object::decompressed_section_contents(
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
section_size_type* plen,
|
section_size_type* plen,
|
||||||
bool* is_new)
|
bool* is_new)
|
||||||
@@ -2860,9 +2864,8 @@ Sized_relobj_file<size, big_endian>::do_decompressed_section_contents(
|
|||||||
// Discard any buffers of uncompressed sections. This is done
|
// Discard any buffers of uncompressed sections. This is done
|
||||||
// at the end of the Add_symbols task.
|
// at the end of the Add_symbols task.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
|
||||||
void
|
void
|
||||||
Sized_relobj_file<size, big_endian>::do_discard_decompressed_sections()
|
Object::discard_decompressed_sections()
|
||||||
{
|
{
|
||||||
if (this->compressed_sections_ == NULL)
|
if (this->compressed_sections_ == NULL)
|
||||||
return;
|
return;
|
||||||
|
|||||||
116
gold/object.h
116
gold/object.h
@@ -314,6 +314,21 @@ class Got_offset_list
|
|||||||
Got_offset_list* got_next_;
|
Got_offset_list* got_next_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Type for mapping section index to uncompressed size and contents.
|
||||||
|
|
||||||
|
struct Compressed_section_info
|
||||||
|
{
|
||||||
|
section_size_type size;
|
||||||
|
const unsigned char* contents;
|
||||||
|
};
|
||||||
|
typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
Compressed_section_map*
|
||||||
|
build_compressed_section_map(const unsigned char* pshdrs, unsigned int shnum,
|
||||||
|
const char* names, section_size_type names_size,
|
||||||
|
Object* obj, bool decompress_if_needed);
|
||||||
|
|
||||||
// Object is an abstract base class which represents either a 32-bit
|
// Object is an abstract base class which represents either a 32-bit
|
||||||
// or a 64-bit input object. This can be a regular object file
|
// or a 64-bit input object. This can be a regular object file
|
||||||
// (ET_REL) or a shared object (ET_DYN).
|
// (ET_REL) or a shared object (ET_DYN).
|
||||||
@@ -332,7 +347,8 @@ class Object
|
|||||||
: name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
|
: name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
|
||||||
is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false),
|
is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false),
|
||||||
has_no_split_stack_(false), no_export_(false),
|
has_no_split_stack_(false), no_export_(false),
|
||||||
is_in_system_directory_(false), as_needed_(false), xindex_(NULL)
|
is_in_system_directory_(false), as_needed_(false), xindex_(NULL),
|
||||||
|
compressed_sections_(NULL)
|
||||||
{
|
{
|
||||||
if (input_file != NULL)
|
if (input_file != NULL)
|
||||||
{
|
{
|
||||||
@@ -725,26 +741,34 @@ class Object
|
|||||||
set_no_export(bool value)
|
set_no_export(bool value)
|
||||||
{ this->no_export_ = value; }
|
{ this->no_export_ = value; }
|
||||||
|
|
||||||
// Return TRUE if the section is a compressed debug section, and set
|
|
||||||
// *UNCOMPRESSED_SIZE to the size of the uncompressed data.
|
|
||||||
bool
|
bool
|
||||||
section_is_compressed(unsigned int shndx,
|
section_is_compressed(unsigned int shndx,
|
||||||
section_size_type* uncompressed_size) const
|
section_size_type* uncompressed_size) const
|
||||||
{ return this->do_section_is_compressed(shndx, uncompressed_size); }
|
{
|
||||||
|
if (this->compressed_sections_ == NULL)
|
||||||
|
return false;
|
||||||
|
Compressed_section_map::const_iterator p =
|
||||||
|
this->compressed_sections_->find(shndx);
|
||||||
|
if (p != this->compressed_sections_->end())
|
||||||
|
{
|
||||||
|
if (uncompressed_size != NULL)
|
||||||
|
*uncompressed_size = p->second.size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Return a view of the decompressed contents of a section. Set *PLEN
|
// Return a view of the decompressed contents of a section. Set *PLEN
|
||||||
// to the size. Set *IS_NEW to true if the contents need to be freed
|
// to the size. Set *IS_NEW to true if the contents need to be freed
|
||||||
// by the caller.
|
// by the caller.
|
||||||
const unsigned char*
|
const unsigned char*
|
||||||
decompressed_section_contents(unsigned int shndx, section_size_type* plen,
|
decompressed_section_contents(unsigned int shndx, section_size_type* plen,
|
||||||
bool* is_cached)
|
bool* is_cached);
|
||||||
{ return this->do_decompressed_section_contents(shndx, plen, is_cached); }
|
|
||||||
|
|
||||||
// Discard any buffers of decompressed sections. This is done
|
// Discard any buffers of decompressed sections. This is done
|
||||||
// at the end of the Add_symbols task.
|
// at the end of the Add_symbols task.
|
||||||
void
|
void
|
||||||
discard_decompressed_sections()
|
discard_decompressed_sections();
|
||||||
{ this->do_discard_decompressed_sections(); }
|
|
||||||
|
|
||||||
// Return the index of the first incremental relocation for symbol SYMNDX.
|
// Return the index of the first incremental relocation for symbol SYMNDX.
|
||||||
unsigned int
|
unsigned int
|
||||||
@@ -923,27 +947,6 @@ class Object
|
|||||||
bool
|
bool
|
||||||
handle_split_stack_section(const char* name);
|
handle_split_stack_section(const char* name);
|
||||||
|
|
||||||
// Return TRUE if the section is a compressed debug section, and set
|
|
||||||
// *UNCOMPRESSED_SIZE to the size of the uncompressed data.
|
|
||||||
virtual bool
|
|
||||||
do_section_is_compressed(unsigned int, section_size_type*) const
|
|
||||||
{ return false; }
|
|
||||||
|
|
||||||
// Return a view of the decompressed contents of a section. Set *PLEN
|
|
||||||
// to the size. This default implementation simply returns the
|
|
||||||
// raw section contents and sets *IS_NEW to false to indicate
|
|
||||||
// that the contents do not need to be freed by the caller.
|
|
||||||
// This function must be overridden for any types of object files
|
|
||||||
// that might contain compressed sections.
|
|
||||||
virtual const unsigned char*
|
|
||||||
do_decompressed_section_contents(unsigned int shndx,
|
|
||||||
section_size_type* plen,
|
|
||||||
bool* is_new)
|
|
||||||
{
|
|
||||||
*is_new = false;
|
|
||||||
return this->do_section_contents(shndx, plen, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Discard any buffers of decompressed sections. This is done
|
// Discard any buffers of decompressed sections. This is done
|
||||||
// at the end of the Add_symbols task.
|
// at the end of the Add_symbols task.
|
||||||
virtual void
|
virtual void
|
||||||
@@ -962,6 +965,14 @@ class Object
|
|||||||
do_get_incremental_reloc_count(unsigned int) const
|
do_get_incremental_reloc_count(unsigned int) const
|
||||||
{ gold_unreachable(); }
|
{ gold_unreachable(); }
|
||||||
|
|
||||||
|
void
|
||||||
|
set_compressed_sections(Compressed_section_map* compressed_sections)
|
||||||
|
{ this->compressed_sections_ = compressed_sections; }
|
||||||
|
|
||||||
|
Compressed_section_map*
|
||||||
|
compressed_sections()
|
||||||
|
{ return this->compressed_sections_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This class may not be copied.
|
// This class may not be copied.
|
||||||
Object(const Object&);
|
Object(const Object&);
|
||||||
@@ -996,6 +1007,9 @@ class Object
|
|||||||
bool as_needed_ : 1;
|
bool as_needed_ : 1;
|
||||||
// Many sections for objects with more than SHN_LORESERVE sections.
|
// Many sections for objects with more than SHN_LORESERVE sections.
|
||||||
Xindex* xindex_;
|
Xindex* xindex_;
|
||||||
|
// For compressed debug sections, map section index to uncompressed size
|
||||||
|
// and contents.
|
||||||
|
Compressed_section_map* compressed_sections_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A regular object (ET_REL). This is an abstract base class itself.
|
// A regular object (ET_REL). This is an abstract base class itself.
|
||||||
@@ -1862,15 +1876,6 @@ class Reloc_symbol_changes
|
|||||||
std::vector<Symbol*> vec_;
|
std::vector<Symbol*> vec_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Type for mapping section index to uncompressed size and contents.
|
|
||||||
|
|
||||||
struct Compressed_section_info
|
|
||||||
{
|
|
||||||
section_size_type size;
|
|
||||||
const unsigned char* contents;
|
|
||||||
};
|
|
||||||
typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
|
|
||||||
|
|
||||||
// Abstract base class for a regular object file, either a real object file
|
// Abstract base class for a regular object file, either a real object file
|
||||||
// or an incremental (unchanged) object. This is size and endian specific.
|
// or an incremental (unchanged) object. This is size and endian specific.
|
||||||
|
|
||||||
@@ -2453,38 +2458,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
|||||||
set_output_local_symbol_count(unsigned int value)
|
set_output_local_symbol_count(unsigned int value)
|
||||||
{ this->output_local_symbol_count_ = value; }
|
{ this->output_local_symbol_count_ = value; }
|
||||||
|
|
||||||
// Return TRUE if the section is a compressed debug section, and set
|
|
||||||
// *UNCOMPRESSED_SIZE to the size of the uncompressed data.
|
|
||||||
bool
|
|
||||||
do_section_is_compressed(unsigned int shndx,
|
|
||||||
section_size_type* uncompressed_size) const
|
|
||||||
{
|
|
||||||
if (this->compressed_sections_ == NULL)
|
|
||||||
return false;
|
|
||||||
Compressed_section_map::const_iterator p =
|
|
||||||
this->compressed_sections_->find(shndx);
|
|
||||||
if (p != this->compressed_sections_->end())
|
|
||||||
{
|
|
||||||
if (uncompressed_size != NULL)
|
|
||||||
*uncompressed_size = p->second.size;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a view of the uncompressed contents of a section. Set *PLEN
|
|
||||||
// to the size. Set *IS_NEW to true if the contents need to be deleted
|
|
||||||
// by the caller.
|
|
||||||
const unsigned char*
|
|
||||||
do_decompressed_section_contents(unsigned int shndx,
|
|
||||||
section_size_type* plen,
|
|
||||||
bool* is_new);
|
|
||||||
|
|
||||||
// Discard any buffers of decompressed sections. This is done
|
|
||||||
// at the end of the Add_symbols task.
|
|
||||||
void
|
|
||||||
do_discard_decompressed_sections();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For convenience.
|
// For convenience.
|
||||||
typedef Sized_relobj_file<size, big_endian> This;
|
typedef Sized_relobj_file<size, big_endian> This;
|
||||||
@@ -2751,9 +2724,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
|||||||
std::vector<Deferred_layout> deferred_layout_;
|
std::vector<Deferred_layout> deferred_layout_;
|
||||||
// The list of relocation sections whose layout was deferred.
|
// The list of relocation sections whose layout was deferred.
|
||||||
std::vector<Deferred_layout> deferred_layout_relocs_;
|
std::vector<Deferred_layout> deferred_layout_relocs_;
|
||||||
// For compressed debug sections, map section index to uncompressed size
|
|
||||||
// and contents.
|
|
||||||
Compressed_section_map* compressed_sections_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// A class to manage the list of all objects.
|
// A class to manage the list of all objects.
|
||||||
|
|||||||
@@ -3336,8 +3336,11 @@ Symbol_table::detect_odr_violations(const Task* task,
|
|||||||
first_object_name = locs->object->name();
|
first_object_name = locs->object->name();
|
||||||
first_object_linenos = this->linenos_from_loc(task, *locs);
|
first_object_linenos = this->linenos_from_loc(task, *locs);
|
||||||
}
|
}
|
||||||
|
if (first_object_linenos.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
// Sort by Odr_violation_compare to make std::set_intersection work.
|
// Sort by Odr_violation_compare to make std::set_intersection work.
|
||||||
|
std::string first_object_canonical_result = first_object_linenos.back();
|
||||||
std::sort(first_object_linenos.begin(), first_object_linenos.end(),
|
std::sort(first_object_linenos.begin(), first_object_linenos.end(),
|
||||||
Odr_violation_compare());
|
Odr_violation_compare());
|
||||||
|
|
||||||
@@ -3349,6 +3352,8 @@ Symbol_table::detect_odr_violations(const Task* task,
|
|||||||
if (linenos.empty())
|
if (linenos.empty())
|
||||||
continue;
|
continue;
|
||||||
// Sort by Odr_violation_compare to make std::set_intersection work.
|
// Sort by Odr_violation_compare to make std::set_intersection work.
|
||||||
|
gold_assert(!linenos.empty());
|
||||||
|
std::string second_object_canonical_result = linenos.back();
|
||||||
std::sort(linenos.begin(), linenos.end(), Odr_violation_compare());
|
std::sort(linenos.begin(), linenos.end(), Odr_violation_compare());
|
||||||
|
|
||||||
Check_intersection intersection_result =
|
Check_intersection intersection_result =
|
||||||
@@ -3367,13 +3372,11 @@ Symbol_table::detect_odr_violations(const Task* task,
|
|||||||
// which may not be the location we expect to intersect
|
// which may not be the location we expect to intersect
|
||||||
// with another definition. We could print the whole
|
// with another definition. We could print the whole
|
||||||
// set of locations, but that seems too verbose.
|
// set of locations, but that seems too verbose.
|
||||||
gold_assert(!first_object_linenos.empty());
|
|
||||||
gold_assert(!linenos.empty());
|
|
||||||
fprintf(stderr, _(" %s from %s\n"),
|
fprintf(stderr, _(" %s from %s\n"),
|
||||||
first_object_linenos[0].c_str(),
|
first_object_canonical_result.c_str(),
|
||||||
first_object_name.c_str());
|
first_object_name.c_str());
|
||||||
fprintf(stderr, _(" %s from %s\n"),
|
fprintf(stderr, _(" %s from %s\n"),
|
||||||
linenos[0].c_str(),
|
second_object_canonical_result.c_str(),
|
||||||
locs->object->name().c_str());
|
locs->object->name().c_str());
|
||||||
// Only print one broken pair, to avoid needing to
|
// Only print one broken pair, to avoid needing to
|
||||||
// compare against a list of the disjoint definition
|
// compare against a list of the disjoint definition
|
||||||
|
|||||||
@@ -200,6 +200,8 @@ DW_FORM (DW_FORM_sec_offset, 0x17)
|
|||||||
DW_FORM (DW_FORM_exprloc, 0x18)
|
DW_FORM (DW_FORM_exprloc, 0x18)
|
||||||
DW_FORM (DW_FORM_flag_present, 0x19)
|
DW_FORM (DW_FORM_flag_present, 0x19)
|
||||||
DW_FORM (DW_FORM_ref_sig8, 0x20)
|
DW_FORM (DW_FORM_ref_sig8, 0x20)
|
||||||
|
/* DWARF 5. */
|
||||||
|
DW_FORM (DW_FORM_line_strp, 0x1f)
|
||||||
/* Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. */
|
/* Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. */
|
||||||
DW_FORM (DW_FORM_GNU_addr_index, 0x1f01)
|
DW_FORM (DW_FORM_GNU_addr_index, 0x1f01)
|
||||||
DW_FORM (DW_FORM_GNU_str_index, 0x1f02)
|
DW_FORM (DW_FORM_GNU_str_index, 0x1f02)
|
||||||
|
|||||||
@@ -222,7 +222,13 @@ enum dwarf_line_number_ops
|
|||||||
/* DWARF 3. */
|
/* DWARF 3. */
|
||||||
DW_LNS_set_prologue_end = 10,
|
DW_LNS_set_prologue_end = 10,
|
||||||
DW_LNS_set_epilogue_begin = 11,
|
DW_LNS_set_epilogue_begin = 11,
|
||||||
DW_LNS_set_isa = 12
|
DW_LNS_set_isa = 12,
|
||||||
|
/* Experimental DWARF 5 extensions.
|
||||||
|
See http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables. */
|
||||||
|
DW_LNS_set_address_from_logical = 13, /* Actuals table only. */
|
||||||
|
DW_LNS_set_subprogram = 13, /* Logicals table only. */
|
||||||
|
DW_LNS_inlined_call = 14, /* Logicals table only. */
|
||||||
|
DW_LNS_pop_context = 15 /* Logicals table only. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Line number extended opcodes. */
|
/* Line number extended opcodes. */
|
||||||
@@ -268,6 +274,22 @@ enum dwarf_location_list_entry_type
|
|||||||
DW_LLE_GNU_start_length_entry = 3
|
DW_LLE_GNU_start_length_entry = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Type codes for line number program content descriptors (DWARF 5). */
|
||||||
|
|
||||||
|
enum dwarf_line_number_content_type
|
||||||
|
{
|
||||||
|
DW_LNCT_path = 1,
|
||||||
|
DW_LNCT_directory_index = 2,
|
||||||
|
DW_LNCT_timestamp = 3,
|
||||||
|
DW_LNCT_size = 4,
|
||||||
|
DW_LNCT_MD5 = 5,
|
||||||
|
/* Experimental DWARF 5 extensions.
|
||||||
|
See http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables. */
|
||||||
|
DW_LNCT_subprogram_name = 6,
|
||||||
|
DW_LNCT_decl_file = 7,
|
||||||
|
DW_LNCT_decl_line = 8
|
||||||
|
};
|
||||||
|
|
||||||
#define DW_CIE_ID 0xffffffff
|
#define DW_CIE_ID 0xffffffff
|
||||||
#define DW64_CIE_ID 0xffffffffffffffffULL
|
#define DW64_CIE_ID 0xffffffffffffffffULL
|
||||||
#define DW_CIE_VERSION 1
|
#define DW_CIE_VERSION 1
|
||||||
|
|||||||
Reference in New Issue
Block a user