|  | /* Read DWARF macro information | 
|  |  | 
|  | Copyright (C) 1994-2022 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" | 
|  | #include "objfiles.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, | 
|  | const 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, | 
|  | const 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, | 
|  | const 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_MACINFO or DW_MACRO 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 (dwarf2_per_objfile *per_objfile, | 
|  | buildsym_compunit *builder, | 
|  | bfd *abfd, | 
|  | const gdb_byte *mac_ptr, const gdb_byte *mac_end, | 
|  | struct macro_source_file *current_file, | 
|  | const struct line_header *lh, | 
|  | const struct dwarf2_section_info *section, | 
|  | int section_is_gnu, int section_is_dwz, | 
|  | unsigned int offset_size, | 
|  | struct dwarf2_section_info *str_section, | 
|  | struct dwarf2_section_info *str_offsets_section, | 
|  | gdb::optional<ULONGEST> str_offsets_base, | 
|  | htab_t include_hash) | 
|  | { | 
|  | struct objfile *objfile = 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) | 
|  | { | 
|  | dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd, | 
|  | true); | 
|  |  | 
|  | body = dwz->read_string (objfile, str_offset); | 
|  | } | 
|  | else | 
|  | body = per_objfile->per_bfd->str.read_string (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_define_strx: | 
|  | case DW_MACRO_undef_strx: | 
|  | { | 
|  | unsigned int bytes_read; | 
|  |  | 
|  | int line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); | 
|  | mac_ptr += bytes_read; | 
|  | int offset_index = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); | 
|  | mac_ptr += bytes_read; | 
|  |  | 
|  | /* Use of the strx operators requires a DW_AT_str_offsets_base.  */ | 
|  | if (!str_offsets_base.has_value ()) | 
|  | { | 
|  | complaint (_("use of %s with unknown string offsets base " | 
|  | "[in module %s]"), | 
|  | (macinfo_type == DW_MACRO_define_strx | 
|  | ? "DW_MACRO_define_strx" | 
|  | : "DW_MACRO_undef_strx"), | 
|  | objfile_name (objfile)); | 
|  | break; | 
|  | } | 
|  |  | 
|  | str_offsets_section->read (objfile); | 
|  | const gdb_byte *info_ptr = (str_offsets_section->buffer | 
|  | + *str_offsets_base | 
|  | + offset_index * offset_size); | 
|  |  | 
|  | const char *macinfo_str = (macinfo_type == DW_MACRO_define_strx ? | 
|  | "DW_MACRO_define_strx" : "DW_MACRO_undef_strx"); | 
|  |  | 
|  | if (*str_offsets_base + offset_index * offset_size | 
|  | >= str_offsets_section->size) | 
|  | { | 
|  | complaint (_("%s pointing outside of .debug_str_offsets section " | 
|  | "[in module %s]"), macinfo_str, objfile_name (objfile)); | 
|  | break; | 
|  | } | 
|  |  | 
|  | ULONGEST str_offset = read_offset (abfd, info_ptr, offset_size); | 
|  |  | 
|  | const char *body = str_section->read_string (objfile, str_offset, | 
|  | macinfo_str); | 
|  | if (current_file == nullptr) | 
|  | { | 
|  | /* DWARF violation as no main source is present.  */ | 
|  | complaint (_("debug info with no main source gives macro %s " | 
|  | "on line %d: %s"), | 
|  | macinfo_type == DW_MACRO_define_strx ? _("definition") | 
|  | : _("undefinition"), line, body); | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (macinfo_type == DW_MACRO_define_strx) | 
|  | parse_macro_definition (current_file, line, body); | 
|  | else | 
|  | 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; | 
|  | const 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) | 
|  | { | 
|  | dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd, | 
|  | true); | 
|  |  | 
|  | 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 (per_objfile, builder, include_bfd, | 
|  | new_mac_ptr, include_mac_end, | 
|  | current_file, lh, section, | 
|  | section_is_gnu, is_dwz, offset_size, | 
|  | str_section, str_offsets_section, | 
|  | str_offsets_base, 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 (dwarf2_per_objfile *per_objfile, | 
|  | buildsym_compunit *builder, | 
|  | const dwarf2_section_info *section, | 
|  | const struct line_header *lh, unsigned int offset_size, | 
|  | unsigned int offset, struct dwarf2_section_info *str_section, | 
|  | struct dwarf2_section_info *str_offsets_section, | 
|  | gdb::optional<ULONGEST> str_offsets_base, | 
|  | 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_define_strx: | 
|  | case DW_MACRO_undef_strx: | 
|  | { | 
|  | unsigned int bytes_read; | 
|  |  | 
|  | read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); | 
|  | mac_ptr += bytes_read; | 
|  | read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); | 
|  | mac_ptr += bytes_read; | 
|  | } | 
|  | 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 (per_objfile, builder, abfd, mac_ptr, mac_end, | 
|  | current_file, lh, section, section_is_gnu, 0, | 
|  | offset_size, str_section, str_offsets_section, | 
|  | str_offsets_base, include_hash.get ()); | 
|  | } |