From: Jim Blandy Date: Thu, 16 May 2002 21:00:14 +0000 (+0000) Subject: Teach the Dwarf 2 reader to read macro information. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2e2761252bc9d29d6b96fce80d677991ef5c4e75;p=binutils-gdb.git Teach the Dwarf 2 reader to read macro information. * dwarf2read.c: #include "macrotab.h". (dwarf_macinfo_buffer): New variable. (struct dwarf2_pinfo): New members: dwarf_macinfo_buffer, and dwarf_macinfo_size. (DWARF_MACINFO_BUFFER, DWARF_MACINFO_SIZE): New macros. (dwarf2_missing_macinfo_section, dwarf2_macros_too_long, dwarf2_macros_not_terminated, dwarf2_macro_outside_file, dwarf2_macro_unmatched_end_file, dwarf2_macro_malformed_definition, dwarf2_macro_spaces_in_definition): New complaints. (dwarf2_has_info): Initialize dwarf_macinfo_offset. (dwarf2_build_psymtabs): Read the .dwarf_macinfo section. (dwarf2_build_psymtabs_hard): Record the buffer and its size in the partial symbol table. (psymtab_to_symtab_1): Set the macinfo buffer and size globals from what's recorded in the partial symbol table. (read_file_scope): If the compilation unit has a `DW_AT_macro_info' attribute, read its macro information. * Makefile.in (dwarf2read.o): Depend on macrotab.h. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 98ce9c7b83e..1cd20642304 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,25 @@ +2002-05-16 Jim Blandy + + Teach the Dwarf 2 reader to read macro information. + * dwarf2read.c: #include "macrotab.h". + (dwarf_macinfo_buffer): New variable. + (struct dwarf2_pinfo): New members: dwarf_macinfo_buffer, and + dwarf_macinfo_size. + (DWARF_MACINFO_BUFFER, DWARF_MACINFO_SIZE): New macros. + (dwarf2_missing_macinfo_section, dwarf2_macros_too_long, + dwarf2_macros_not_terminated, dwarf2_macro_outside_file, + dwarf2_macro_unmatched_end_file, dwarf2_macro_malformed_definition, + dwarf2_macro_spaces_in_definition): New complaints. + (dwarf2_has_info): Initialize dwarf_macinfo_offset. + (dwarf2_build_psymtabs): Read the .dwarf_macinfo section. + (dwarf2_build_psymtabs_hard): Record the buffer and its size in + the partial symbol table. + (psymtab_to_symtab_1): Set the macinfo buffer and size globals + from what's recorded in the partial symbol table. + (read_file_scope): If the compilation unit has a + `DW_AT_macro_info' attribute, read its macro information. + * Makefile.in (dwarf2read.o): Depend on macrotab.h. + 2002-05-16 Daniel Jacobowitz Fix PR gdb/546 diff --git a/gdb/Makefile.in b/gdb/Makefile.in index e6d43ad25af..dfcbf8c9887 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1426,7 +1426,7 @@ dwarfread.o: dwarfread.c $(bfd_h) $(buildsym_h) $(complaints_h) $(defs_h) \ dwarf2read.o: dwarf2read.c $(bfd_h) $(buildsym_h) $(defs_h) \ $(expression_h) $(gdbtypes_h) $(language_h) $(objfiles_h) \ - $(symfile_h) $(symtab_h) $(gdb_string_h) + $(symfile_h) $(symtab_h) $(gdb_string_h) $(macrotab_h) elfread.o: elfread.c $(bfd_h) $(buildsym_h) $(complaints_h) $(defs_h) \ $(gdb_stabs_h) $(objfiles_h) $(symfile_h) $(symtab_h) $(gdb_string_h) \ diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 27938178325..d702d0077fc 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -37,6 +37,7 @@ #include "demangle.h" #include "expression.h" #include "filenames.h" /* for DOSish file names */ +#include "macrotab.h" #include "language.h" #include "complaints.h" @@ -350,6 +351,7 @@ static char *dwarf_info_buffer; static char *dwarf_abbrev_buffer; static char *dwarf_line_buffer; static char *dwarf_str_buffer; +static char *dwarf_macinfo_buffer; /* A zeroed version of a partial die for initialization purposes. */ static struct partial_die_info zeroed_partial_die; @@ -443,6 +445,15 @@ struct dwarf2_pinfo /* Size of dwarf string section for the objfile. */ unsigned int dwarf_str_size; + + /* Pointer to start of dwarf macro buffer for the objfile. */ + + char *dwarf_macinfo_buffer; + + /* Size of dwarf macinfo section for the objfile. */ + + unsigned int dwarf_macinfo_size; + }; #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private) @@ -454,6 +465,8 @@ struct dwarf2_pinfo #define DWARF_LINE_SIZE(p) (PST_PRIVATE(p)->dwarf_line_size) #define DWARF_STR_BUFFER(p) (PST_PRIVATE(p)->dwarf_str_buffer) #define DWARF_STR_SIZE(p) (PST_PRIVATE(p)->dwarf_str_size) +#define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer) +#define DWARF_MACINFO_SIZE(p) (PST_PRIVATE(p)->dwarf_macinfo_size) /* Maintain an array of referenced fundamental types for the current compilation unit being read. For DWARF version 1, we have to construct @@ -617,6 +630,34 @@ static struct complaint dwarf2_line_header_too_long = { "line number info header doesn't fit in `.debug_line' section", 0, 0 }; +static struct complaint dwarf2_missing_macinfo_section = +{ + "missing .debug_macinfo section", 0, 0 +}; +static struct complaint dwarf2_macros_too_long = +{ + "macro info runs off end of `.debug_macinfo' section", 0, 0 +}; +static struct complaint dwarf2_macros_not_terminated = +{ + "no terminating 0-type entry for macros in `.debug_macinfo' section", 0, 0 +}; +static struct complaint dwarf2_macro_outside_file = +{ + "debug info gives macro %s outside of any file: %s", 0, 0 +}; +static struct complaint dwarf2_macro_unmatched_end_file = +{ + "macro debug info has an unmatched `close_file' directive", 0, 0 +}; +static struct complaint dwarf2_macro_malformed_definition = +{ + "macro debug info contains a malformed macro definition:\n`%s'", 0, 0 +}; +static struct complaint dwarf2_macro_spaces_in_definition = +{ + "macro definition contains spaces in formal argument list:\n`%s'", 0, 0 +}; /* local function prototypes */ @@ -862,15 +903,23 @@ static void initialize_cu_func_list (void); static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR); +static void dwarf_decode_macros (struct line_header *, unsigned int, + char *, bfd *, const struct comp_unit_head *, + struct objfile *); + /* Try to locate the sections we need for DWARF 2 debugging information and return true if we have enough to do something. */ int dwarf2_has_info (bfd *abfd) { - dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0; + dwarf_info_offset = 0; + dwarf_abbrev_offset = 0; + dwarf_line_offset = 0; dwarf_str_offset = 0; - dwarf_frame_offset = dwarf_eh_frame_offset = 0; + dwarf_macinfo_offset = 0; + dwarf_frame_offset = 0; + dwarf_eh_frame_offset = 0; bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL); if (dwarf_info_offset && dwarf_abbrev_offset) { @@ -966,6 +1015,13 @@ dwarf2_build_psymtabs (struct objfile *objfile, int mainline) else dwarf_str_buffer = NULL; + if (dwarf_macinfo_offset) + dwarf_macinfo_buffer = dwarf2_read_section (objfile, + dwarf_macinfo_offset, + dwarf_macinfo_size); + else + dwarf_macinfo_buffer = NULL; + if (mainline || (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)) @@ -1174,6 +1230,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) DWARF_LINE_SIZE (pst) = dwarf_line_size; DWARF_STR_BUFFER (pst) = dwarf_str_buffer; DWARF_STR_SIZE (pst) = dwarf_str_size; + DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer; + DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); /* Store the function that reads in the rest of the symbol table */ @@ -1476,6 +1534,8 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) dwarf_line_size = DWARF_LINE_SIZE (pst); dwarf_str_buffer = DWARF_STR_BUFFER (pst); dwarf_str_size = DWARF_STR_SIZE (pst); + dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst); + dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst); baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile)); cu_header_offset = offset; info_ptr = dwarf_info_buffer + offset; @@ -1738,6 +1798,17 @@ read_file_scope (struct die_info *die, struct objfile *objfile, } } + /* Decode macro information, if present. Dwarf 2 macro information + refers to information in the line number info statement program + header, so we can only read it if we've read the header + successfully. */ + attr = dwarf_attr (die, DW_AT_macro_info); + if (attr) + { + unsigned int macro_offset = DW_UNSND (attr); + dwarf_decode_macros (line_header, macro_offset, + comp_dir, abfd, cu_header, objfile); + } do_cleanups (back_to); } @@ -6367,3 +6438,376 @@ dwarf_alloc_die (void) memset (die, 0, sizeof (struct die_info)); return (die); } + + +/* Macro support. */ + + +/* Return the full name of file number I in *LH's file name table. + Use COMP_DIR as the name of the current directory of the + compilation. The result is allocated using xmalloc; the caller is + responsible for freeing it. */ +static char * +file_full_name (int file, struct line_header *lh, const char *comp_dir) +{ + struct file_entry *fe = &lh->file_names[file - 1]; + + if (IS_ABSOLUTE_PATH (fe->name)) + return xstrdup (fe->name); + else + { + const char *dir; + int dir_len; + char *full_name; + + if (fe->dir_index) + dir = lh->include_dirs[fe->dir_index - 1]; + else + dir = comp_dir; + + if (dir) + { + dir_len = strlen (dir); + full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1); + strcpy (full_name, dir); + full_name[dir_len] = '/'; + strcpy (full_name + dir_len + 1, fe->name); + return full_name; + } + else + return xstrdup (fe->name); + } +} + + +static struct macro_source_file * +macro_start_file (int file, int line, + struct macro_source_file *current_file, + const char *comp_dir, + struct line_header *lh, struct objfile *objfile) +{ + /* The full name of this source file. */ + char *full_name = file_full_name (file, lh, comp_dir); + + /* We don't create a macro table for this compilation unit + at all until we actually get a filename. */ + if (! pending_macros) + pending_macros = new_macro_table (&objfile->symbol_obstack, + &objfile->macro_cache); + + if (! current_file) + /* 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 (pending_macros, full_name); + else + current_file = macro_include (current_file, line, full_name); + + xfree (full_name); + + return current_file; +} + + +/* Copy the LEN characters at BUF to a xmalloc'ed block of memory, + followed by a null byte. */ +static char * +copy_string (const char *buf, int len) +{ + char *s = xmalloc (len + 1); + memcpy (s, buf, len); + s[len] = '\0'; + + return s; +} + + +static const char * +consume_improper_spaces (const char *p, const char *body) +{ + if (*p == ' ') + { + complain (&dwarf2_macro_spaces_in_definition, 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: + + " " + + For function-like macro definitions, it should be: + + "() " + or + "(" ( "," ) * ") " + + Spaces may appear only where explicitly indicated, and in the + . + + 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; + char *name = copy_string (body, name_len); + const char *replacement; + + if (*p == ' ') + replacement = body + name_len + 1; + else + { + complain (&dwarf2_macro_malformed_definition, body); + replacement = body + name_len; + } + + macro_define_object (file, line, name, replacement); + + xfree (name); + } + else if (*p == '(') + { + /* It's a function-like macro. */ + char *name = copy_string (body, p - body); + int argc = 0; + int argv_size = 1; + char **argv = xmalloc (argv_size * sizeof (*argv)); + + 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) + complain (&dwarf2_macro_malformed_definition, + body); + else + { + /* Make sure argv has room for the new argument. */ + if (argc >= argv_size) + { + argv_size *= 2; + argv = xrealloc (argv, argv_size * sizeof (*argv)); + } + + argv[argc++] = copy_string (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, + argc, (const char **) argv, + p + 1); + else if (*p == '\0') + { + /* Complain, but do define it. */ + complain (&dwarf2_macro_malformed_definition, body); + macro_define_function (file, line, name, + argc, (const char **) argv, + p); + } + else + /* Just complain. */ + complain (&dwarf2_macro_malformed_definition, body); + } + else + /* Just complain. */ + complain (&dwarf2_macro_malformed_definition, body); + + xfree (name); + { + int i; + + for (i = 0; i < argc; i++) + xfree (argv[i]); + } + xfree (argv); + } + else + complain (&dwarf2_macro_malformed_definition, body); +} + + +static void +dwarf_decode_macros (struct line_header *lh, unsigned int offset, + char *comp_dir, bfd *abfd, + const struct comp_unit_head *cu_header, + struct objfile *objfile) +{ + char *mac_ptr, *mac_end; + struct macro_source_file *current_file = 0; + + if (dwarf_macinfo_buffer == NULL) + { + complain (&dwarf2_missing_macinfo_section); + return; + } + + mac_ptr = dwarf_macinfo_buffer + offset; + mac_end = dwarf_macinfo_buffer + dwarf_macinfo_size; + + for (;;) + { + enum dwarf_macinfo_record_type macinfo_type; + + /* Do we at least have room for a macinfo type byte? */ + if (mac_ptr >= mac_end) + { + complain (&dwarf2_macros_too_long); + return; + } + + macinfo_type = read_1_byte (abfd, mac_ptr); + mac_ptr++; + + switch (macinfo_type) + { + /* A zero macinfo type indicates the end of the macro + information. */ + case 0: + return; + + case DW_MACINFO_define: + case DW_MACINFO_undef: + { + int bytes_read; + int line; + char *body; + + line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + body = read_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + + if (! current_file) + complain (&dwarf2_macro_outside_file, + macinfo_type == DW_MACINFO_define ? "definition" : + macinfo_type == DW_MACINFO_undef ? "undefinition" : + "something-or-other", + body); + else + { + if (macinfo_type == DW_MACINFO_define) + parse_macro_definition (current_file, line, body); + else if (macinfo_type == DW_MACINFO_undef) + macro_undef (current_file, line, body); + } + } + break; + + case DW_MACINFO_start_file: + { + 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 (file, line, + current_file, comp_dir, + lh, objfile); + } + break; + + case DW_MACINFO_end_file: + if (! current_file) + complain (&dwarf2_macro_unmatched_end_file); + else + { + current_file = current_file->included_by; + if (! current_file) + { + enum dwarf_macinfo_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) + { + complain (&dwarf2_macros_too_long); + return; + } + + /* We don't increment mac_ptr here, so this is just + a look-ahead. */ + next_type = read_1_byte (abfd, mac_ptr); + if (next_type != 0) + complain (&dwarf2_macros_not_terminated); + + return; + } + } + break; + + case DW_MACINFO_vendor_ext: + { + int bytes_read; + int constant; + char *string; + + constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + string = read_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + + /* We don't recognize any vendor extensions. */ + } + break; + } + } +}