diff options
-rw-r--r-- | bfd/ChangeLog | 6 | ||||
-rw-r--r-- | bfd/dwarf2.c | 2 | ||||
-rw-r--r-- | binutils/ChangeLog | 13 | ||||
-rw-r--r-- | binutils/NEWS | 2 | ||||
-rw-r--r-- | binutils/dwarf.c | 320 | ||||
-rw-r--r-- | binutils/dwarf.h | 1 | ||||
-rw-r--r-- | binutils/readelf.c | 1 |
7 files changed, 344 insertions, 1 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c92d664bb8..495f9f25ed 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2011-07-26 Jakub Jelinek <jakub@redhat.com> + + * dwarf2.c (dwarf_debug_sections): Add .debug_macro + and .zdebug_macro entry. + (dwarf_debug_section_enum): Add debug_macro. + 2011-07-26 Alan Modra <amodra@gmail.com> * elf32-ppc.c: Include dwarf2.h. diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 02e69a8672..3cd2f7d7d4 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -287,6 +287,7 @@ const struct dwarf_debug_section dwarf_debug_sections[] = { ".debug_line", ".zdebug_line" }, { ".debug_loc", ".zdebug_loc" }, { ".debug_macinfo", ".zdebug_macinfo" }, + { ".debug_macro", ".zdebug_macro" }, { ".debug_pubnames", ".zdebug_pubnames" }, { ".debug_pubtypes", ".zdebug_pubtypes" }, { ".debug_ranges", ".zdebug_ranges" }, @@ -314,6 +315,7 @@ enum dwarf_debug_section_enum debug_line, debug_loc, debug_macinfo, + debug_macro, debug_pubnames, debug_pubtypes, debug_ranges, diff --git a/binutils/ChangeLog b/binutils/ChangeLog index f9956b646c..44d41bf004 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,16 @@ +2011-07-26 Jakub Jelinek <jakub@redhat.com> + + * NEWS: Mention .debug_macro support. + * dwarf.c (read_and_display_attr_value): Don't print a tab + if attribute is 0. + (get_AT_name): Handle DW_AT_GNU_macros. + (get_line_filename_and_dirname, display_debug_macro): New + functions. + (debug_displays): Add an entry for .debug_macro and .zdebug_macro. + * readelf.c (process_section_headers): With do_debug_macinfo + handle also .debug_macro sections. + * dwarf.h (dwarf_section_display_enum): Add macro. + 2011-07-24 Chao-ying Fu <fu@mips.com> Maciej W. Rozycki <macro@codesourcery.com> diff --git a/binutils/NEWS b/binutils/NEWS index e069a25c9d..42b5c4f81d 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -1,5 +1,7 @@ -*- text -*- +* Add support for displaying the contents of .debug.macro sections. + * Add --preprocessor-arg option to windres to specify additional options passed to preprocessor. diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 08febadf55..ae1cd809de 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -1542,7 +1542,7 @@ read_and_display_attr_value (unsigned long attribute, } } - if (do_loc) + if (do_loc || attribute == 0) return data; /* For some attributes we can display further information. */ @@ -1960,6 +1960,7 @@ get_AT_name (unsigned long attribute) case DW_AT_GNU_all_tail_call_sites: return "DW_AT_GNU_all_tail_call_sites"; case DW_AT_GNU_all_call_sites: return "DW_AT_GNU_all_call_sites"; case DW_AT_GNU_all_source_call_sites: return "DW_AT_GNU_all_source_call_sites"; + case DW_AT_GNU_macros: return "DW_AT_GNU_macros"; /* UPC extension. */ case DW_AT_upc_threads_scaled: return "DW_AT_upc_threads_scaled"; @@ -3450,6 +3451,321 @@ display_debug_macinfo (struct dwarf_section *section, return 1; } +/* Given LINE_OFFSET into the .debug_line section, attempt to return + filename and dirname corresponding to file name table entry with index + FILEIDX. Return NULL on failure. */ + +static unsigned char * +get_line_filename_and_dirname (dwarf_vma line_offset, dwarf_vma fileidx, + unsigned char **dir_name) +{ + struct dwarf_section *section = &debug_displays [line].section; + unsigned char *hdrptr, *dirtable, *file_name; + unsigned int offset_size, initial_length_size; + unsigned int version, opcode_base, bytes_read; + dwarf_vma length, diridx; + + *dir_name = NULL; + if (section->start == NULL + || line_offset >= section->size + || fileidx == 0) + return NULL; + + hdrptr = section->start + line_offset; + length = byte_get (hdrptr, 4); + hdrptr += 4; + if (length == 0xffffffff) + { + /* This section is 64-bit DWARF 3. */ + length = byte_get (hdrptr, 8); + hdrptr += 8; + offset_size = 8; + initial_length_size = 12; + } + else + { + offset_size = 4; + initial_length_size = 4; + } + if (length + initial_length_size > section->size) + return NULL; + version = byte_get (hdrptr, 2); + hdrptr += 2; + if (version != 2 && version != 3 && version != 4) + return NULL; + hdrptr += offset_size + 1;/* Skip prologue_length and min_insn_length. */ + if (version >= 4) + hdrptr++; /* Skip max_ops_per_insn. */ + hdrptr += 3; /* Skip default_is_stmt, line_base, line_range. */ + opcode_base = byte_get (hdrptr, 1); + if (opcode_base == 0) + return NULL; + hdrptr++; + hdrptr += opcode_base - 1; + dirtable = hdrptr; + /* Skip over dirname table. */ + while (*hdrptr != '\0') + hdrptr += strlen ((char *) hdrptr) + 1; + hdrptr++; /* Skip the NUL at the end of the table. */ + /* Now skip over preceding filename table entries. */ + for (; *hdrptr != '\0' && fileidx > 1; fileidx--) + { + hdrptr += strlen ((char *) hdrptr) + 1; + read_leb128 (hdrptr, &bytes_read, 0); + hdrptr += bytes_read; + read_leb128 (hdrptr, &bytes_read, 0); + hdrptr += bytes_read; + read_leb128 (hdrptr, &bytes_read, 0); + hdrptr += bytes_read; + } + if (*hdrptr == '\0') + return NULL; + file_name = hdrptr; + hdrptr += strlen ((char *) hdrptr) + 1; + diridx = read_leb128 (hdrptr, &bytes_read, 0); + if (diridx == 0) + return file_name; + for (; *dirtable != '\0' && diridx > 1; diridx--) + dirtable += strlen ((char *) dirtable) + 1; + if (*dirtable == '\0') + return NULL; + *dir_name = dirtable; + return file_name; +} + +static int +display_debug_macro (struct dwarf_section *section, + void *file) +{ + unsigned char *start = section->start; + unsigned char *end = start + section->size; + unsigned char *curr = start; + unsigned char *extended_op_buf[256]; + unsigned int bytes_read; + + load_debug_section (str, file); + load_debug_section (line, file); + + printf (_("Contents of the %s section:\n\n"), section->name); + + while (curr < end) + { + unsigned int lineno, version, flags; + unsigned int offset_size = 4; + const char *string; + dwarf_vma line_offset = 0, sec_offset = curr - start, offset; + unsigned char **extended_ops = NULL; + + version = byte_get (curr, 2); + curr += 2; + + if (version != 4) + { + error (_("Only GNU extension to DWARF 4 of %s is currently supported.\n"), + section->name); + return 0; + } + + flags = byte_get (curr++, 1); + if (flags & 1) + offset_size = 8; + printf (_(" Offset: 0x%lx\n"), + (unsigned long) sec_offset); + printf (_(" Version: %d\n"), version); + printf (_(" Offset size: %d\n"), offset_size); + if (flags & 2) + { + line_offset = byte_get (curr, offset_size); + curr += offset_size; + printf (_(" Offset into .debug_line: 0x%lx\n"), + (unsigned long) line_offset); + } + if (flags & 4) + { + unsigned int i, count = byte_get (curr++, 1), op; + dwarf_vma nargs, n; + memset (extended_op_buf, 0, sizeof (extended_op_buf)); + extended_ops = extended_op_buf; + if (count) + { + printf (_(" Extension opcode arguments:\n")); + for (i = 0; i < count; i++) + { + op = byte_get (curr++, 1); + extended_ops[op] = curr; + nargs = read_leb128 (curr, &bytes_read, 0); + curr += bytes_read; + if (nargs == 0) + printf (_(" DW_MACRO_GNU_%02x has no arguments\n"), op); + else + { + printf (_(" DW_MACRO_GNU_%02x arguments: "), op); + for (n = 0; n < nargs; n++) + { + unsigned int form = byte_get (curr++, 1); + printf ("%s%s", get_FORM_name (form), + n == nargs - 1 ? "\n" : ", "); + switch (form) + { + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_flag: + case DW_FORM_string: + case DW_FORM_strp: + case DW_FORM_sec_offset: + break; + default: + error (_("Invalid extension opcode form %s\n"), + get_FORM_name (form)); + return 0; + } + } + } + } + } + } + printf ("\n"); + + while (1) + { + unsigned int op; + + if (curr >= end) + { + error (_(".debug_macro section not zero terminated\n")); + return 0; + } + + op = byte_get (curr++, 1); + if (op == 0) + break; + + switch (op) + { + case DW_MACRO_GNU_start_file: + { + unsigned int filenum; + unsigned char *file_name = NULL, *dir_name = NULL; + + lineno = read_leb128 (curr, &bytes_read, 0); + curr += bytes_read; + filenum = read_leb128 (curr, &bytes_read, 0); + curr += bytes_read; + + if ((flags & 2) == 0) + error (_("DW_MACRO_GNU_start_file used, but no .debug_line offset provided.\n")); + else + file_name + = get_line_filename_and_dirname (line_offset, filenum, + &dir_name); + if (file_name == NULL) + printf (_(" DW_MACRO_GNU_start_file - lineno: %d filenum: %d\n"), + lineno, filenum); + else + printf (_(" DW_MACRO_GNU_start_file - lineno: %d filenum: %d filename: %s%s%s\n"), + lineno, filenum, + dir_name != NULL ? (const char *) dir_name : "", + dir_name != NULL ? "/" : "", file_name); + } + break; + + case DW_MACRO_GNU_end_file: + printf (_(" DW_MACRO_GNU_end_file\n")); + break; + + case DW_MACRO_GNU_define: + lineno = read_leb128 (curr, &bytes_read, 0); + curr += bytes_read; + string = (char *) curr; + curr += strlen (string) + 1; + printf (_(" DW_MACRO_GNU_define - lineno : %d macro : %s\n"), + lineno, string); + break; + + case DW_MACRO_GNU_undef: + lineno = read_leb128 (curr, &bytes_read, 0); + curr += bytes_read; + string = (char *) curr; + curr += strlen (string) + 1; + printf (_(" DW_MACRO_GNU_undef - lineno : %d macro : %s\n"), + lineno, string); + break; + + case DW_MACRO_GNU_define_indirect: + lineno = read_leb128 (curr, &bytes_read, 0); + curr += bytes_read; + offset = byte_get (curr, offset_size); + curr += offset_size; + string = fetch_indirect_string (offset); + printf (_(" DW_MACRO_GNU_define_indirect - lineno : %d macro : %s\n"), + lineno, string); + break; + + case DW_MACRO_GNU_undef_indirect: + lineno = read_leb128 (curr, &bytes_read, 0); + curr += bytes_read; + offset = byte_get (curr, offset_size); + curr += offset_size; + string = fetch_indirect_string (offset); + printf (_(" DW_MACRO_GNU_undef_indirect - lineno : %d macro : %s\n"), + lineno, string); + break; + + case DW_MACRO_GNU_transparent_include: + offset = byte_get (curr, offset_size); + curr += offset_size; + printf (_(" DW_MACRO_GNU_transparent_include - offset : 0x%lx\n"), + (unsigned long) offset); + break; + + default: + if (extended_ops == NULL || extended_ops[op] == NULL) + { + error (_(" Unknown macro opcode %02x seen\n"), op); + return 0; + } + else + { + /* Skip over unhandled opcodes. */ + dwarf_vma nargs, n; + unsigned char *desc = extended_ops[op]; + nargs = read_leb128 (desc, &bytes_read, 0); + desc += bytes_read; + if (nargs == 0) + { + printf (_(" DW_MACRO_GNU_%02x\n"), op); + break; + } + printf (_(" DW_MACRO_GNU_%02x -"), op); + for (n = 0; n < nargs; n++) + { + curr + = read_and_display_attr_value (0, byte_get (desc++, 1), + curr, 0, 0, offset_size, + version, NULL, 0, NULL); + if (n != nargs - 1) + printf (","); + } + printf ("\n"); + } + break; + } + } + + printf ("\n"); + } + + return 1; +} + static int display_debug_abbrev (struct dwarf_section *section, void *file ATTRIBUTE_UNUSED) @@ -5537,6 +5853,8 @@ struct dwarf_section_display debug_displays[] = display_debug_frames, &do_debug_frames, 1 }, { { ".debug_macinfo", ".zdebug_macinfo", NULL, NULL, 0, 0 }, display_debug_macinfo, &do_debug_macinfo, 0 }, + { { ".debug_macro", ".zdebug_macro", NULL, NULL, 0, 0 }, + display_debug_macro, &do_debug_macinfo, 1 }, { { ".debug_str", ".zdebug_str", NULL, NULL, 0, 0 }, display_debug_str, &do_debug_str, 0 }, { { ".debug_loc", ".zdebug_loc", NULL, NULL, 0, 0 }, diff --git a/binutils/dwarf.h b/binutils/dwarf.h index 07b95b09ec..7a755c9a28 100644 --- a/binutils/dwarf.h +++ b/binutils/dwarf.h @@ -143,6 +143,7 @@ enum dwarf_section_display_enum pubnames, eh_frame, macinfo, + macro, str, loc, pubtypes, diff --git a/binutils/readelf.c b/binutils/readelf.c index 1191aebfb1..a9064c541f 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -4620,6 +4620,7 @@ process_section_headers (FILE * file) || (do_debug_ranges && streq (name, "ranges")) || (do_debug_frames && streq (name, "frame")) || (do_debug_macinfo && streq (name, "macinfo")) + || (do_debug_macinfo && streq (name, "macro")) || (do_debug_str && streq (name, "str")) || (do_debug_loc && streq (name, "loc")) ) |