dwarf2read.c: Clean up out of bounds handling
Multiple places in dwarf2read.c open code 1-based to 0-based index conversion and check for out of bounds accesses to lh->include_dirs and lh->file_names. This commit factors those out to a couple methods and uses them throughout. gdb/ChangeLog: 2017-03-27 Pedro Alves <palves@redhat.com> * dwarf2read.c (file_entry) <dir_index>: Add comment. (file_entry::include_dir): New method. (line_header::include_dir_at, line_header::file_name_at): New methods. (setup_type_unit_groups, setup_type_unit_groups) (psymtab_include_file_name): Simplify using the new methods. (lnp_state_machine) <the_line_header>: New field. <file>: Add comment. (lnp_state_machine::current_file): New method. (dwarf_record_line): Simplify using the new methods. (init_lnp_state_machine): Initialize the "the_line_header" field. (dwarf_decode_lines_1, dwarf_decode_lines, file_file_name): Simplify using the new methods.
This commit is contained in:
parent
a7e80b9e21
commit
8c43009f48
|
@ -1,3 +1,19 @@
|
||||||
|
2017-03-27 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
|
* dwarf2read.c (file_entry) <dir_index>: Add comment.
|
||||||
|
(file_entry::include_dir): New method.
|
||||||
|
(line_header::include_dir_at, line_header::file_name_at): New
|
||||||
|
methods.
|
||||||
|
(setup_type_unit_groups, setup_type_unit_groups)
|
||||||
|
(psymtab_include_file_name): Simplify using the new methods.
|
||||||
|
(lnp_state_machine) <the_line_header>: New field.
|
||||||
|
<file>: Add comment.
|
||||||
|
(lnp_state_machine::current_file): New method.
|
||||||
|
(dwarf_record_line): Simplify using the new methods.
|
||||||
|
(init_lnp_state_machine): Initialize the "the_line_header" field.
|
||||||
|
(dwarf_decode_lines_1, dwarf_decode_lines, file_file_name):
|
||||||
|
Simplify using the new methods.
|
||||||
|
|
||||||
2017-03-27 Pedro Alves <palves@redhat.com>
|
2017-03-27 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
* cp-name-parser.y (make_empty): Delete.
|
* cp-name-parser.y (make_empty): Delete.
|
||||||
|
|
158
gdb/dwarf2read.c
158
gdb/dwarf2read.c
|
@ -1054,7 +1054,12 @@ typedef void (die_reader_func_ftype) (const struct die_reader_specs *reader,
|
||||||
|
|
||||||
struct file_entry
|
struct file_entry
|
||||||
{
|
{
|
||||||
|
/* Return the include directory at DIR_INDEX stored in LH. Returns
|
||||||
|
NULL if DIR_INDEX is out of bounds. */
|
||||||
|
const char *include_dir (const line_header *lh) const;
|
||||||
|
|
||||||
const char *name;
|
const char *name;
|
||||||
|
/* The directory index (1-based). */
|
||||||
unsigned int dir_index;
|
unsigned int dir_index;
|
||||||
unsigned int mod_time;
|
unsigned int mod_time;
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
|
@ -1069,6 +1074,24 @@ struct file_entry
|
||||||
which contains the following information. */
|
which contains the following information. */
|
||||||
struct line_header
|
struct line_header
|
||||||
{
|
{
|
||||||
|
/* Return the include dir at INDEX (0-based). Returns NULL if INDEX
|
||||||
|
is out of bounds. */
|
||||||
|
const char *include_dir_at (unsigned int index) const
|
||||||
|
{
|
||||||
|
if (include_dirs == NULL || index >= num_include_dirs)
|
||||||
|
return NULL;
|
||||||
|
return include_dirs[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the file name at INDEX (0-based). Returns NULL if INDEX
|
||||||
|
is out of bounds. */
|
||||||
|
file_entry *file_name_at (unsigned int index) const
|
||||||
|
{
|
||||||
|
if (file_names == NULL || index >= num_file_names)
|
||||||
|
return NULL;
|
||||||
|
return &file_names[index];
|
||||||
|
}
|
||||||
|
|
||||||
/* Offset of line number information in .debug_line section. */
|
/* Offset of line number information in .debug_line section. */
|
||||||
sect_offset offset;
|
sect_offset offset;
|
||||||
|
|
||||||
|
@ -1109,6 +1132,14 @@ struct line_header
|
||||||
const gdb_byte *statement_program_start, *statement_program_end;
|
const gdb_byte *statement_program_start, *statement_program_end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *
|
||||||
|
file_entry::include_dir (const line_header *lh) const
|
||||||
|
{
|
||||||
|
/* lh->include_dirs is 0-based, but the directory index numbers in
|
||||||
|
the statement program are 1-based. */
|
||||||
|
return lh->include_dir_at (dir_index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* When we construct a partial symbol table entry we only
|
/* When we construct a partial symbol table entry we only
|
||||||
need this much information. */
|
need this much information. */
|
||||||
struct partial_die_info
|
struct partial_die_info
|
||||||
|
@ -9423,13 +9454,9 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
|
|
||||||
for (i = 0; i < lh->num_file_names; ++i)
|
for (i = 0; i < lh->num_file_names; ++i)
|
||||||
{
|
{
|
||||||
const char *dir = NULL;
|
file_entry &fe = lh->file_names[i];
|
||||||
struct file_entry *fe = &lh->file_names[i];
|
|
||||||
|
|
||||||
if (fe->dir_index && lh->include_dirs != NULL
|
dwarf2_start_subfile (fe.name, fe.include_dir (lh));
|
||||||
&& (fe->dir_index - 1) < lh->num_include_dirs)
|
|
||||||
dir = lh->include_dirs[fe->dir_index - 1];
|
|
||||||
dwarf2_start_subfile (fe->name, dir);
|
|
||||||
|
|
||||||
if (current_subfile->symtab == NULL)
|
if (current_subfile->symtab == NULL)
|
||||||
{
|
{
|
||||||
|
@ -9441,8 +9468,8 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
= allocate_symtab (cust, current_subfile->name);
|
= allocate_symtab (cust, current_subfile->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
fe->symtab = current_subfile->symtab;
|
fe.symtab = current_subfile->symtab;
|
||||||
tu_group->symtabs[i] = fe->symtab;
|
tu_group->symtabs[i] = fe.symtab;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -17983,17 +18010,14 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
|
||||||
const struct partial_symtab *pst,
|
const struct partial_symtab *pst,
|
||||||
const char *comp_dir)
|
const char *comp_dir)
|
||||||
{
|
{
|
||||||
const struct file_entry fe = lh->file_names [file_index];
|
const file_entry &fe = lh->file_names[file_index];
|
||||||
const char *include_name = fe.name;
|
const char *include_name = fe.name;
|
||||||
const char *include_name_to_compare = include_name;
|
const char *include_name_to_compare = include_name;
|
||||||
const char *dir_name = NULL;
|
|
||||||
const char *pst_filename;
|
const char *pst_filename;
|
||||||
char *copied_name = NULL;
|
char *copied_name = NULL;
|
||||||
int file_is_pst;
|
int file_is_pst;
|
||||||
|
|
||||||
if (fe.dir_index && lh->include_dirs != NULL
|
const char *dir_name = fe.include_dir (lh);
|
||||||
&& (fe.dir_index - 1) < lh->num_include_dirs)
|
|
||||||
dir_name = lh->include_dirs[fe.dir_index - 1];
|
|
||||||
|
|
||||||
if (!IS_ABSOLUTE_PATH (include_name)
|
if (!IS_ABSOLUTE_PATH (include_name)
|
||||||
&& (dir_name != NULL || comp_dir != NULL))
|
&& (dir_name != NULL || comp_dir != NULL))
|
||||||
|
@ -18058,11 +18082,22 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
|
||||||
|
|
||||||
/* State machine to track the state of the line number program. */
|
/* State machine to track the state of the line number program. */
|
||||||
|
|
||||||
typedef struct
|
struct lnp_state_machine
|
||||||
{
|
{
|
||||||
|
file_entry *current_file ()
|
||||||
|
{
|
||||||
|
/* lh->file_names is 0-based, but the file name numbers in the
|
||||||
|
statement program are 1-based. */
|
||||||
|
return the_line_header->file_name_at (file - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The line number header. */
|
||||||
|
line_header *the_line_header;
|
||||||
|
|
||||||
/* These are part of the standard DWARF line number state machine. */
|
/* These are part of the standard DWARF line number state machine. */
|
||||||
|
|
||||||
unsigned char op_index;
|
unsigned char op_index;
|
||||||
|
/* The line table index (1-based) of the current file. */
|
||||||
unsigned int file;
|
unsigned int file;
|
||||||
unsigned int line;
|
unsigned int line;
|
||||||
CORE_ADDR address;
|
CORE_ADDR address;
|
||||||
|
@ -18085,7 +18120,7 @@ typedef struct
|
||||||
example, when discriminators are present. PR 17276. */
|
example, when discriminators are present. PR 17276. */
|
||||||
unsigned int last_line;
|
unsigned int last_line;
|
||||||
int line_has_non_zero_discriminator;
|
int line_has_non_zero_discriminator;
|
||||||
} lnp_state_machine;
|
};
|
||||||
|
|
||||||
/* There's a lot of static state to pass to dwarf_record_line.
|
/* There's a lot of static state to pass to dwarf_record_line.
|
||||||
This keeps it all together. */
|
This keeps it all together. */
|
||||||
|
@ -18211,10 +18246,9 @@ dwarf_record_line (lnp_reader_state *reader, lnp_state_machine *state,
|
||||||
int end_sequence)
|
int end_sequence)
|
||||||
{
|
{
|
||||||
const struct line_header *lh = reader->line_header;
|
const struct line_header *lh = reader->line_header;
|
||||||
unsigned int file, line, discriminator;
|
unsigned int line, discriminator;
|
||||||
int is_stmt;
|
int is_stmt;
|
||||||
|
|
||||||
file = state->file;
|
|
||||||
line = state->line;
|
line = state->line;
|
||||||
is_stmt = state->is_stmt;
|
is_stmt = state->is_stmt;
|
||||||
discriminator = state->discriminator;
|
discriminator = state->discriminator;
|
||||||
|
@ -18224,19 +18258,21 @@ dwarf_record_line (lnp_reader_state *reader, lnp_state_machine *state,
|
||||||
fprintf_unfiltered (gdb_stdlog,
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
"Processing actual line %u: file %u,"
|
"Processing actual line %u: file %u,"
|
||||||
" address %s, is_stmt %u, discrim %u\n",
|
" address %s, is_stmt %u, discrim %u\n",
|
||||||
line, file,
|
line, state->file,
|
||||||
paddress (reader->gdbarch, state->address),
|
paddress (reader->gdbarch, state->address),
|
||||||
is_stmt, discriminator);
|
is_stmt, discriminator);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file == 0 || file - 1 >= lh->num_file_names)
|
file_entry *fe = state->current_file ();
|
||||||
|
|
||||||
|
if (fe == NULL)
|
||||||
dwarf2_debug_line_missing_file_complaint ();
|
dwarf2_debug_line_missing_file_complaint ();
|
||||||
/* For now we ignore lines not starting on an instruction boundary.
|
/* For now we ignore lines not starting on an instruction boundary.
|
||||||
But not when processing end_sequence for compatibility with the
|
But not when processing end_sequence for compatibility with the
|
||||||
previous version of the code. */
|
previous version of the code. */
|
||||||
else if (state->op_index == 0 || end_sequence)
|
else if (state->op_index == 0 || end_sequence)
|
||||||
{
|
{
|
||||||
lh->file_names[file - 1].included_p = 1;
|
fe->included_p = 1;
|
||||||
if (reader->record_lines_p && is_stmt)
|
if (reader->record_lines_p && is_stmt)
|
||||||
{
|
{
|
||||||
if (state->last_subfile != current_subfile || end_sequence)
|
if (state->last_subfile != current_subfile || end_sequence)
|
||||||
|
@ -18290,6 +18326,7 @@ init_lnp_state_machine (lnp_state_machine *state,
|
||||||
state->address = gdbarch_adjust_dwarf2_line (reader->gdbarch, 0, 0);
|
state->address = gdbarch_adjust_dwarf2_line (reader->gdbarch, 0, 0);
|
||||||
state->is_stmt = reader->line_header->default_is_stmt;
|
state->is_stmt = reader->line_header->default_is_stmt;
|
||||||
state->discriminator = 0;
|
state->discriminator = 0;
|
||||||
|
state->the_line_header = reader->line_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check address and if invalid nop-out the rest of the lines in this
|
/* Check address and if invalid nop-out the rest of the lines in this
|
||||||
|
@ -18364,20 +18401,14 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
|
||||||
/* Reset the state machine at the start of each sequence. */
|
/* Reset the state machine at the start of each sequence. */
|
||||||
init_lnp_state_machine (&state_machine, &reader_state);
|
init_lnp_state_machine (&state_machine, &reader_state);
|
||||||
|
|
||||||
if (record_lines_p && lh->num_file_names >= state_machine.file)
|
if (record_lines_p)
|
||||||
{
|
{
|
||||||
/* Start a subfile for the current file of the state machine. */
|
/* Start a subfile for the current file of the state
|
||||||
/* lh->include_dirs and lh->file_names are 0-based, but the
|
machine. */
|
||||||
directory and file name numbers in the statement program
|
const file_entry *fe = state_machine.current_file ();
|
||||||
are 1-based. */
|
|
||||||
struct file_entry *fe = &lh->file_names[state_machine.file - 1];
|
|
||||||
const char *dir = NULL;
|
|
||||||
|
|
||||||
if (fe->dir_index && lh->include_dirs != NULL
|
if (fe != NULL)
|
||||||
&& (fe->dir_index - 1) < lh->num_include_dirs)
|
dwarf2_start_subfile (fe->name, fe->include_dir (lh));
|
||||||
dir = lh->include_dirs[fe->dir_index - 1];
|
|
||||||
|
|
||||||
dwarf2_start_subfile (fe->name, dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decode the table. */
|
/* Decode the table. */
|
||||||
|
@ -18522,26 +18553,19 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
|
||||||
break;
|
break;
|
||||||
case DW_LNS_set_file:
|
case DW_LNS_set_file:
|
||||||
{
|
{
|
||||||
/* The arrays lh->include_dirs and lh->file_names are
|
|
||||||
0-based, but the directory and file name numbers in
|
|
||||||
the statement program are 1-based. */
|
|
||||||
struct file_entry *fe;
|
|
||||||
const char *dir = NULL;
|
|
||||||
|
|
||||||
state_machine.file = read_unsigned_leb128 (abfd, line_ptr,
|
state_machine.file = read_unsigned_leb128 (abfd, line_ptr,
|
||||||
&bytes_read);
|
&bytes_read);
|
||||||
line_ptr += bytes_read;
|
line_ptr += bytes_read;
|
||||||
if (state_machine.file == 0
|
|
||||||
|| state_machine.file - 1 >= lh->num_file_names)
|
const file_entry *fe = state_machine.current_file ();
|
||||||
|
if (fe == NULL)
|
||||||
dwarf2_debug_line_missing_file_complaint ();
|
dwarf2_debug_line_missing_file_complaint ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fe = &lh->file_names[state_machine.file - 1];
|
|
||||||
if (fe->dir_index && lh->include_dirs != NULL
|
|
||||||
&& (fe->dir_index - 1) < lh->num_include_dirs)
|
|
||||||
dir = lh->include_dirs[fe->dir_index - 1];
|
|
||||||
if (record_lines_p)
|
if (record_lines_p)
|
||||||
{
|
{
|
||||||
|
const char *dir = fe->include_dir (lh);
|
||||||
|
|
||||||
state_machine.last_subfile = current_subfile;
|
state_machine.last_subfile = current_subfile;
|
||||||
state_machine.line_has_non_zero_discriminator
|
state_machine.line_has_non_zero_discriminator
|
||||||
= state_machine.discriminator != 0;
|
= state_machine.discriminator != 0;
|
||||||
|
@ -18676,21 +18700,16 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
|
||||||
|
|
||||||
for (i = 0; i < lh->num_file_names; i++)
|
for (i = 0; i < lh->num_file_names; i++)
|
||||||
{
|
{
|
||||||
const char *dir = NULL;
|
file_entry &fe = lh->file_names[i];
|
||||||
struct file_entry *fe;
|
|
||||||
|
|
||||||
fe = &lh->file_names[i];
|
dwarf2_start_subfile (fe.name, fe.include_dir (lh));
|
||||||
if (fe->dir_index && lh->include_dirs != NULL
|
|
||||||
&& (fe->dir_index - 1) < lh->num_include_dirs)
|
|
||||||
dir = lh->include_dirs[fe->dir_index - 1];
|
|
||||||
dwarf2_start_subfile (fe->name, dir);
|
|
||||||
|
|
||||||
if (current_subfile->symtab == NULL)
|
if (current_subfile->symtab == NULL)
|
||||||
{
|
{
|
||||||
current_subfile->symtab
|
current_subfile->symtab
|
||||||
= allocate_symtab (cust, current_subfile->name);
|
= allocate_symtab (cust, current_subfile->name);
|
||||||
}
|
}
|
||||||
fe->symtab = current_subfile->symtab;
|
fe.symtab = current_subfile->symtab;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18899,19 +18918,19 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
||||||
cu);
|
cu);
|
||||||
if (attr)
|
if (attr)
|
||||||
{
|
{
|
||||||
int file_index = DW_UNSND (attr);
|
unsigned int file_index = DW_UNSND (attr);
|
||||||
|
struct file_entry *fe;
|
||||||
|
|
||||||
if (cu->line_header == NULL
|
if (cu->line_header != NULL && file_index > 0)
|
||||||
|| file_index > cu->line_header->num_file_names)
|
fe = cu->line_header->file_name_at (file_index - 1);
|
||||||
|
else
|
||||||
|
fe = NULL;
|
||||||
|
|
||||||
|
if (fe == NULL)
|
||||||
complaint (&symfile_complaints,
|
complaint (&symfile_complaints,
|
||||||
_("file index out of range"));
|
_("file index out of range"));
|
||||||
else if (file_index > 0)
|
else
|
||||||
{
|
symbol_set_symtab (sym, fe->symtab);
|
||||||
struct file_entry *fe;
|
|
||||||
|
|
||||||
fe = &cu->line_header->file_names[file_index - 1];
|
|
||||||
symbol_set_symtab (sym, fe->symtab);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (die->tag)
|
switch (die->tag)
|
||||||
|
@ -21387,14 +21406,15 @@ file_file_name (int file, struct line_header *lh)
|
||||||
table? Remember that file numbers start with one, not zero. */
|
table? Remember that file numbers start with one, not zero. */
|
||||||
if (1 <= file && file <= lh->num_file_names)
|
if (1 <= file && file <= lh->num_file_names)
|
||||||
{
|
{
|
||||||
struct file_entry *fe = &lh->file_names[file - 1];
|
const file_entry &fe = lh->file_names[file - 1];
|
||||||
|
|
||||||
if (IS_ABSOLUTE_PATH (fe->name) || fe->dir_index == 0
|
if (!IS_ABSOLUTE_PATH (fe.name))
|
||||||
|| lh->include_dirs == NULL
|
{
|
||||||
|| (fe->dir_index - 1) >= lh->num_include_dirs)
|
const char *dir = fe.include_dir (lh);
|
||||||
return xstrdup (fe->name);
|
if (dir != NULL)
|
||||||
return concat (lh->include_dirs[fe->dir_index - 1], SLASH_STRING,
|
return concat (dir, SLASH_STRING, fe.name, (char *) NULL);
|
||||||
fe->name, (char *) NULL);
|
}
|
||||||
|
return xstrdup (fe.name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue