| /* Read DWARF macro information |
| |
| Copyright (C) 1994-2021 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 ()); |
| } |