diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3f96894f7c3..ec28a1ac8d3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2013-10-22 Sterling Augustine + + * doc/invoke.texi: Document -ggnu-pubnames. + * common.opt: Add new option -ggnu-pubnames and modify -gpubnames + logic. + * dwarf2out.c: Include gdb/gdb-index.h. + (DEBUG_PUBNAMES_SECTION, DEBUG_PUBTYPES_SECTION): Handle + debug_generate_pub_sections. + (is_java, output_pubtables, output_pubname): New functions. + (include_pubname_in_output): Handle debug_generate_pub_sections at + level 2. + (size_of_pubnames): Use new local space_for_flags based on + debug_generate_pub_sections. + (output_pubnames): Unify pubnames and pubtypes output logic. + Genericize comments. Call output_pubname. + (dwarf2out_finish): Move logic to output_pubnames and call it. + 2013-10-22 Uros Bizjak PR target/58779 diff --git a/gcc/common.opt b/gcc/common.opt index 1f11fcd4d5d..deeb3f20a3b 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2412,13 +2412,17 @@ Common JoinedOrMissing Generate debug information in default extended format gno-pubnames -Common RejectNegative Var(debug_generate_pub_sections, 0) Init(-1) +Common Negative(gpubnames) Var(debug_generate_pub_sections, 0) Init(-1) Don't generate DWARF pubnames and pubtypes sections. gpubnames -Common RejectNegative Var(debug_generate_pub_sections, 1) +Common Negative(ggnu-pubnames) Var(debug_generate_pub_sections, 1) Generate DWARF pubnames and pubtypes sections. +ggnu-pubnames +Common Negative(gno-pubnames) Var(debug_generate_pub_sections, 2) +Generate DWARF pubnames and pubtypes sections with GNU extensions. + gno-record-gcc-switches Common RejectNegative Var(dwarf_record_gcc_switches,0) Init(1) Don't record gcc command line switches in DWARF DW_AT_producer. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index adbc45bf92a..46a2b18e1b0 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -5087,6 +5087,12 @@ possible. @opindex gpubnames Generate dwarf .debug_pubnames and .debug_pubtypes sections. +@item -ggnu-pubnames +@opindex ggnu-pubnames +Generate .debug_pubnames and .debug_pubtypes sections in a format +suitable for conversion into a GDB@ index. This option is only useful +with a linker that can produce GDB@ index version 7. + @item -gstabs @opindex gstabs Produce debugging information in stabs format (if that is supported), diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 3f4e314e1d4..0239d6ad62b 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -93,6 +93,7 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "opts.h" #include "tree-dfa.h" +#include "gdb/gdb-index.h" static void dwarf2out_source_line (unsigned int, const char *, int, bool); static rtx last_var_location_insn; @@ -3323,10 +3324,14 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel) #define DEBUG_DWO_LOC_SECTION ".debug_loc.dwo" #endif #ifndef DEBUG_PUBNAMES_SECTION -#define DEBUG_PUBNAMES_SECTION ".debug_pubnames" +#define DEBUG_PUBNAMES_SECTION \ + ((debug_generate_pub_sections == 2) \ + ? ".debug_gnu_pubnames" : ".debug_pubnames") #endif #ifndef DEBUG_PUBTYPES_SECTION -#define DEBUG_PUBTYPES_SECTION ".debug_pubtypes" +#define DEBUG_PUBTYPES_SECTION \ + ((debug_generate_pub_sections == 2) \ + ? ".debug_gnu_pubtypes" : ".debug_pubtypes") #endif #define DEBUG_NORM_STR_OFFSETS_SECTION ".debug_str_offsets" #define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo" @@ -4569,6 +4574,16 @@ is_cxx (void) return lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus; } +/* Return TRUE if the language is Java. */ + +static inline bool +is_java (void) +{ + unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language); + + return lang == DW_LANG_Java; +} + /* Return TRUE if the language is Fortran. */ static inline bool @@ -7960,6 +7975,12 @@ unmark_all_dies (dw_die_ref die) static bool include_pubname_in_output (vec *table, pubname_entry *p) { + /* By limiting gnu pubnames to definitions only, gold can generate a + gdb index without entries for declarations, which don't include + enough information to be useful. */ + if (debug_generate_pub_sections == 2 && is_declaration_die (p->die)) + return false; + if (table == pubname_table) { /* Enumerator names are part of the pubname table, but the @@ -7989,11 +8010,12 @@ size_of_pubnames (vec *names) unsigned long size; unsigned i; pubname_ref p; + int space_for_flags = (debug_generate_pub_sections == 2) ? 1 : 0; size = DWARF_PUBNAMES_HEADER_SIZE; FOR_EACH_VEC_ELT (*names, i, p) if (include_pubname_in_output (names, p)) - size += strlen (p->name) + DWARF_OFFSET_SIZE + 1; + size += strlen (p->name) + DWARF_OFFSET_SIZE + 1 + space_for_flags; size += DWARF_OFFSET_SIZE; return size; @@ -9146,6 +9168,76 @@ add_pubtype (tree decl, dw_die_ref die) } } +/* Output a single entry in the pubnames table. */ + +static void +output_pubname (dw_offset die_offset, pubname_entry *entry) +{ + dw_die_ref die = entry->die; + int is_static = get_AT_flag (die, DW_AT_external) ? 0 : 1; + + dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset"); + + if (debug_generate_pub_sections == 2) + { + /* This logic follows gdb's method for determining the value of the flag + byte. */ + uint32_t flags = GDB_INDEX_SYMBOL_KIND_NONE; + switch (die->die_tag) + { + case DW_TAG_typedef: + case DW_TAG_base_type: + case DW_TAG_subrange_type: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE); + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1); + break; + case DW_TAG_enumerator: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, + GDB_INDEX_SYMBOL_KIND_VARIABLE); + if (!is_cxx () && !is_java ()) + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1); + break; + case DW_TAG_subprogram: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, + GDB_INDEX_SYMBOL_KIND_FUNCTION); + if (!is_ada ()) + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static); + break; + case DW_TAG_constant: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, + GDB_INDEX_SYMBOL_KIND_VARIABLE); + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static); + break; + case DW_TAG_variable: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, + GDB_INDEX_SYMBOL_KIND_VARIABLE); + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static); + break; + case DW_TAG_namespace: + case DW_TAG_imported_declaration: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE); + break; + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE); + if (!is_cxx () && !is_java ()) + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1); + break; + default: + /* An unusual tag. Leave the flag-byte empty. */ + break; + } + dw2_asm_output_data (1, flags >> GDB_INDEX_CU_BITSIZE, + "GDB-index flags"); + } + + dw2_asm_output_nstring (entry->name, -1, "external name"); +} + + /* Output the public names table used to speed up access to externally visible names; or the public types table used to find type definitions. */ @@ -9156,23 +9248,14 @@ output_pubnames (vec *names) unsigned long pubnames_length = size_of_pubnames (names); pubname_ref pub; - if (!want_pubnames () || !info_section_emitted) - return; - if (names == pubname_table) - switch_to_section (debug_pubnames_section); - else - switch_to_section (debug_pubtypes_section); if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) dw2_asm_output_data (4, 0xffffffff, "Initial length escape value indicating 64-bit DWARF extension"); - if (names == pubname_table) - dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, - "Length of Public Names Info"); - else - dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, - "Length of Public Type Names Info"); - /* Version number for pubnames/pubtypes is still 2, even in DWARF3. */ + dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, "Pub Info Length"); + + /* Version number for pubnames/pubtypes is independent of dwarf version. */ dw2_asm_output_data (2, 2, "DWARF Version"); + if (dwarf_split_debug_info) dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label, debug_skeleton_info_section, @@ -9208,15 +9291,31 @@ output_pubnames (vec *names) : 0); } - dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset"); - - dw2_asm_output_nstring (pub->name, -1, "external name"); + output_pubname (die_offset, pub); } } dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL); } +/* Output public names and types tables if necessary. */ + +static void +output_pubtables (void) +{ + if (!want_pubnames () || !info_section_emitted) + return; + + switch_to_section (debug_pubnames_section); + output_pubnames (pubname_table); + /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2. + It shouldn't hurt to emit it always, since pure DWARF2 consumers + simply won't look for the section. */ + switch_to_section (debug_pubtypes_section); + output_pubnames (pubtype_table); +} + + /* Output the information that goes into the .debug_aranges table. Namely, define the beginning and ending address range of the text section generated for this compilation unit. */ @@ -24092,12 +24191,7 @@ dwarf2out_finish (const char *filename) output_location_lists (comp_unit_die ()); } - /* Output public names and types tables if necessary. */ - output_pubnames (pubname_table); - /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2. - It shouldn't hurt to emit it always, since pure DWARF2 consumers - simply won't look for the section. */ - output_pubnames (pubtype_table); + output_pubtables (); /* Output the address range information if a CU (.debug_info section) was emitted. We output an empty table even if we had no functions