| /* 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, | |
| 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_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 (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, | |
| 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); | |
| 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; | |
| 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); | |
| 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, | |
| 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 ()); | |
| } |