Move code to new file dwarf2/macro.c
This moves some more code out of dwarf2/read.c, introducing new files dwarf2/macro.c and dwarf2/macro.h. gdb/ChangeLog 2020-03-26 Tom Tromey <tom@tromey.com> * dwarf2/read.c (dwarf2_macro_malformed_definition_complaint) (macro_start_file, consume_improper_spaces) (parse_macro_definition, skip_form_bytes, skip_unknown_opcode) (dwarf_parse_macro_header, dwarf_decode_macro_bytes) (dwarf_decode_macros): Move to macro.c. * dwarf2/macro.c: New file. * dwarf2/macro.h: New file. * Makefile.in (COMMON_SFILES): Add dwarf2/macro.c.
This commit is contained in:
parent
4f44ae6c69
commit
c90ec28ae4
|
@ -1,3 +1,14 @@
|
|||
2020-03-26 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* dwarf2/read.c (dwarf2_macro_malformed_definition_complaint)
|
||||
(macro_start_file, consume_improper_spaces)
|
||||
(parse_macro_definition, skip_form_bytes, skip_unknown_opcode)
|
||||
(dwarf_parse_macro_header, dwarf_decode_macro_bytes)
|
||||
(dwarf_decode_macros): Move to macro.c.
|
||||
* dwarf2/macro.c: New file.
|
||||
* dwarf2/macro.h: New file.
|
||||
* Makefile.in (COMMON_SFILES): Add dwarf2/macro.c.
|
||||
|
||||
2020-03-26 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* dwarf2/section.h (struct dwarf2_section_info) <read_string>: New
|
||||
|
|
|
@ -1013,6 +1013,7 @@ COMMON_SFILES = \
|
|||
dwarf2/leb.c \
|
||||
dwarf2/line-header.c \
|
||||
dwarf2/loc.c \
|
||||
dwarf2/macro.c \
|
||||
dwarf2/read.c \
|
||||
dwarf2/section.c \
|
||||
eval.c \
|
||||
|
|
|
@ -0,0 +1,867 @@
|
|||
/* Read DWARF macro information
|
||||
|
||||
Copyright (C) 1994-2020 Free Software Foundation, Inc.
|
||||
|
||||
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
|
||||
Inc. with support from Florida State University (under contract
|
||||
with the Ada Joint Program Office), and Silicon Graphics, Inc.
|
||||
Initial contribution by Brent Benson, Harris Computer Systems, Inc.,
|
||||
based on Fred Fish's (Cygnus Support) implementation of DWARF 1
|
||||
support.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "dwarf2/read.h"
|
||||
#include "dwarf2/leb.h"
|
||||
#include "dwarf2/expr.h"
|
||||
#include "dwarf2/line-header.h"
|
||||
#include "dwarf2/section.h"
|
||||
#include "dwarf2/macro.h"
|
||||
#include "dwarf2/dwz.h"
|
||||
#include "buildsym.h"
|
||||
#include "macrotab.h"
|
||||
#include "complaints.h"
|
||||
|
||||
static void
|
||||
dwarf2_macro_malformed_definition_complaint (const char *arg1)
|
||||
{
|
||||
complaint (_("macro debug info contains a "
|
||||
"malformed macro definition:\n`%s'"),
|
||||
arg1);
|
||||
}
|
||||
|
||||
static struct macro_source_file *
|
||||
macro_start_file (buildsym_compunit *builder,
|
||||
int file, int line,
|
||||
struct macro_source_file *current_file,
|
||||
struct line_header *lh)
|
||||
{
|
||||
/* File name relative to the compilation directory of this source file. */
|
||||
gdb::unique_xmalloc_ptr<char> file_name = lh->file_file_name (file);
|
||||
|
||||
if (! current_file)
|
||||
{
|
||||
/* Note: We don't create a macro table for this compilation unit
|
||||
at all until we actually get a filename. */
|
||||
struct macro_table *macro_table = builder->get_macro_table ();
|
||||
|
||||
/* If we have no current file, then this must be the start_file
|
||||
directive for the compilation unit's main source file. */
|
||||
current_file = macro_set_main (macro_table, file_name.get ());
|
||||
macro_define_special (macro_table);
|
||||
}
|
||||
else
|
||||
current_file = macro_include (current_file, line, file_name.get ());
|
||||
|
||||
return current_file;
|
||||
}
|
||||
|
||||
static const char *
|
||||
consume_improper_spaces (const char *p, const char *body)
|
||||
{
|
||||
if (*p == ' ')
|
||||
{
|
||||
complaint (_("macro definition contains spaces "
|
||||
"in formal argument list:\n`%s'"),
|
||||
body);
|
||||
|
||||
while (*p == ' ')
|
||||
p++;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_macro_definition (struct macro_source_file *file, int line,
|
||||
const char *body)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
/* The body string takes one of two forms. For object-like macro
|
||||
definitions, it should be:
|
||||
|
||||
<macro name> " " <definition>
|
||||
|
||||
For function-like macro definitions, it should be:
|
||||
|
||||
<macro name> "() " <definition>
|
||||
or
|
||||
<macro name> "(" <arg name> ( "," <arg name> ) * ") " <definition>
|
||||
|
||||
Spaces may appear only where explicitly indicated, and in the
|
||||
<definition>.
|
||||
|
||||
The Dwarf 2 spec says that an object-like macro's name is always
|
||||
followed by a space, but versions of GCC around March 2002 omit
|
||||
the space when the macro's definition is the empty string.
|
||||
|
||||
The Dwarf 2 spec says that there should be no spaces between the
|
||||
formal arguments in a function-like macro's formal argument list,
|
||||
but versions of GCC around March 2002 include spaces after the
|
||||
commas. */
|
||||
|
||||
|
||||
/* Find the extent of the macro name. The macro name is terminated
|
||||
by either a space or null character (for an object-like macro) or
|
||||
an opening paren (for a function-like macro). */
|
||||
for (p = body; *p; p++)
|
||||
if (*p == ' ' || *p == '(')
|
||||
break;
|
||||
|
||||
if (*p == ' ' || *p == '\0')
|
||||
{
|
||||
/* It's an object-like macro. */
|
||||
int name_len = p - body;
|
||||
std::string name (body, name_len);
|
||||
const char *replacement;
|
||||
|
||||
if (*p == ' ')
|
||||
replacement = body + name_len + 1;
|
||||
else
|
||||
{
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
replacement = body + name_len;
|
||||
}
|
||||
|
||||
macro_define_object (file, line, name.c_str (), replacement);
|
||||
}
|
||||
else if (*p == '(')
|
||||
{
|
||||
/* It's a function-like macro. */
|
||||
std::string name (body, p - body);
|
||||
int argc = 0;
|
||||
int argv_size = 1;
|
||||
char **argv = XNEWVEC (char *, argv_size);
|
||||
|
||||
p++;
|
||||
|
||||
p = consume_improper_spaces (p, body);
|
||||
|
||||
/* Parse the formal argument list. */
|
||||
while (*p && *p != ')')
|
||||
{
|
||||
/* Find the extent of the current argument name. */
|
||||
const char *arg_start = p;
|
||||
|
||||
while (*p && *p != ',' && *p != ')' && *p != ' ')
|
||||
p++;
|
||||
|
||||
if (! *p || p == arg_start)
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
else
|
||||
{
|
||||
/* Make sure argv has room for the new argument. */
|
||||
if (argc >= argv_size)
|
||||
{
|
||||
argv_size *= 2;
|
||||
argv = XRESIZEVEC (char *, argv, argv_size);
|
||||
}
|
||||
|
||||
argv[argc++] = savestring (arg_start, p - arg_start);
|
||||
}
|
||||
|
||||
p = consume_improper_spaces (p, body);
|
||||
|
||||
/* Consume the comma, if present. */
|
||||
if (*p == ',')
|
||||
{
|
||||
p++;
|
||||
|
||||
p = consume_improper_spaces (p, body);
|
||||
}
|
||||
}
|
||||
|
||||
if (*p == ')')
|
||||
{
|
||||
p++;
|
||||
|
||||
if (*p == ' ')
|
||||
/* Perfectly formed definition, no complaints. */
|
||||
macro_define_function (file, line, name.c_str (),
|
||||
argc, (const char **) argv,
|
||||
p + 1);
|
||||
else if (*p == '\0')
|
||||
{
|
||||
/* Complain, but do define it. */
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
macro_define_function (file, line, name.c_str (),
|
||||
argc, (const char **) argv,
|
||||
p);
|
||||
}
|
||||
else
|
||||
/* Just complain. */
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
}
|
||||
else
|
||||
/* Just complain. */
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
xfree (argv[i]);
|
||||
}
|
||||
xfree (argv);
|
||||
}
|
||||
else
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
}
|
||||
|
||||
/* Skip some bytes from BYTES according to the form given in FORM.
|
||||
Returns the new pointer. */
|
||||
|
||||
static const gdb_byte *
|
||||
skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
|
||||
enum dwarf_form form,
|
||||
unsigned int offset_size,
|
||||
struct dwarf2_section_info *section)
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
|
||||
switch (form)
|
||||
{
|
||||
case DW_FORM_data1:
|
||||
case DW_FORM_flag:
|
||||
++bytes;
|
||||
break;
|
||||
|
||||
case DW_FORM_data2:
|
||||
bytes += 2;
|
||||
break;
|
||||
|
||||
case DW_FORM_data4:
|
||||
bytes += 4;
|
||||
break;
|
||||
|
||||
case DW_FORM_data8:
|
||||
bytes += 8;
|
||||
break;
|
||||
|
||||
case DW_FORM_data16:
|
||||
bytes += 16;
|
||||
break;
|
||||
|
||||
case DW_FORM_string:
|
||||
read_direct_string (abfd, bytes, &bytes_read);
|
||||
bytes += bytes_read;
|
||||
break;
|
||||
|
||||
case DW_FORM_sec_offset:
|
||||
case DW_FORM_strp:
|
||||
case DW_FORM_GNU_strp_alt:
|
||||
bytes += offset_size;
|
||||
break;
|
||||
|
||||
case DW_FORM_block:
|
||||
bytes += read_unsigned_leb128 (abfd, bytes, &bytes_read);
|
||||
bytes += bytes_read;
|
||||
break;
|
||||
|
||||
case DW_FORM_block1:
|
||||
bytes += 1 + read_1_byte (abfd, bytes);
|
||||
break;
|
||||
case DW_FORM_block2:
|
||||
bytes += 2 + read_2_bytes (abfd, bytes);
|
||||
break;
|
||||
case DW_FORM_block4:
|
||||
bytes += 4 + read_4_bytes (abfd, bytes);
|
||||
break;
|
||||
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_sdata:
|
||||
case DW_FORM_strx:
|
||||
case DW_FORM_udata:
|
||||
case DW_FORM_GNU_addr_index:
|
||||
case DW_FORM_GNU_str_index:
|
||||
bytes = gdb_skip_leb128 (bytes, buffer_end);
|
||||
if (bytes == NULL)
|
||||
{
|
||||
section->overflow_complaint ();
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_FORM_implicit_const:
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
complaint (_("invalid form 0x%x in `%s'"),
|
||||
form, section->get_name ());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* A helper for dwarf_decode_macros that handles skipping an unknown
|
||||
opcode. Returns an updated pointer to the macro data buffer; or,
|
||||
on error, issues a complaint and returns NULL. */
|
||||
|
||||
static const gdb_byte *
|
||||
skip_unknown_opcode (unsigned int opcode,
|
||||
const gdb_byte **opcode_definitions,
|
||||
const gdb_byte *mac_ptr, const gdb_byte *mac_end,
|
||||
bfd *abfd,
|
||||
unsigned int offset_size,
|
||||
struct dwarf2_section_info *section)
|
||||
{
|
||||
unsigned int bytes_read, i;
|
||||
unsigned long arg;
|
||||
const gdb_byte *defn;
|
||||
|
||||
if (opcode_definitions[opcode] == NULL)
|
||||
{
|
||||
complaint (_("unrecognized DW_MACFINO opcode 0x%x"),
|
||||
opcode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
defn = opcode_definitions[opcode];
|
||||
arg = read_unsigned_leb128 (abfd, defn, &bytes_read);
|
||||
defn += bytes_read;
|
||||
|
||||
for (i = 0; i < arg; ++i)
|
||||
{
|
||||
mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end,
|
||||
(enum dwarf_form) defn[i], offset_size,
|
||||
section);
|
||||
if (mac_ptr == NULL)
|
||||
{
|
||||
/* skip_form_bytes already issued the complaint. */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return mac_ptr;
|
||||
}
|
||||
|
||||
/* A helper function which parses the header of a macro section.
|
||||
If the macro section is the extended (for now called "GNU") type,
|
||||
then this updates *OFFSET_SIZE. Returns a pointer to just after
|
||||
the header, or issues a complaint and returns NULL on error. */
|
||||
|
||||
static const gdb_byte *
|
||||
dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
|
||||
bfd *abfd,
|
||||
const gdb_byte *mac_ptr,
|
||||
unsigned int *offset_size,
|
||||
int section_is_gnu)
|
||||
{
|
||||
memset (opcode_definitions, 0, 256 * sizeof (gdb_byte *));
|
||||
|
||||
if (section_is_gnu)
|
||||
{
|
||||
unsigned int version, flags;
|
||||
|
||||
version = read_2_bytes (abfd, mac_ptr);
|
||||
if (version != 4 && version != 5)
|
||||
{
|
||||
complaint (_("unrecognized version `%d' in .debug_macro section"),
|
||||
version);
|
||||
return NULL;
|
||||
}
|
||||
mac_ptr += 2;
|
||||
|
||||
flags = read_1_byte (abfd, mac_ptr);
|
||||
++mac_ptr;
|
||||
*offset_size = (flags & 1) ? 8 : 4;
|
||||
|
||||
if ((flags & 2) != 0)
|
||||
/* We don't need the line table offset. */
|
||||
mac_ptr += *offset_size;
|
||||
|
||||
/* Vendor opcode descriptions. */
|
||||
if ((flags & 4) != 0)
|
||||
{
|
||||
unsigned int i, count;
|
||||
|
||||
count = read_1_byte (abfd, mac_ptr);
|
||||
++mac_ptr;
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
unsigned int opcode, bytes_read;
|
||||
unsigned long arg;
|
||||
|
||||
opcode = read_1_byte (abfd, mac_ptr);
|
||||
++mac_ptr;
|
||||
opcode_definitions[opcode] = mac_ptr;
|
||||
arg = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
mac_ptr += arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mac_ptr;
|
||||
}
|
||||
|
||||
/* A helper for dwarf_decode_macros that handles the GNU extensions,
|
||||
including DW_MACRO_import. */
|
||||
|
||||
static void
|
||||
dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
buildsym_compunit *builder,
|
||||
bfd *abfd,
|
||||
const gdb_byte *mac_ptr, const gdb_byte *mac_end,
|
||||
struct macro_source_file *current_file,
|
||||
struct line_header *lh,
|
||||
struct dwarf2_section_info *section,
|
||||
int section_is_gnu, int section_is_dwz,
|
||||
unsigned int offset_size,
|
||||
htab_t include_hash)
|
||||
{
|
||||
struct objfile *objfile = dwarf2_per_objfile->objfile;
|
||||
enum dwarf_macro_record_type macinfo_type;
|
||||
int at_commandline;
|
||||
const gdb_byte *opcode_definitions[256];
|
||||
|
||||
mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
|
||||
&offset_size, section_is_gnu);
|
||||
if (mac_ptr == NULL)
|
||||
{
|
||||
/* We already issued a complaint. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determines if GDB is still before first DW_MACINFO_start_file. If true
|
||||
GDB is still reading the definitions from command line. First
|
||||
DW_MACINFO_start_file will need to be ignored as it was already executed
|
||||
to create CURRENT_FILE for the main source holding also the command line
|
||||
definitions. On first met DW_MACINFO_start_file this flag is reset to
|
||||
normally execute all the remaining DW_MACINFO_start_file macinfos. */
|
||||
|
||||
at_commandline = 1;
|
||||
|
||||
do
|
||||
{
|
||||
/* Do we at least have room for a macinfo type byte? */
|
||||
if (mac_ptr >= mac_end)
|
||||
{
|
||||
section->overflow_complaint ();
|
||||
break;
|
||||
}
|
||||
|
||||
macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
|
||||
mac_ptr++;
|
||||
|
||||
/* Note that we rely on the fact that the corresponding GNU and
|
||||
DWARF constants are the same. */
|
||||
DIAGNOSTIC_PUSH
|
||||
DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
|
||||
switch (macinfo_type)
|
||||
{
|
||||
/* A zero macinfo type indicates the end of the macro
|
||||
information. */
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case DW_MACRO_define:
|
||||
case DW_MACRO_undef:
|
||||
case DW_MACRO_define_strp:
|
||||
case DW_MACRO_undef_strp:
|
||||
case DW_MACRO_define_sup:
|
||||
case DW_MACRO_undef_sup:
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
int line;
|
||||
const char *body;
|
||||
int is_define;
|
||||
|
||||
line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
|
||||
if (macinfo_type == DW_MACRO_define
|
||||
|| macinfo_type == DW_MACRO_undef)
|
||||
{
|
||||
body = read_direct_string (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
}
|
||||
else
|
||||
{
|
||||
LONGEST str_offset;
|
||||
|
||||
str_offset = read_offset (abfd, mac_ptr, offset_size);
|
||||
mac_ptr += offset_size;
|
||||
|
||||
if (macinfo_type == DW_MACRO_define_sup
|
||||
|| macinfo_type == DW_MACRO_undef_sup
|
||||
|| section_is_dwz)
|
||||
{
|
||||
struct dwz_file *dwz
|
||||
= dwarf2_get_dwz_file (dwarf2_per_objfile);
|
||||
|
||||
body = dwz->read_string (objfile, str_offset);
|
||||
}
|
||||
else
|
||||
body = (dwarf2_per_objfile->str.read_string
|
||||
(dwarf2_per_objfile->objfile,
|
||||
str_offset, "DW_FORM_strp"));
|
||||
}
|
||||
|
||||
is_define = (macinfo_type == DW_MACRO_define
|
||||
|| macinfo_type == DW_MACRO_define_strp
|
||||
|| macinfo_type == DW_MACRO_define_sup);
|
||||
if (! current_file)
|
||||
{
|
||||
/* DWARF violation as no main source is present. */
|
||||
complaint (_("debug info with no main source gives macro %s "
|
||||
"on line %d: %s"),
|
||||
is_define ? _("definition") : _("undefinition"),
|
||||
line, body);
|
||||
break;
|
||||
}
|
||||
if ((line == 0 && !at_commandline)
|
||||
|| (line != 0 && at_commandline))
|
||||
complaint (_("debug info gives %s macro %s with %s line %d: %s"),
|
||||
at_commandline ? _("command-line") : _("in-file"),
|
||||
is_define ? _("definition") : _("undefinition"),
|
||||
line == 0 ? _("zero") : _("non-zero"), line, body);
|
||||
|
||||
if (body == NULL)
|
||||
{
|
||||
/* Fedora's rpm-build's "debugedit" binary
|
||||
corrupted .debug_macro sections.
|
||||
|
||||
For more info, see
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1708786 */
|
||||
complaint (_("debug info gives %s invalid macro %s "
|
||||
"without body (corrupted?) at line %d "
|
||||
"on file %s"),
|
||||
at_commandline ? _("command-line") : _("in-file"),
|
||||
is_define ? _("definition") : _("undefinition"),
|
||||
line, current_file->filename);
|
||||
}
|
||||
else if (is_define)
|
||||
parse_macro_definition (current_file, line, body);
|
||||
else
|
||||
{
|
||||
gdb_assert (macinfo_type == DW_MACRO_undef
|
||||
|| macinfo_type == DW_MACRO_undef_strp
|
||||
|| macinfo_type == DW_MACRO_undef_sup);
|
||||
macro_undef (current_file, line, body);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_start_file:
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
int line, file;
|
||||
|
||||
line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
|
||||
if ((line == 0 && !at_commandline)
|
||||
|| (line != 0 && at_commandline))
|
||||
complaint (_("debug info gives source %d included "
|
||||
"from %s at %s line %d"),
|
||||
file, at_commandline ? _("command-line") : _("file"),
|
||||
line == 0 ? _("zero") : _("non-zero"), line);
|
||||
|
||||
if (at_commandline)
|
||||
{
|
||||
/* This DW_MACRO_start_file was executed in the
|
||||
pass one. */
|
||||
at_commandline = 0;
|
||||
}
|
||||
else
|
||||
current_file = macro_start_file (builder, file, line,
|
||||
current_file, lh);
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_end_file:
|
||||
if (! current_file)
|
||||
complaint (_("macro debug info has an unmatched "
|
||||
"`close_file' directive"));
|
||||
else
|
||||
{
|
||||
current_file = current_file->included_by;
|
||||
if (! current_file)
|
||||
{
|
||||
enum dwarf_macro_record_type next_type;
|
||||
|
||||
/* GCC circa March 2002 doesn't produce the zero
|
||||
type byte marking the end of the compilation
|
||||
unit. Complain if it's not there, but exit no
|
||||
matter what. */
|
||||
|
||||
/* Do we at least have room for a macinfo type byte? */
|
||||
if (mac_ptr >= mac_end)
|
||||
{
|
||||
section->overflow_complaint ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* We don't increment mac_ptr here, so this is just
|
||||
a look-ahead. */
|
||||
next_type
|
||||
= (enum dwarf_macro_record_type) read_1_byte (abfd,
|
||||
mac_ptr);
|
||||
if (next_type != 0)
|
||||
complaint (_("no terminating 0-type entry for "
|
||||
"macros in `.debug_macinfo' section"));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_import:
|
||||
case DW_MACRO_import_sup:
|
||||
{
|
||||
LONGEST offset;
|
||||
void **slot;
|
||||
bfd *include_bfd = abfd;
|
||||
struct dwarf2_section_info *include_section = section;
|
||||
const gdb_byte *include_mac_end = mac_end;
|
||||
int is_dwz = section_is_dwz;
|
||||
const gdb_byte *new_mac_ptr;
|
||||
|
||||
offset = read_offset (abfd, mac_ptr, offset_size);
|
||||
mac_ptr += offset_size;
|
||||
|
||||
if (macinfo_type == DW_MACRO_import_sup)
|
||||
{
|
||||
struct dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
|
||||
|
||||
dwz->macro.read (objfile);
|
||||
|
||||
include_section = &dwz->macro;
|
||||
include_bfd = include_section->get_bfd_owner ();
|
||||
include_mac_end = dwz->macro.buffer + dwz->macro.size;
|
||||
is_dwz = 1;
|
||||
}
|
||||
|
||||
new_mac_ptr = include_section->buffer + offset;
|
||||
slot = htab_find_slot (include_hash, new_mac_ptr, INSERT);
|
||||
|
||||
if (*slot != NULL)
|
||||
{
|
||||
/* This has actually happened; see
|
||||
http://sourceware.org/bugzilla/show_bug.cgi?id=13568. */
|
||||
complaint (_("recursive DW_MACRO_import in "
|
||||
".debug_macro section"));
|
||||
}
|
||||
else
|
||||
{
|
||||
*slot = (void *) new_mac_ptr;
|
||||
|
||||
dwarf_decode_macro_bytes (dwarf2_per_objfile, builder,
|
||||
include_bfd, new_mac_ptr,
|
||||
include_mac_end, current_file, lh,
|
||||
section, section_is_gnu, is_dwz,
|
||||
offset_size, include_hash);
|
||||
|
||||
htab_remove_elt (include_hash, (void *) new_mac_ptr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACINFO_vendor_ext:
|
||||
if (!section_is_gnu)
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
|
||||
/* This reads the constant, but since we don't recognize
|
||||
any vendor extensions, we ignore it. */
|
||||
read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
read_direct_string (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
|
||||
/* We don't recognize any vendor extensions. */
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
|
||||
mac_ptr, mac_end, abfd, offset_size,
|
||||
section);
|
||||
if (mac_ptr == NULL)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
DIAGNOSTIC_POP
|
||||
} while (macinfo_type != 0);
|
||||
}
|
||||
|
||||
void
|
||||
dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
buildsym_compunit *builder, dwarf2_section_info *section,
|
||||
struct line_header *lh, unsigned int offset_size,
|
||||
unsigned int offset, int section_is_gnu)
|
||||
{
|
||||
bfd *abfd;
|
||||
const gdb_byte *mac_ptr, *mac_end;
|
||||
struct macro_source_file *current_file = 0;
|
||||
enum dwarf_macro_record_type macinfo_type;
|
||||
const gdb_byte *opcode_definitions[256];
|
||||
void **slot;
|
||||
|
||||
abfd = section->get_bfd_owner ();
|
||||
|
||||
/* First pass: Find the name of the base filename.
|
||||
This filename is needed in order to process all macros whose definition
|
||||
(or undefinition) comes from the command line. These macros are defined
|
||||
before the first DW_MACINFO_start_file entry, and yet still need to be
|
||||
associated to the base file.
|
||||
|
||||
To determine the base file name, we scan the macro definitions until we
|
||||
reach the first DW_MACINFO_start_file entry. We then initialize
|
||||
CURRENT_FILE accordingly so that any macro definition found before the
|
||||
first DW_MACINFO_start_file can still be associated to the base file. */
|
||||
|
||||
mac_ptr = section->buffer + offset;
|
||||
mac_end = section->buffer + section->size;
|
||||
|
||||
mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
|
||||
&offset_size, section_is_gnu);
|
||||
if (mac_ptr == NULL)
|
||||
{
|
||||
/* We already issued a complaint. */
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* Do we at least have room for a macinfo type byte? */
|
||||
if (mac_ptr >= mac_end)
|
||||
{
|
||||
/* Complaint is printed during the second pass as GDB will probably
|
||||
stop the first pass earlier upon finding
|
||||
DW_MACINFO_start_file. */
|
||||
break;
|
||||
}
|
||||
|
||||
macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
|
||||
mac_ptr++;
|
||||
|
||||
/* Note that we rely on the fact that the corresponding GNU and
|
||||
DWARF constants are the same. */
|
||||
DIAGNOSTIC_PUSH
|
||||
DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
|
||||
switch (macinfo_type)
|
||||
{
|
||||
/* A zero macinfo type indicates the end of the macro
|
||||
information. */
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case DW_MACRO_define:
|
||||
case DW_MACRO_undef:
|
||||
/* Only skip the data by MAC_PTR. */
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
|
||||
read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
read_direct_string (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_start_file:
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
int line, file;
|
||||
|
||||
line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
|
||||
current_file = macro_start_file (builder, file, line,
|
||||
current_file, lh);
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_end_file:
|
||||
/* No data to skip by MAC_PTR. */
|
||||
break;
|
||||
|
||||
case DW_MACRO_define_strp:
|
||||
case DW_MACRO_undef_strp:
|
||||
case DW_MACRO_define_sup:
|
||||
case DW_MACRO_undef_sup:
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
|
||||
read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
mac_ptr += offset_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_import:
|
||||
case DW_MACRO_import_sup:
|
||||
/* Note that, according to the spec, a transparent include
|
||||
chain cannot call DW_MACRO_start_file. So, we can just
|
||||
skip this opcode. */
|
||||
mac_ptr += offset_size;
|
||||
break;
|
||||
|
||||
case DW_MACINFO_vendor_ext:
|
||||
/* Only skip the data by MAC_PTR. */
|
||||
if (!section_is_gnu)
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
|
||||
read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
read_direct_string (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
|
||||
mac_ptr, mac_end, abfd, offset_size,
|
||||
section);
|
||||
if (mac_ptr == NULL)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
DIAGNOSTIC_POP
|
||||
} while (macinfo_type != 0 && current_file == NULL);
|
||||
|
||||
/* Second pass: Process all entries.
|
||||
|
||||
Use the AT_COMMAND_LINE flag to determine whether we are still processing
|
||||
command-line macro definitions/undefinitions. This flag is unset when we
|
||||
reach the first DW_MACINFO_start_file entry. */
|
||||
|
||||
htab_up include_hash (htab_create_alloc (1, htab_hash_pointer,
|
||||
htab_eq_pointer,
|
||||
NULL, xcalloc, xfree));
|
||||
mac_ptr = section->buffer + offset;
|
||||
slot = htab_find_slot (include_hash.get (), mac_ptr, INSERT);
|
||||
*slot = (void *) mac_ptr;
|
||||
dwarf_decode_macro_bytes (dwarf2_per_objfile, builder,
|
||||
abfd, mac_ptr, mac_end,
|
||||
current_file, lh, section,
|
||||
section_is_gnu, 0, offset_size,
|
||||
include_hash.get ());
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* DWARF macro support for GDB.
|
||||
|
||||
Copyright (C) 2003-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GDB_DWARF2_MACRO_H
|
||||
#define GDB_DWARF2_MACRO_H
|
||||
|
||||
struct buildsym_compunit;
|
||||
|
||||
extern void dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
buildsym_compunit *builder,
|
||||
dwarf2_section_info *section,
|
||||
struct line_header *lh,
|
||||
unsigned int offset_size,
|
||||
unsigned int offset,
|
||||
int section_is_gnu);
|
||||
|
||||
#endif /* GDB_DWARF2_MACRO_H */
|
|
@ -38,6 +38,7 @@
|
|||
#include "dwarf2/leb.h"
|
||||
#include "dwarf2/line-header.h"
|
||||
#include "dwarf2/dwz.h"
|
||||
#include "dwarf2/macro.h"
|
||||
#include "bfd.h"
|
||||
#include "elf-bfd.h"
|
||||
#include "symtab.h"
|
||||
|
@ -48,7 +49,6 @@
|
|||
#include "demangle.h"
|
||||
#include "gdb-demangle.h"
|
||||
#include "filenames.h" /* for DOSish file names */
|
||||
#include "macrotab.h"
|
||||
#include "language.h"
|
||||
#include "complaints.h"
|
||||
#include "dwarf2/expr.h"
|
||||
|
@ -1710,14 +1710,6 @@ dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
|
|||
arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
static void
|
||||
dwarf2_macro_malformed_definition_complaint (const char *arg1)
|
||||
{
|
||||
complaint (_("macro debug info contains a "
|
||||
"malformed macro definition:\n`%s'"),
|
||||
arg1);
|
||||
}
|
||||
|
||||
static void
|
||||
dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
|
||||
{
|
||||
|
@ -23040,829 +23032,9 @@ dwarf_alloc_die (struct dwarf2_cu *cu, int num_attrs)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* Macro support. */
|
||||
|
||||
static struct macro_source_file *
|
||||
macro_start_file (buildsym_compunit *builder,
|
||||
int file, int line,
|
||||
struct macro_source_file *current_file,
|
||||
struct line_header *lh)
|
||||
{
|
||||
/* File name relative to the compilation directory of this source file. */
|
||||
gdb::unique_xmalloc_ptr<char> file_name = lh->file_file_name (file);
|
||||
|
||||
if (! current_file)
|
||||
{
|
||||
/* Note: We don't create a macro table for this compilation unit
|
||||
at all until we actually get a filename. */
|
||||
struct macro_table *macro_table = builder->get_macro_table ();
|
||||
|
||||
/* If we have no current file, then this must be the start_file
|
||||
directive for the compilation unit's main source file. */
|
||||
current_file = macro_set_main (macro_table, file_name.get ());
|
||||
macro_define_special (macro_table);
|
||||
}
|
||||
else
|
||||
current_file = macro_include (current_file, line, file_name.get ());
|
||||
|
||||
return current_file;
|
||||
}
|
||||
|
||||
static const char *
|
||||
consume_improper_spaces (const char *p, const char *body)
|
||||
{
|
||||
if (*p == ' ')
|
||||
{
|
||||
complaint (_("macro definition contains spaces "
|
||||
"in formal argument list:\n`%s'"),
|
||||
body);
|
||||
|
||||
while (*p == ' ')
|
||||
p++;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_macro_definition (struct macro_source_file *file, int line,
|
||||
const char *body)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
/* The body string takes one of two forms. For object-like macro
|
||||
definitions, it should be:
|
||||
|
||||
<macro name> " " <definition>
|
||||
|
||||
For function-like macro definitions, it should be:
|
||||
|
||||
<macro name> "() " <definition>
|
||||
or
|
||||
<macro name> "(" <arg name> ( "," <arg name> ) * ") " <definition>
|
||||
|
||||
Spaces may appear only where explicitly indicated, and in the
|
||||
<definition>.
|
||||
|
||||
The Dwarf 2 spec says that an object-like macro's name is always
|
||||
followed by a space, but versions of GCC around March 2002 omit
|
||||
the space when the macro's definition is the empty string.
|
||||
|
||||
The Dwarf 2 spec says that there should be no spaces between the
|
||||
formal arguments in a function-like macro's formal argument list,
|
||||
but versions of GCC around March 2002 include spaces after the
|
||||
commas. */
|
||||
|
||||
|
||||
/* Find the extent of the macro name. The macro name is terminated
|
||||
by either a space or null character (for an object-like macro) or
|
||||
an opening paren (for a function-like macro). */
|
||||
for (p = body; *p; p++)
|
||||
if (*p == ' ' || *p == '(')
|
||||
break;
|
||||
|
||||
if (*p == ' ' || *p == '\0')
|
||||
{
|
||||
/* It's an object-like macro. */
|
||||
int name_len = p - body;
|
||||
std::string name (body, name_len);
|
||||
const char *replacement;
|
||||
|
||||
if (*p == ' ')
|
||||
replacement = body + name_len + 1;
|
||||
else
|
||||
{
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
replacement = body + name_len;
|
||||
}
|
||||
|
||||
macro_define_object (file, line, name.c_str (), replacement);
|
||||
}
|
||||
else if (*p == '(')
|
||||
{
|
||||
/* It's a function-like macro. */
|
||||
std::string name (body, p - body);
|
||||
int argc = 0;
|
||||
int argv_size = 1;
|
||||
char **argv = XNEWVEC (char *, argv_size);
|
||||
|
||||
p++;
|
||||
|
||||
p = consume_improper_spaces (p, body);
|
||||
|
||||
/* Parse the formal argument list. */
|
||||
while (*p && *p != ')')
|
||||
{
|
||||
/* Find the extent of the current argument name. */
|
||||
const char *arg_start = p;
|
||||
|
||||
while (*p && *p != ',' && *p != ')' && *p != ' ')
|
||||
p++;
|
||||
|
||||
if (! *p || p == arg_start)
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
else
|
||||
{
|
||||
/* Make sure argv has room for the new argument. */
|
||||
if (argc >= argv_size)
|
||||
{
|
||||
argv_size *= 2;
|
||||
argv = XRESIZEVEC (char *, argv, argv_size);
|
||||
}
|
||||
|
||||
argv[argc++] = savestring (arg_start, p - arg_start);
|
||||
}
|
||||
|
||||
p = consume_improper_spaces (p, body);
|
||||
|
||||
/* Consume the comma, if present. */
|
||||
if (*p == ',')
|
||||
{
|
||||
p++;
|
||||
|
||||
p = consume_improper_spaces (p, body);
|
||||
}
|
||||
}
|
||||
|
||||
if (*p == ')')
|
||||
{
|
||||
p++;
|
||||
|
||||
if (*p == ' ')
|
||||
/* Perfectly formed definition, no complaints. */
|
||||
macro_define_function (file, line, name.c_str (),
|
||||
argc, (const char **) argv,
|
||||
p + 1);
|
||||
else if (*p == '\0')
|
||||
{
|
||||
/* Complain, but do define it. */
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
macro_define_function (file, line, name.c_str (),
|
||||
argc, (const char **) argv,
|
||||
p);
|
||||
}
|
||||
else
|
||||
/* Just complain. */
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
}
|
||||
else
|
||||
/* Just complain. */
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
xfree (argv[i]);
|
||||
}
|
||||
xfree (argv);
|
||||
}
|
||||
else
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
}
|
||||
|
||||
/* Skip some bytes from BYTES according to the form given in FORM.
|
||||
Returns the new pointer. */
|
||||
|
||||
static const gdb_byte *
|
||||
skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
|
||||
enum dwarf_form form,
|
||||
unsigned int offset_size,
|
||||
struct dwarf2_section_info *section)
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
|
||||
switch (form)
|
||||
{
|
||||
case DW_FORM_data1:
|
||||
case DW_FORM_flag:
|
||||
++bytes;
|
||||
break;
|
||||
|
||||
case DW_FORM_data2:
|
||||
bytes += 2;
|
||||
break;
|
||||
|
||||
case DW_FORM_data4:
|
||||
bytes += 4;
|
||||
break;
|
||||
|
||||
case DW_FORM_data8:
|
||||
bytes += 8;
|
||||
break;
|
||||
|
||||
case DW_FORM_data16:
|
||||
bytes += 16;
|
||||
break;
|
||||
|
||||
case DW_FORM_string:
|
||||
read_direct_string (abfd, bytes, &bytes_read);
|
||||
bytes += bytes_read;
|
||||
break;
|
||||
|
||||
case DW_FORM_sec_offset:
|
||||
case DW_FORM_strp:
|
||||
case DW_FORM_GNU_strp_alt:
|
||||
bytes += offset_size;
|
||||
break;
|
||||
|
||||
case DW_FORM_block:
|
||||
bytes += read_unsigned_leb128 (abfd, bytes, &bytes_read);
|
||||
bytes += bytes_read;
|
||||
break;
|
||||
|
||||
case DW_FORM_block1:
|
||||
bytes += 1 + read_1_byte (abfd, bytes);
|
||||
break;
|
||||
case DW_FORM_block2:
|
||||
bytes += 2 + read_2_bytes (abfd, bytes);
|
||||
break;
|
||||
case DW_FORM_block4:
|
||||
bytes += 4 + read_4_bytes (abfd, bytes);
|
||||
break;
|
||||
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_sdata:
|
||||
case DW_FORM_strx:
|
||||
case DW_FORM_udata:
|
||||
case DW_FORM_GNU_addr_index:
|
||||
case DW_FORM_GNU_str_index:
|
||||
bytes = gdb_skip_leb128 (bytes, buffer_end);
|
||||
if (bytes == NULL)
|
||||
{
|
||||
section->overflow_complaint ();
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_FORM_implicit_const:
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
complaint (_("invalid form 0x%x in `%s'"),
|
||||
form, section->get_name ());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* A helper for dwarf_decode_macros that handles skipping an unknown
|
||||
opcode. Returns an updated pointer to the macro data buffer; or,
|
||||
on error, issues a complaint and returns NULL. */
|
||||
|
||||
static const gdb_byte *
|
||||
skip_unknown_opcode (unsigned int opcode,
|
||||
const gdb_byte **opcode_definitions,
|
||||
const gdb_byte *mac_ptr, const gdb_byte *mac_end,
|
||||
bfd *abfd,
|
||||
unsigned int offset_size,
|
||||
struct dwarf2_section_info *section)
|
||||
{
|
||||
unsigned int bytes_read, i;
|
||||
unsigned long arg;
|
||||
const gdb_byte *defn;
|
||||
|
||||
if (opcode_definitions[opcode] == NULL)
|
||||
{
|
||||
complaint (_("unrecognized DW_MACFINO opcode 0x%x"),
|
||||
opcode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
defn = opcode_definitions[opcode];
|
||||
arg = read_unsigned_leb128 (abfd, defn, &bytes_read);
|
||||
defn += bytes_read;
|
||||
|
||||
for (i = 0; i < arg; ++i)
|
||||
{
|
||||
mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end,
|
||||
(enum dwarf_form) defn[i], offset_size,
|
||||
section);
|
||||
if (mac_ptr == NULL)
|
||||
{
|
||||
/* skip_form_bytes already issued the complaint. */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return mac_ptr;
|
||||
}
|
||||
|
||||
/* A helper function which parses the header of a macro section.
|
||||
If the macro section is the extended (for now called "GNU") type,
|
||||
then this updates *OFFSET_SIZE. Returns a pointer to just after
|
||||
the header, or issues a complaint and returns NULL on error. */
|
||||
|
||||
static const gdb_byte *
|
||||
dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
|
||||
bfd *abfd,
|
||||
const gdb_byte *mac_ptr,
|
||||
unsigned int *offset_size,
|
||||
int section_is_gnu)
|
||||
{
|
||||
memset (opcode_definitions, 0, 256 * sizeof (gdb_byte *));
|
||||
|
||||
if (section_is_gnu)
|
||||
{
|
||||
unsigned int version, flags;
|
||||
|
||||
version = read_2_bytes (abfd, mac_ptr);
|
||||
if (version != 4 && version != 5)
|
||||
{
|
||||
complaint (_("unrecognized version `%d' in .debug_macro section"),
|
||||
version);
|
||||
return NULL;
|
||||
}
|
||||
mac_ptr += 2;
|
||||
|
||||
flags = read_1_byte (abfd, mac_ptr);
|
||||
++mac_ptr;
|
||||
*offset_size = (flags & 1) ? 8 : 4;
|
||||
|
||||
if ((flags & 2) != 0)
|
||||
/* We don't need the line table offset. */
|
||||
mac_ptr += *offset_size;
|
||||
|
||||
/* Vendor opcode descriptions. */
|
||||
if ((flags & 4) != 0)
|
||||
{
|
||||
unsigned int i, count;
|
||||
|
||||
count = read_1_byte (abfd, mac_ptr);
|
||||
++mac_ptr;
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
unsigned int opcode, bytes_read;
|
||||
unsigned long arg;
|
||||
|
||||
opcode = read_1_byte (abfd, mac_ptr);
|
||||
++mac_ptr;
|
||||
opcode_definitions[opcode] = mac_ptr;
|
||||
arg = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
mac_ptr += arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mac_ptr;
|
||||
}
|
||||
|
||||
/* A helper for dwarf_decode_macros that handles the GNU extensions,
|
||||
including DW_MACRO_import. */
|
||||
|
||||
static void
|
||||
dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
buildsym_compunit *builder,
|
||||
bfd *abfd,
|
||||
const gdb_byte *mac_ptr, const gdb_byte *mac_end,
|
||||
struct macro_source_file *current_file,
|
||||
struct line_header *lh,
|
||||
struct dwarf2_section_info *section,
|
||||
int section_is_gnu, int section_is_dwz,
|
||||
unsigned int offset_size,
|
||||
htab_t include_hash)
|
||||
{
|
||||
struct objfile *objfile = dwarf2_per_objfile->objfile;
|
||||
enum dwarf_macro_record_type macinfo_type;
|
||||
int at_commandline;
|
||||
const gdb_byte *opcode_definitions[256];
|
||||
|
||||
mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
|
||||
&offset_size, section_is_gnu);
|
||||
if (mac_ptr == NULL)
|
||||
{
|
||||
/* We already issued a complaint. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determines if GDB is still before first DW_MACINFO_start_file. If true
|
||||
GDB is still reading the definitions from command line. First
|
||||
DW_MACINFO_start_file will need to be ignored as it was already executed
|
||||
to create CURRENT_FILE for the main source holding also the command line
|
||||
definitions. On first met DW_MACINFO_start_file this flag is reset to
|
||||
normally execute all the remaining DW_MACINFO_start_file macinfos. */
|
||||
|
||||
at_commandline = 1;
|
||||
|
||||
do
|
||||
{
|
||||
/* Do we at least have room for a macinfo type byte? */
|
||||
if (mac_ptr >= mac_end)
|
||||
{
|
||||
section->overflow_complaint ();
|
||||
break;
|
||||
}
|
||||
|
||||
macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
|
||||
mac_ptr++;
|
||||
|
||||
/* Note that we rely on the fact that the corresponding GNU and
|
||||
DWARF constants are the same. */
|
||||
DIAGNOSTIC_PUSH
|
||||
DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
|
||||
switch (macinfo_type)
|
||||
{
|
||||
/* A zero macinfo type indicates the end of the macro
|
||||
information. */
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case DW_MACRO_define:
|
||||
case DW_MACRO_undef:
|
||||
case DW_MACRO_define_strp:
|
||||
case DW_MACRO_undef_strp:
|
||||
case DW_MACRO_define_sup:
|
||||
case DW_MACRO_undef_sup:
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
int line;
|
||||
const char *body;
|
||||
int is_define;
|
||||
|
||||
line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
|
||||
if (macinfo_type == DW_MACRO_define
|
||||
|| macinfo_type == DW_MACRO_undef)
|
||||
{
|
||||
body = read_direct_string (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
}
|
||||
else
|
||||
{
|
||||
LONGEST str_offset;
|
||||
|
||||
str_offset = read_offset (abfd, mac_ptr, offset_size);
|
||||
mac_ptr += offset_size;
|
||||
|
||||
if (macinfo_type == DW_MACRO_define_sup
|
||||
|| macinfo_type == DW_MACRO_undef_sup
|
||||
|| section_is_dwz)
|
||||
{
|
||||
struct dwz_file *dwz
|
||||
= dwarf2_get_dwz_file (dwarf2_per_objfile);
|
||||
|
||||
body = dwz->read_string (objfile, str_offset);
|
||||
}
|
||||
else
|
||||
body = read_indirect_string_at_offset (dwarf2_per_objfile,
|
||||
str_offset);
|
||||
}
|
||||
|
||||
is_define = (macinfo_type == DW_MACRO_define
|
||||
|| macinfo_type == DW_MACRO_define_strp
|
||||
|| macinfo_type == DW_MACRO_define_sup);
|
||||
if (! current_file)
|
||||
{
|
||||
/* DWARF violation as no main source is present. */
|
||||
complaint (_("debug info with no main source gives macro %s "
|
||||
"on line %d: %s"),
|
||||
is_define ? _("definition") : _("undefinition"),
|
||||
line, body);
|
||||
break;
|
||||
}
|
||||
if ((line == 0 && !at_commandline)
|
||||
|| (line != 0 && at_commandline))
|
||||
complaint (_("debug info gives %s macro %s with %s line %d: %s"),
|
||||
at_commandline ? _("command-line") : _("in-file"),
|
||||
is_define ? _("definition") : _("undefinition"),
|
||||
line == 0 ? _("zero") : _("non-zero"), line, body);
|
||||
|
||||
if (body == NULL)
|
||||
{
|
||||
/* Fedora's rpm-build's "debugedit" binary
|
||||
corrupted .debug_macro sections.
|
||||
|
||||
For more info, see
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1708786 */
|
||||
complaint (_("debug info gives %s invalid macro %s "
|
||||
"without body (corrupted?) at line %d "
|
||||
"on file %s"),
|
||||
at_commandline ? _("command-line") : _("in-file"),
|
||||
is_define ? _("definition") : _("undefinition"),
|
||||
line, current_file->filename);
|
||||
}
|
||||
else if (is_define)
|
||||
parse_macro_definition (current_file, line, body);
|
||||
else
|
||||
{
|
||||
gdb_assert (macinfo_type == DW_MACRO_undef
|
||||
|| macinfo_type == DW_MACRO_undef_strp
|
||||
|| macinfo_type == DW_MACRO_undef_sup);
|
||||
macro_undef (current_file, line, body);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_start_file:
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
int line, file;
|
||||
|
||||
line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
|
||||
if ((line == 0 && !at_commandline)
|
||||
|| (line != 0 && at_commandline))
|
||||
complaint (_("debug info gives source %d included "
|
||||
"from %s at %s line %d"),
|
||||
file, at_commandline ? _("command-line") : _("file"),
|
||||
line == 0 ? _("zero") : _("non-zero"), line);
|
||||
|
||||
if (at_commandline)
|
||||
{
|
||||
/* This DW_MACRO_start_file was executed in the
|
||||
pass one. */
|
||||
at_commandline = 0;
|
||||
}
|
||||
else
|
||||
current_file = macro_start_file (builder, file, line,
|
||||
current_file, lh);
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_end_file:
|
||||
if (! current_file)
|
||||
complaint (_("macro debug info has an unmatched "
|
||||
"`close_file' directive"));
|
||||
else
|
||||
{
|
||||
current_file = current_file->included_by;
|
||||
if (! current_file)
|
||||
{
|
||||
enum dwarf_macro_record_type next_type;
|
||||
|
||||
/* GCC circa March 2002 doesn't produce the zero
|
||||
type byte marking the end of the compilation
|
||||
unit. Complain if it's not there, but exit no
|
||||
matter what. */
|
||||
|
||||
/* Do we at least have room for a macinfo type byte? */
|
||||
if (mac_ptr >= mac_end)
|
||||
{
|
||||
section->overflow_complaint ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* We don't increment mac_ptr here, so this is just
|
||||
a look-ahead. */
|
||||
next_type
|
||||
= (enum dwarf_macro_record_type) read_1_byte (abfd,
|
||||
mac_ptr);
|
||||
if (next_type != 0)
|
||||
complaint (_("no terminating 0-type entry for "
|
||||
"macros in `.debug_macinfo' section"));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_import:
|
||||
case DW_MACRO_import_sup:
|
||||
{
|
||||
LONGEST offset;
|
||||
void **slot;
|
||||
bfd *include_bfd = abfd;
|
||||
struct dwarf2_section_info *include_section = section;
|
||||
const gdb_byte *include_mac_end = mac_end;
|
||||
int is_dwz = section_is_dwz;
|
||||
const gdb_byte *new_mac_ptr;
|
||||
|
||||
offset = read_offset (abfd, mac_ptr, offset_size);
|
||||
mac_ptr += offset_size;
|
||||
|
||||
if (macinfo_type == DW_MACRO_import_sup)
|
||||
{
|
||||
struct dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
|
||||
|
||||
dwz->macro.read (objfile);
|
||||
|
||||
include_section = &dwz->macro;
|
||||
include_bfd = include_section->get_bfd_owner ();
|
||||
include_mac_end = dwz->macro.buffer + dwz->macro.size;
|
||||
is_dwz = 1;
|
||||
}
|
||||
|
||||
new_mac_ptr = include_section->buffer + offset;
|
||||
slot = htab_find_slot (include_hash, new_mac_ptr, INSERT);
|
||||
|
||||
if (*slot != NULL)
|
||||
{
|
||||
/* This has actually happened; see
|
||||
http://sourceware.org/bugzilla/show_bug.cgi?id=13568. */
|
||||
complaint (_("recursive DW_MACRO_import in "
|
||||
".debug_macro section"));
|
||||
}
|
||||
else
|
||||
{
|
||||
*slot = (void *) new_mac_ptr;
|
||||
|
||||
dwarf_decode_macro_bytes (dwarf2_per_objfile, builder,
|
||||
include_bfd, new_mac_ptr,
|
||||
include_mac_end, current_file, lh,
|
||||
section, section_is_gnu, is_dwz,
|
||||
offset_size, include_hash);
|
||||
|
||||
htab_remove_elt (include_hash, (void *) new_mac_ptr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACINFO_vendor_ext:
|
||||
if (!section_is_gnu)
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
|
||||
/* This reads the constant, but since we don't recognize
|
||||
any vendor extensions, we ignore it. */
|
||||
read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
read_direct_string (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
|
||||
/* We don't recognize any vendor extensions. */
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
|
||||
mac_ptr, mac_end, abfd, offset_size,
|
||||
section);
|
||||
if (mac_ptr == NULL)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
DIAGNOSTIC_POP
|
||||
} while (macinfo_type != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
buildsym_compunit *builder, dwarf2_section_info *section,
|
||||
struct line_header *lh, unsigned int offset_size,
|
||||
unsigned int offset, int section_is_gnu)
|
||||
{
|
||||
bfd *abfd;
|
||||
const gdb_byte *mac_ptr, *mac_end;
|
||||
struct macro_source_file *current_file = 0;
|
||||
enum dwarf_macro_record_type macinfo_type;
|
||||
const gdb_byte *opcode_definitions[256];
|
||||
void **slot;
|
||||
|
||||
abfd = section->get_bfd_owner ();
|
||||
|
||||
/* First pass: Find the name of the base filename.
|
||||
This filename is needed in order to process all macros whose definition
|
||||
(or undefinition) comes from the command line. These macros are defined
|
||||
before the first DW_MACINFO_start_file entry, and yet still need to be
|
||||
associated to the base file.
|
||||
|
||||
To determine the base file name, we scan the macro definitions until we
|
||||
reach the first DW_MACINFO_start_file entry. We then initialize
|
||||
CURRENT_FILE accordingly so that any macro definition found before the
|
||||
first DW_MACINFO_start_file can still be associated to the base file. */
|
||||
|
||||
mac_ptr = section->buffer + offset;
|
||||
mac_end = section->buffer + section->size;
|
||||
|
||||
mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
|
||||
&offset_size, section_is_gnu);
|
||||
if (mac_ptr == NULL)
|
||||
{
|
||||
/* We already issued a complaint. */
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* Do we at least have room for a macinfo type byte? */
|
||||
if (mac_ptr >= mac_end)
|
||||
{
|
||||
/* Complaint is printed during the second pass as GDB will probably
|
||||
stop the first pass earlier upon finding
|
||||
DW_MACINFO_start_file. */
|
||||
break;
|
||||
}
|
||||
|
||||
macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
|
||||
mac_ptr++;
|
||||
|
||||
/* Note that we rely on the fact that the corresponding GNU and
|
||||
DWARF constants are the same. */
|
||||
DIAGNOSTIC_PUSH
|
||||
DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
|
||||
switch (macinfo_type)
|
||||
{
|
||||
/* A zero macinfo type indicates the end of the macro
|
||||
information. */
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case DW_MACRO_define:
|
||||
case DW_MACRO_undef:
|
||||
/* Only skip the data by MAC_PTR. */
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
|
||||
read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
read_direct_string (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_start_file:
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
int line, file;
|
||||
|
||||
line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
|
||||
current_file = macro_start_file (builder, file, line,
|
||||
current_file, lh);
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_end_file:
|
||||
/* No data to skip by MAC_PTR. */
|
||||
break;
|
||||
|
||||
case DW_MACRO_define_strp:
|
||||
case DW_MACRO_undef_strp:
|
||||
case DW_MACRO_define_sup:
|
||||
case DW_MACRO_undef_sup:
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
|
||||
read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
mac_ptr += offset_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_MACRO_import:
|
||||
case DW_MACRO_import_sup:
|
||||
/* Note that, according to the spec, a transparent include
|
||||
chain cannot call DW_MACRO_start_file. So, we can just
|
||||
skip this opcode. */
|
||||
mac_ptr += offset_size;
|
||||
break;
|
||||
|
||||
case DW_MACINFO_vendor_ext:
|
||||
/* Only skip the data by MAC_PTR. */
|
||||
if (!section_is_gnu)
|
||||
{
|
||||
unsigned int bytes_read;
|
||||
|
||||
read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
read_direct_string (abfd, mac_ptr, &bytes_read);
|
||||
mac_ptr += bytes_read;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
|
||||
mac_ptr, mac_end, abfd, offset_size,
|
||||
section);
|
||||
if (mac_ptr == NULL)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
DIAGNOSTIC_POP
|
||||
} while (macinfo_type != 0 && current_file == NULL);
|
||||
|
||||
/* Second pass: Process all entries.
|
||||
|
||||
Use the AT_COMMAND_LINE flag to determine whether we are still processing
|
||||
command-line macro definitions/undefinitions. This flag is unset when we
|
||||
reach the first DW_MACINFO_start_file entry. */
|
||||
|
||||
htab_up include_hash (htab_create_alloc (1, htab_hash_pointer,
|
||||
htab_eq_pointer,
|
||||
NULL, xcalloc, xfree));
|
||||
mac_ptr = section->buffer + offset;
|
||||
slot = htab_find_slot (include_hash.get (), mac_ptr, INSERT);
|
||||
*slot = (void *) mac_ptr;
|
||||
dwarf_decode_macro_bytes (dwarf2_per_objfile, builder,
|
||||
abfd, mac_ptr, mac_end,
|
||||
current_file, lh, section,
|
||||
section_is_gnu, 0, offset_size,
|
||||
include_hash.get ());
|
||||
}
|
||||
|
||||
/* An overload of dwarf_decode_macros that finds the correct section
|
||||
and ensures it is read in before calling the other overload. */
|
||||
|
||||
|
|
Loading…
Reference in New Issue