Move more code to line-header.c
This moves some more code out of read.c and into line-header.c. dwarf_decode_line_header is split into two -- the part remaining in read.c handles interfacing to the dwarf2_cu; while the part in line-header.c (more or less) purely handles the actual decoding. gdb/ChangeLog 2020-03-26 Tom Tromey <tom@tromey.com> * dwarf2/line-header.h (dwarf_decode_line_header): Declare. * dwarf2/read.c (dwarf2_statement_list_fits_in_line_number_section_complaint): Move to line-header.c. (read_checked_initial_length_and_offset, read_formatted_entries): Likewise. (dwarf_decode_line_header): Split into two. * dwarf2/line-header.c (dwarf2_statement_list_fits_in_line_number_section_complaint): Move from read.c. (read_checked_initial_length_and_offset, read_formatted_entries): Likewise. (dwarf_decode_line_header): New function, split from read.c.
This commit is contained in:
parent
86c0bb4c57
commit
0df7ad3a67
|
@ -1,3 +1,19 @@
|
|||
2020-03-26 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* dwarf2/line-header.h (dwarf_decode_line_header): Declare.
|
||||
* dwarf2/read.c
|
||||
(dwarf2_statement_list_fits_in_line_number_section_complaint):
|
||||
Move to line-header.c.
|
||||
(read_checked_initial_length_and_offset, read_formatted_entries):
|
||||
Likewise.
|
||||
(dwarf_decode_line_header): Split into two.
|
||||
* dwarf2/line-header.c
|
||||
(dwarf2_statement_list_fits_in_line_number_section_complaint):
|
||||
Move from read.c.
|
||||
(read_checked_initial_length_and_offset, read_formatted_entries):
|
||||
Likewise.
|
||||
(dwarf_decode_line_header): New function, split from read.c.
|
||||
|
||||
2020-03-26 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* dwarf2/read.h (struct dwarf2_per_objfile) <read_line_string>:
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "dwarf2/comp-unit.h"
|
||||
#include "dwarf2/leb.h"
|
||||
#include "dwarf2/line-header.h"
|
||||
#include "dwarf2/read.h"
|
||||
#include "complaints.h"
|
||||
|
@ -112,3 +114,336 @@ line_header::file_full_name (int file, const char *comp_dir) const
|
|||
else
|
||||
return file_file_name (file);
|
||||
}
|
||||
|
||||
static void
|
||||
dwarf2_statement_list_fits_in_line_number_section_complaint (void)
|
||||
{
|
||||
complaint (_("statement list doesn't fit in .debug_line section"));
|
||||
}
|
||||
|
||||
/* Cover function for read_initial_length.
|
||||
Returns the length of the object at BUF, and stores the size of the
|
||||
initial length in *BYTES_READ and stores the size that offsets will be in
|
||||
*OFFSET_SIZE.
|
||||
If the initial length size is not equivalent to that specified in
|
||||
CU_HEADER then issue a complaint.
|
||||
This is useful when reading non-comp-unit headers. */
|
||||
|
||||
static LONGEST
|
||||
read_checked_initial_length_and_offset (bfd *abfd, const gdb_byte *buf,
|
||||
const struct comp_unit_head *cu_header,
|
||||
unsigned int *bytes_read,
|
||||
unsigned int *offset_size)
|
||||
{
|
||||
LONGEST length = read_initial_length (abfd, buf, bytes_read);
|
||||
|
||||
gdb_assert (cu_header->initial_length_size == 4
|
||||
|| cu_header->initial_length_size == 8
|
||||
|| cu_header->initial_length_size == 12);
|
||||
|
||||
if (cu_header->initial_length_size != *bytes_read)
|
||||
complaint (_("intermixed 32-bit and 64-bit DWARF sections"));
|
||||
|
||||
*offset_size = (*bytes_read == 4) ? 4 : 8;
|
||||
return length;
|
||||
}
|
||||
|
||||
/* Read directory or file name entry format, starting with byte of
|
||||
format count entries, ULEB128 pairs of entry formats, ULEB128 of
|
||||
entries count and the entries themselves in the described entry
|
||||
format. */
|
||||
|
||||
static void
|
||||
read_formatted_entries (struct dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
bfd *abfd, const gdb_byte **bufp,
|
||||
struct line_header *lh,
|
||||
const struct comp_unit_head *cu_header,
|
||||
void (*callback) (struct line_header *lh,
|
||||
const char *name,
|
||||
dir_index d_index,
|
||||
unsigned int mod_time,
|
||||
unsigned int length))
|
||||
{
|
||||
gdb_byte format_count, formati;
|
||||
ULONGEST data_count, datai;
|
||||
const gdb_byte *buf = *bufp;
|
||||
const gdb_byte *format_header_data;
|
||||
unsigned int bytes_read;
|
||||
|
||||
format_count = read_1_byte (abfd, buf);
|
||||
buf += 1;
|
||||
format_header_data = buf;
|
||||
for (formati = 0; formati < format_count; formati++)
|
||||
{
|
||||
read_unsigned_leb128 (abfd, buf, &bytes_read);
|
||||
buf += bytes_read;
|
||||
read_unsigned_leb128 (abfd, buf, &bytes_read);
|
||||
buf += bytes_read;
|
||||
}
|
||||
|
||||
data_count = read_unsigned_leb128 (abfd, buf, &bytes_read);
|
||||
buf += bytes_read;
|
||||
for (datai = 0; datai < data_count; datai++)
|
||||
{
|
||||
const gdb_byte *format = format_header_data;
|
||||
struct file_entry fe;
|
||||
|
||||
for (formati = 0; formati < format_count; formati++)
|
||||
{
|
||||
ULONGEST content_type = read_unsigned_leb128 (abfd, format, &bytes_read);
|
||||
format += bytes_read;
|
||||
|
||||
ULONGEST form = read_unsigned_leb128 (abfd, format, &bytes_read);
|
||||
format += bytes_read;
|
||||
|
||||
gdb::optional<const char *> string;
|
||||
gdb::optional<unsigned int> uint;
|
||||
|
||||
switch (form)
|
||||
{
|
||||
case DW_FORM_string:
|
||||
string.emplace (read_direct_string (abfd, buf, &bytes_read));
|
||||
buf += bytes_read;
|
||||
break;
|
||||
|
||||
case DW_FORM_line_strp:
|
||||
string.emplace
|
||||
(dwarf2_per_objfile->read_line_string (buf,
|
||||
cu_header,
|
||||
&bytes_read));
|
||||
buf += bytes_read;
|
||||
break;
|
||||
|
||||
case DW_FORM_data1:
|
||||
uint.emplace (read_1_byte (abfd, buf));
|
||||
buf += 1;
|
||||
break;
|
||||
|
||||
case DW_FORM_data2:
|
||||
uint.emplace (read_2_bytes (abfd, buf));
|
||||
buf += 2;
|
||||
break;
|
||||
|
||||
case DW_FORM_data4:
|
||||
uint.emplace (read_4_bytes (abfd, buf));
|
||||
buf += 4;
|
||||
break;
|
||||
|
||||
case DW_FORM_data8:
|
||||
uint.emplace (read_8_bytes (abfd, buf));
|
||||
buf += 8;
|
||||
break;
|
||||
|
||||
case DW_FORM_data16:
|
||||
/* This is used for MD5, but file_entry does not record MD5s. */
|
||||
buf += 16;
|
||||
break;
|
||||
|
||||
case DW_FORM_udata:
|
||||
uint.emplace (read_unsigned_leb128 (abfd, buf, &bytes_read));
|
||||
buf += bytes_read;
|
||||
break;
|
||||
|
||||
case DW_FORM_block:
|
||||
/* It is valid only for DW_LNCT_timestamp which is ignored by
|
||||
current GDB. */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (content_type)
|
||||
{
|
||||
case DW_LNCT_path:
|
||||
if (string.has_value ())
|
||||
fe.name = *string;
|
||||
break;
|
||||
case DW_LNCT_directory_index:
|
||||
if (uint.has_value ())
|
||||
fe.d_index = (dir_index) *uint;
|
||||
break;
|
||||
case DW_LNCT_timestamp:
|
||||
if (uint.has_value ())
|
||||
fe.mod_time = *uint;
|
||||
break;
|
||||
case DW_LNCT_size:
|
||||
if (uint.has_value ())
|
||||
fe.length = *uint;
|
||||
break;
|
||||
case DW_LNCT_MD5:
|
||||
break;
|
||||
default:
|
||||
complaint (_("Unknown format content type %s"),
|
||||
pulongest (content_type));
|
||||
}
|
||||
}
|
||||
|
||||
callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length);
|
||||
}
|
||||
|
||||
*bufp = buf;
|
||||
}
|
||||
|
||||
/* See line-header.h. */
|
||||
|
||||
line_header_up
|
||||
dwarf_decode_line_header (sect_offset sect_off, bool is_dwz,
|
||||
struct dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
struct dwarf2_section_info *section,
|
||||
const struct comp_unit_head *cu_header)
|
||||
{
|
||||
const gdb_byte *line_ptr;
|
||||
unsigned int bytes_read, offset_size;
|
||||
int i;
|
||||
const char *cur_dir, *cur_file;
|
||||
|
||||
bfd *abfd = section->get_bfd_owner ();
|
||||
|
||||
/* Make sure that at least there's room for the total_length field.
|
||||
That could be 12 bytes long, but we're just going to fudge that. */
|
||||
if (to_underlying (sect_off) + 4 >= section->size)
|
||||
{
|
||||
dwarf2_statement_list_fits_in_line_number_section_complaint ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
line_header_up lh (new line_header ());
|
||||
|
||||
lh->sect_off = sect_off;
|
||||
lh->offset_in_dwz = is_dwz;
|
||||
|
||||
line_ptr = section->buffer + to_underlying (sect_off);
|
||||
|
||||
/* Read in the header. */
|
||||
lh->total_length =
|
||||
read_checked_initial_length_and_offset (abfd, line_ptr, cu_header,
|
||||
&bytes_read, &offset_size);
|
||||
line_ptr += bytes_read;
|
||||
|
||||
const gdb_byte *start_here = line_ptr;
|
||||
|
||||
if (line_ptr + lh->total_length > (section->buffer + section->size))
|
||||
{
|
||||
dwarf2_statement_list_fits_in_line_number_section_complaint ();
|
||||
return 0;
|
||||
}
|
||||
lh->statement_program_end = start_here + lh->total_length;
|
||||
lh->version = read_2_bytes (abfd, line_ptr);
|
||||
line_ptr += 2;
|
||||
if (lh->version > 5)
|
||||
{
|
||||
/* This is a version we don't understand. The format could have
|
||||
changed in ways we don't handle properly so just punt. */
|
||||
complaint (_("unsupported version in .debug_line section"));
|
||||
return NULL;
|
||||
}
|
||||
if (lh->version >= 5)
|
||||
{
|
||||
gdb_byte segment_selector_size;
|
||||
|
||||
/* Skip address size. */
|
||||
read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
|
||||
segment_selector_size = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
if (segment_selector_size != 0)
|
||||
{
|
||||
complaint (_("unsupported segment selector size %u "
|
||||
"in .debug_line section"),
|
||||
segment_selector_size);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
lh->header_length = read_offset (abfd, line_ptr, offset_size);
|
||||
line_ptr += offset_size;
|
||||
lh->statement_program_start = line_ptr + lh->header_length;
|
||||
lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
if (lh->version >= 4)
|
||||
{
|
||||
lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
}
|
||||
else
|
||||
lh->maximum_ops_per_instruction = 1;
|
||||
|
||||
if (lh->maximum_ops_per_instruction == 0)
|
||||
{
|
||||
lh->maximum_ops_per_instruction = 1;
|
||||
complaint (_("invalid maximum_ops_per_instruction "
|
||||
"in `.debug_line' section"));
|
||||
}
|
||||
|
||||
lh->default_is_stmt = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
lh->line_base = read_1_signed_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
lh->line_range = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
lh->opcode_base = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
lh->standard_opcode_lengths.reset (new unsigned char[lh->opcode_base]);
|
||||
|
||||
lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */
|
||||
for (i = 1; i < lh->opcode_base; ++i)
|
||||
{
|
||||
lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
}
|
||||
|
||||
if (lh->version >= 5)
|
||||
{
|
||||
/* Read directory table. */
|
||||
read_formatted_entries (dwarf2_per_objfile, abfd, &line_ptr, lh.get (),
|
||||
cu_header,
|
||||
[] (struct line_header *header, const char *name,
|
||||
dir_index d_index, unsigned int mod_time,
|
||||
unsigned int length)
|
||||
{
|
||||
header->add_include_dir (name);
|
||||
});
|
||||
|
||||
/* Read file name table. */
|
||||
read_formatted_entries (dwarf2_per_objfile, abfd, &line_ptr, lh.get (),
|
||||
cu_header,
|
||||
[] (struct line_header *header, const char *name,
|
||||
dir_index d_index, unsigned int mod_time,
|
||||
unsigned int length)
|
||||
{
|
||||
header->add_file_name (name, d_index, mod_time, length);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read directory table. */
|
||||
while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
|
||||
{
|
||||
line_ptr += bytes_read;
|
||||
lh->add_include_dir (cur_dir);
|
||||
}
|
||||
line_ptr += bytes_read;
|
||||
|
||||
/* Read file name table. */
|
||||
while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
|
||||
{
|
||||
unsigned int mod_time, length;
|
||||
dir_index d_index;
|
||||
|
||||
line_ptr += bytes_read;
|
||||
d_index = (dir_index) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
line_ptr += bytes_read;
|
||||
mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
line_ptr += bytes_read;
|
||||
length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
line_ptr += bytes_read;
|
||||
|
||||
lh->add_file_name (cur_file, d_index, mod_time, length);
|
||||
}
|
||||
line_ptr += bytes_read;
|
||||
}
|
||||
|
||||
if (line_ptr > (section->buffer + section->size))
|
||||
complaint (_("line number info header doesn't "
|
||||
"fit in `.debug_line' section"));
|
||||
|
||||
return lh;
|
||||
}
|
||||
|
|
|
@ -195,4 +195,18 @@ file_entry::include_dir (const line_header *lh) const
|
|||
return lh->include_dir_at (d_index);
|
||||
}
|
||||
|
||||
/* Read the statement program header starting at SECT_OFF in SECTION.
|
||||
Return line_header. Returns nullptr if there is a problem reading
|
||||
the header, e.g., if it has a version we don't understand.
|
||||
|
||||
NOTE: the strings in the include directory and file name tables of
|
||||
the returned object point into the dwarf line section buffer,
|
||||
and must not be freed. */
|
||||
|
||||
extern line_header_up dwarf_decode_line_header
|
||||
(sect_offset sect_off, bool is_dwz,
|
||||
struct dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
struct dwarf2_section_info *section,
|
||||
const struct comp_unit_head *cu_header);
|
||||
|
||||
#endif /* DWARF2_LINE_HEADER_H */
|
||||
|
|
|
@ -1239,10 +1239,6 @@ static void read_attribute_reprocess (const struct die_reader_specs *reader,
|
|||
|
||||
static CORE_ADDR read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index);
|
||||
|
||||
static LONGEST read_checked_initial_length_and_offset
|
||||
(bfd *, const gdb_byte *, const struct comp_unit_head *,
|
||||
unsigned int *, unsigned int *);
|
||||
|
||||
static sect_offset read_abbrev_offset
|
||||
(struct dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
struct dwarf2_section_info *, sect_offset);
|
||||
|
@ -1673,12 +1669,6 @@ static void free_line_header_voidp (void *arg);
|
|||
|
||||
/* Various complaints about symbol reading that don't abort the process. */
|
||||
|
||||
static void
|
||||
dwarf2_statement_list_fits_in_line_number_section_complaint (void)
|
||||
{
|
||||
complaint (_("statement list doesn't fit in .debug_line section"));
|
||||
}
|
||||
|
||||
static void
|
||||
dwarf2_debug_line_missing_file_complaint (void)
|
||||
{
|
||||
|
@ -18730,33 +18720,6 @@ read_attribute (const struct die_reader_specs *reader,
|
|||
need_reprocess);
|
||||
}
|
||||
|
||||
/* Cover function for read_initial_length.
|
||||
Returns the length of the object at BUF, and stores the size of the
|
||||
initial length in *BYTES_READ and stores the size that offsets will be in
|
||||
*OFFSET_SIZE.
|
||||
If the initial length size is not equivalent to that specified in
|
||||
CU_HEADER then issue a complaint.
|
||||
This is useful when reading non-comp-unit headers. */
|
||||
|
||||
static LONGEST
|
||||
read_checked_initial_length_and_offset (bfd *abfd, const gdb_byte *buf,
|
||||
const struct comp_unit_head *cu_header,
|
||||
unsigned int *bytes_read,
|
||||
unsigned int *offset_size)
|
||||
{
|
||||
LONGEST length = read_initial_length (abfd, buf, bytes_read);
|
||||
|
||||
gdb_assert (cu_header->initial_length_size == 4
|
||||
|| cu_header->initial_length_size == 8
|
||||
|| cu_header->initial_length_size == 12);
|
||||
|
||||
if (cu_header->initial_length_size != *bytes_read)
|
||||
complaint (_("intermixed 32-bit and 64-bit DWARF sections"));
|
||||
|
||||
*offset_size = (*bytes_read == 4) ? 4 : 8;
|
||||
return length;
|
||||
}
|
||||
|
||||
/* Return pointer to string at .debug_str offset STR_OFFSET. */
|
||||
|
||||
static const char *
|
||||
|
@ -19217,140 +19180,6 @@ get_debug_line_section (struct dwarf2_cu *cu)
|
|||
return section;
|
||||
}
|
||||
|
||||
/* Read directory or file name entry format, starting with byte of
|
||||
format count entries, ULEB128 pairs of entry formats, ULEB128 of
|
||||
entries count and the entries themselves in the described entry
|
||||
format. */
|
||||
|
||||
static void
|
||||
read_formatted_entries (struct dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
bfd *abfd, const gdb_byte **bufp,
|
||||
struct line_header *lh,
|
||||
const struct comp_unit_head *cu_header,
|
||||
void (*callback) (struct line_header *lh,
|
||||
const char *name,
|
||||
dir_index d_index,
|
||||
unsigned int mod_time,
|
||||
unsigned int length))
|
||||
{
|
||||
gdb_byte format_count, formati;
|
||||
ULONGEST data_count, datai;
|
||||
const gdb_byte *buf = *bufp;
|
||||
const gdb_byte *format_header_data;
|
||||
unsigned int bytes_read;
|
||||
|
||||
format_count = read_1_byte (abfd, buf);
|
||||
buf += 1;
|
||||
format_header_data = buf;
|
||||
for (formati = 0; formati < format_count; formati++)
|
||||
{
|
||||
read_unsigned_leb128 (abfd, buf, &bytes_read);
|
||||
buf += bytes_read;
|
||||
read_unsigned_leb128 (abfd, buf, &bytes_read);
|
||||
buf += bytes_read;
|
||||
}
|
||||
|
||||
data_count = read_unsigned_leb128 (abfd, buf, &bytes_read);
|
||||
buf += bytes_read;
|
||||
for (datai = 0; datai < data_count; datai++)
|
||||
{
|
||||
const gdb_byte *format = format_header_data;
|
||||
struct file_entry fe;
|
||||
|
||||
for (formati = 0; formati < format_count; formati++)
|
||||
{
|
||||
ULONGEST content_type = read_unsigned_leb128 (abfd, format, &bytes_read);
|
||||
format += bytes_read;
|
||||
|
||||
ULONGEST form = read_unsigned_leb128 (abfd, format, &bytes_read);
|
||||
format += bytes_read;
|
||||
|
||||
gdb::optional<const char *> string;
|
||||
gdb::optional<unsigned int> uint;
|
||||
|
||||
switch (form)
|
||||
{
|
||||
case DW_FORM_string:
|
||||
string.emplace (read_direct_string (abfd, buf, &bytes_read));
|
||||
buf += bytes_read;
|
||||
break;
|
||||
|
||||
case DW_FORM_line_strp:
|
||||
string.emplace
|
||||
(dwarf2_per_objfile->read_line_string (buf,
|
||||
cu_header,
|
||||
&bytes_read));
|
||||
buf += bytes_read;
|
||||
break;
|
||||
|
||||
case DW_FORM_data1:
|
||||
uint.emplace (read_1_byte (abfd, buf));
|
||||
buf += 1;
|
||||
break;
|
||||
|
||||
case DW_FORM_data2:
|
||||
uint.emplace (read_2_bytes (abfd, buf));
|
||||
buf += 2;
|
||||
break;
|
||||
|
||||
case DW_FORM_data4:
|
||||
uint.emplace (read_4_bytes (abfd, buf));
|
||||
buf += 4;
|
||||
break;
|
||||
|
||||
case DW_FORM_data8:
|
||||
uint.emplace (read_8_bytes (abfd, buf));
|
||||
buf += 8;
|
||||
break;
|
||||
|
||||
case DW_FORM_data16:
|
||||
/* This is used for MD5, but file_entry does not record MD5s. */
|
||||
buf += 16;
|
||||
break;
|
||||
|
||||
case DW_FORM_udata:
|
||||
uint.emplace (read_unsigned_leb128 (abfd, buf, &bytes_read));
|
||||
buf += bytes_read;
|
||||
break;
|
||||
|
||||
case DW_FORM_block:
|
||||
/* It is valid only for DW_LNCT_timestamp which is ignored by
|
||||
current GDB. */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (content_type)
|
||||
{
|
||||
case DW_LNCT_path:
|
||||
if (string.has_value ())
|
||||
fe.name = *string;
|
||||
break;
|
||||
case DW_LNCT_directory_index:
|
||||
if (uint.has_value ())
|
||||
fe.d_index = (dir_index) *uint;
|
||||
break;
|
||||
case DW_LNCT_timestamp:
|
||||
if (uint.has_value ())
|
||||
fe.mod_time = *uint;
|
||||
break;
|
||||
case DW_LNCT_size:
|
||||
if (uint.has_value ())
|
||||
fe.length = *uint;
|
||||
break;
|
||||
case DW_LNCT_MD5:
|
||||
break;
|
||||
default:
|
||||
complaint (_("Unknown format content type %s"),
|
||||
pulongest (content_type));
|
||||
}
|
||||
}
|
||||
|
||||
callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length);
|
||||
}
|
||||
|
||||
*bufp = buf;
|
||||
}
|
||||
|
||||
/* Read the statement program header starting at OFFSET in
|
||||
.debug_line, or .debug_line.dwo. Return a pointer
|
||||
to a struct line_header, allocated using xmalloc.
|
||||
|
@ -19364,12 +19193,7 @@ read_formatted_entries (struct dwarf2_per_objfile *dwarf2_per_objfile,
|
|||
static line_header_up
|
||||
dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
|
||||
{
|
||||
const gdb_byte *line_ptr;
|
||||
unsigned int bytes_read, offset_size;
|
||||
int i;
|
||||
const char *cur_dir, *cur_file;
|
||||
struct dwarf2_section_info *section;
|
||||
bfd *abfd;
|
||||
struct dwarf2_per_objfile *dwarf2_per_objfile
|
||||
= cu->per_cu->dwarf2_per_objfile;
|
||||
|
||||
|
@ -19384,159 +19208,9 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* We can't do this until we know the section is non-empty.
|
||||
Only then do we know we have such a section. */
|
||||
abfd = section->get_bfd_owner ();
|
||||
|
||||
/* Make sure that at least there's room for the total_length field.
|
||||
That could be 12 bytes long, but we're just going to fudge that. */
|
||||
if (to_underlying (sect_off) + 4 >= section->size)
|
||||
{
|
||||
dwarf2_statement_list_fits_in_line_number_section_complaint ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
line_header_up lh (new line_header ());
|
||||
|
||||
lh->sect_off = sect_off;
|
||||
lh->offset_in_dwz = cu->per_cu->is_dwz;
|
||||
|
||||
line_ptr = section->buffer + to_underlying (sect_off);
|
||||
|
||||
/* Read in the header. */
|
||||
lh->total_length =
|
||||
read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header,
|
||||
&bytes_read, &offset_size);
|
||||
line_ptr += bytes_read;
|
||||
|
||||
const gdb_byte *start_here = line_ptr;
|
||||
|
||||
if (line_ptr + lh->total_length > (section->buffer + section->size))
|
||||
{
|
||||
dwarf2_statement_list_fits_in_line_number_section_complaint ();
|
||||
return 0;
|
||||
}
|
||||
lh->statement_program_end = start_here + lh->total_length;
|
||||
lh->version = read_2_bytes (abfd, line_ptr);
|
||||
line_ptr += 2;
|
||||
if (lh->version > 5)
|
||||
{
|
||||
/* This is a version we don't understand. The format could have
|
||||
changed in ways we don't handle properly so just punt. */
|
||||
complaint (_("unsupported version in .debug_line section"));
|
||||
return NULL;
|
||||
}
|
||||
if (lh->version >= 5)
|
||||
{
|
||||
gdb_byte segment_selector_size;
|
||||
|
||||
/* Skip address size. */
|
||||
read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
|
||||
segment_selector_size = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
if (segment_selector_size != 0)
|
||||
{
|
||||
complaint (_("unsupported segment selector size %u "
|
||||
"in .debug_line section"),
|
||||
segment_selector_size);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
lh->header_length = read_offset (abfd, line_ptr, offset_size);
|
||||
line_ptr += offset_size;
|
||||
lh->statement_program_start = line_ptr + lh->header_length;
|
||||
lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
if (lh->version >= 4)
|
||||
{
|
||||
lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
}
|
||||
else
|
||||
lh->maximum_ops_per_instruction = 1;
|
||||
|
||||
if (lh->maximum_ops_per_instruction == 0)
|
||||
{
|
||||
lh->maximum_ops_per_instruction = 1;
|
||||
complaint (_("invalid maximum_ops_per_instruction "
|
||||
"in `.debug_line' section"));
|
||||
}
|
||||
|
||||
lh->default_is_stmt = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
lh->line_base = read_1_signed_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
lh->line_range = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
lh->opcode_base = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
lh->standard_opcode_lengths.reset (new unsigned char[lh->opcode_base]);
|
||||
|
||||
lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */
|
||||
for (i = 1; i < lh->opcode_base; ++i)
|
||||
{
|
||||
lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
}
|
||||
|
||||
if (lh->version >= 5)
|
||||
{
|
||||
/* Read directory table. */
|
||||
read_formatted_entries (dwarf2_per_objfile, abfd, &line_ptr, lh.get (),
|
||||
&cu->header,
|
||||
[] (struct line_header *header, const char *name,
|
||||
dir_index d_index, unsigned int mod_time,
|
||||
unsigned int length)
|
||||
{
|
||||
header->add_include_dir (name);
|
||||
});
|
||||
|
||||
/* Read file name table. */
|
||||
read_formatted_entries (dwarf2_per_objfile, abfd, &line_ptr, lh.get (),
|
||||
&cu->header,
|
||||
[] (struct line_header *header, const char *name,
|
||||
dir_index d_index, unsigned int mod_time,
|
||||
unsigned int length)
|
||||
{
|
||||
header->add_file_name (name, d_index, mod_time, length);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read directory table. */
|
||||
while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
|
||||
{
|
||||
line_ptr += bytes_read;
|
||||
lh->add_include_dir (cur_dir);
|
||||
}
|
||||
line_ptr += bytes_read;
|
||||
|
||||
/* Read file name table. */
|
||||
while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
|
||||
{
|
||||
unsigned int mod_time, length;
|
||||
dir_index d_index;
|
||||
|
||||
line_ptr += bytes_read;
|
||||
d_index = (dir_index) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
line_ptr += bytes_read;
|
||||
mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
line_ptr += bytes_read;
|
||||
length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
line_ptr += bytes_read;
|
||||
|
||||
lh->add_file_name (cur_file, d_index, mod_time, length);
|
||||
}
|
||||
line_ptr += bytes_read;
|
||||
}
|
||||
|
||||
if (line_ptr > (section->buffer + section->size))
|
||||
complaint (_("line number info header doesn't "
|
||||
"fit in `.debug_line' section"));
|
||||
|
||||
return lh;
|
||||
return dwarf_decode_line_header (sect_off, cu->per_cu->is_dwz,
|
||||
dwarf2_per_objfile, section,
|
||||
&cu->header);
|
||||
}
|
||||
|
||||
/* Subroutine of dwarf_decode_lines to simplify it.
|
||||
|
|
Loading…
Reference in New Issue