For google/gcc-4_6 branch. This patch fixes several problems with -gfission: - Bad index for range list in the compile unit DIE. - DW_AT_ranges attribute for compile unit in the wrong file. - Incorrect size for skeleton type unit DIEs. - Wrote location expression using DW_OP_addr to DWO file. - Emitted skeleton debug section even when there is no debug info.
Tested: bootstrap, gcc regression tests, hand testing on -gfission test cases. include/ 2012-03-15 Sterling Augustine <saugust...@google.com> Cary Coutant <ccout...@google.com> * dwarf2.h (enum dwarf_location_atom): Add DW_OP_GNU_addr_index. gcc/ 2012-03-15 Sterling Augustine <saugust...@google.com> Cary Coutant <ccout...@google.com> * dwarf2out.c (dwarf_stack_op_name): Add DW_OP_GNU_addr_index. (size_of_loc_descr): Likewise. (output_loc_operands): Likewise. (output_loc_operands_raw): Likewise. (new_addr_loc_descr): New function. (add_AT_range_list): Store index in AT_index. (size_of_die): For range_list, use AT_index for index value. (add_top_level_skeleton_die_attrs): Don't add DW_AT_stmt_list here. (get_skeleton_type_unit): New function. (output_skeleton_debug_sections): Add comp_unit parameter; adjust caller. Don't allocate new comp unit DIE here. Move allocation of debug_skeleton_info_section_label and debug_skeleton_abbrev_section_label to dwarf2out_init. Call get_skeleton_type_unit. (output_comdat_type_unit): Remove assert; call get_skeleton_type_unit. (mem_loc_descriptor): Call new_addr_loc_desc. (loc_descriptor): Likewise. (loc_list_from_tree): Likewise. (add_const_value_attribute): Likewise. (dwarf2out_init): Allocate debug_skeleton_info_section_label and debug_skeleton_abbrev_section_label. (output_indirect_string): Check for DW_FORM_strp instead of label and refcount. (output_addr_table): Add case for dw_val_class_loc. (resolve_addr_in_expr): Handle DW_OP_addr_index. (hash_loc_operands): Likewise. (compare_loc_operands): Likewise. (dwarf2out_finish): Allocate skeleton compile unit DIE here; add range lists, DW_AT_stmt_list, and DW_AT_macro_info to it instead of dwo compile unit DIE. Output skeleton debug info section only if there is debug info. Index: include/dwarf2.h =================================================================== --- include/dwarf2.h (revision 185451) +++ include/dwarf2.h (working copy) @@ -547,6 +547,8 @@ enum dwarf_location_atom DW_OP_GNU_uninit = 0xf0, DW_OP_GNU_encoded_addr = 0xf1, DW_OP_GNU_implicit_pointer = 0xf2, + /* Extension for Fission. See http://gcc.gnu.org/wiki/DebugFission. */ + DW_OP_GNU_addr_index = 0xfb, /* HP extensions. */ DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */ DW_OP_HP_is_value = 0xe1, Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c (revision 185451) +++ gcc/dwarf2out.c (working copy) @@ -4779,6 +4779,8 @@ dwarf_stack_op_name (unsigned int op) return "DW_OP_GNU_encoded_addr"; case DW_OP_GNU_implicit_pointer: return "DW_OP_GNU_implicit_pointer"; + case DW_OP_GNU_addr_index: + return "DW_OP_GNU_addr_index"; default: return "OP_<unknown>"; @@ -4897,6 +4899,9 @@ size_of_loc_descr (dw_loc_descr_ref loc) case DW_OP_addr: size += DWARF2_ADDR_SIZE; break; + case DW_OP_GNU_addr_index: + size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); + break; case DW_OP_const1u: case DW_OP_const1s: size += 1; @@ -5275,6 +5280,11 @@ output_loc_operands (dw_loc_descr_ref lo } break; + case DW_OP_GNU_addr_index: + dw2_asm_output_data_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned, + "(address index)"); + break; + case DW_OP_GNU_implicit_pointer: { char label[MAX_ARTIFICIAL_LABEL_BYTES @@ -5343,6 +5353,7 @@ output_loc_operands_raw (dw_loc_descr_re switch (loc->dw_loc_opc) { case DW_OP_addr: + case DW_OP_GNU_addr_index: case DW_OP_implicit_value: /* We cannot output addresses in .cfi_escape, only bytes. */ gcc_unreachable (); @@ -6314,6 +6325,7 @@ static inline dw_loc_descr_ref AT_loc (d static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute, dw_loc_list_ref); static inline dw_loc_list_ref AT_loc_list (dw_attr_ref); +static unsigned int add_addr_table_entry (dw_attr_node *); static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx); static inline rtx AT_addr (dw_attr_ref); static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *); @@ -6571,6 +6583,31 @@ static bool generic_type_p (tree); static void schedule_generic_params_dies_gen (tree t); static void gen_scheduled_generic_parms_dies (void); +/* Return a pointer to a newly allocated address location description. If + dwarf_split_debug_info is true, then record the address with the appropriate + relocation. */ +static inline dw_loc_descr_ref +new_addr_loc_descr (rtx addr, int dtprel) +{ + dw_loc_descr_ref ref = new_loc_descr (DW_OP_addr, 0, 0); + + ref->dw_loc_oprnd1.val_class = dw_val_class_addr; + ref->dw_loc_oprnd1.v.val_addr = addr; + if (dwarf_split_debug_info) + { + dw_attr_node attr; + + attr.dw_attr = DW_AT_location; + attr.dw_attr_val.val_class = (dtprel + ? dw_val_class_loc : dw_val_class_addr); + attr.dw_attr_val.v.val_addr = addr; + + ref->dw_loc_opc = DW_OP_GNU_addr_index; + ref->dw_loc_oprnd1.v.val_unsigned = add_addr_table_entry (&attr); + } + return ref; +} + /* Section names used to hold DWARF debugging information. */ #ifndef DEBUG_INFO_SECTION @@ -7358,7 +7395,7 @@ AT_class (dw_attr_ref a) } /* Return the index for any attribute that will be referenced with a - DW_FORM_GNU_ref_index of DW_FORM_GNU_addr_index. Strings have their + DW_FORM_GNU_ref_index or DW_FORM_GNU_addr_index. Strings have their indices handled differently to account for reference counting pruning. */ @@ -7372,7 +7409,7 @@ AT_index (dw_attr_ref a) } /* Set the index for any attribute that will be referenced with a - DW_FORM_GNU_ref_index of DW_FORM_GNU_addr_index. */ + DW_FORM_GNU_ref_index or DW_FORM_GNU_addr_index. */ static inline void set_AT_index (dw_attr_ref a, unsigned int index) @@ -7905,7 +7942,7 @@ add_ref_table_entry (dw_attr_node *attr) return 0; } -/* Add an range_list attribute value to a DIE. */ +/* Add a range_list attribute value to a DIE. */ static void add_AT_range_list (dw_die_ref die, enum dwarf_attribute attr_kind, @@ -7919,11 +7956,12 @@ add_AT_range_list (dw_die_ref die, enum add_dwarf_attr (die, &attr); if (dwarf_split_debug_info) { + dw_attr_ref a = get_AT (die, DW_AT_ranges); + /* There will be two copies of the attr, one in the die, and one in the - ref table. Substitute the index for the actual offset in the die, and - save the actual offset in the ref table. */ - get_AT (die, DW_AT_ranges)->dw_attr_val.v.val_offset - = add_ref_table_entry (&attr); + ref table. Store the index in the die, and save the actual offset + in the ref table. */ + set_AT_index (a, add_ref_table_entry (&attr)); } } @@ -10901,14 +10939,9 @@ size_of_die (dw_die_ref die) } break; case dw_val_class_loc_list: - if (dwarf_split_debug_info) - size += size_of_uleb128 (AT_index (a)); - else - size += DWARF_OFFSET_SIZE; - break; case dw_val_class_range_list: if (dwarf_split_debug_info) - size += size_of_uleb128 (a->dw_attr_val.v.val_offset); + size += size_of_uleb128 (AT_index (a)); else size += DWARF_OFFSET_SIZE; break; @@ -11867,12 +11900,9 @@ add_AT_pubnames (dw_die_ref die) static void add_top_level_skeleton_die_attrs (dw_die_ref die) { - /* The splitter will fill in the file name. It would be good to allocate - a fairly large string here to make it easy for the splitter though. */ const char *dwo_file_name = concat (aux_base_name, ".dwo", NULL); dw_attr_ref attr; - add_AT_lineptr (die, DW_AT_stmt_list, debug_line_section_label); add_comp_dir_attribute (die); add_AT_string (die, DW_AT_GNU_dwo_name, dwo_file_name); /* The specification suggests that these attributes be inline to avoid @@ -11882,17 +11912,31 @@ add_top_level_skeleton_die_attrs (dw_die attr->dw_attr_val.v.val_str->form = DW_FORM_string; attr = get_AT (die, DW_AT_comp_dir); attr->dw_attr_val.v.val_str->form = DW_FORM_string; - /* The post compile splitter will fill in this value. */ + add_AT_pubnames (die); add_AT_lineptr (die, DW_AT_GNU_ref_base, debug_ref_section_label); add_AT_lineptr (die, DW_AT_GNU_addr_base, debug_addr_section_label); } -/* For split_debug_sections with use_type info, all type units int the skeleton - sections have identical dies (but different headers). This single die will - be output many times. */ +/* Return the single type-unit die for skeleton type units. */ -static dw_die_ref skeleton_type_unit = NULL; +static dw_die_ref +get_skeleton_type_unit (void) +{ + /* For split_debug_sections with use_type info, all type units int the + skeleton sections have identical dies (but different headers). This single + die will be output many times. */ + + static dw_die_ref skeleton_type_unit = NULL; + + if (skeleton_type_unit == NULL) + { + skeleton_type_unit = new_die (DW_TAG_type_unit, NULL, NULL); + add_top_level_skeleton_die_attrs (skeleton_type_unit); + skeleton_type_unit->die_abbrev = SKELETON_TYPE_DIE_ABBREV; + } + return skeleton_type_unit; +} /* The splitter will fill in this value. */ @@ -11901,21 +11945,19 @@ unsigned char dwo_id_placeholder[8] = { /* Output skeleton debug sections that point to the dwo file. */ static void -output_skeleton_debug_sections (void) +output_skeleton_debug_sections (dw_die_ref comp_unit) { - dw_die_ref comp_unit = gen_compile_unit_die (NULL); - /* These attributes will be found in the full debug_info section. */ remove_AT (comp_unit, DW_AT_producer); remove_AT (comp_unit, DW_AT_language); + /* Add attributes common to skeleton compile_units and type_units. */ add_top_level_skeleton_die_attrs (comp_unit); - /* Only the compilation unit gets the dwo_id. */ + + /* The dwo_id is only for compile_units. */ add_AT_data8 (comp_unit, DW_AT_GNU_dwo_id, dwo_id_placeholder); switch_to_section (debug_skeleton_info_section); - ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label, - DEBUG_SKELETON_INFO_SECTION_LABEL, 0); ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_info_section_label); /* Produce the skeleton compilation-unit header. This one differs enough from @@ -11932,8 +11974,6 @@ output_skeleton_debug_sections (void) + size_of_die (comp_unit) + 1, "Length of Compilation Unit Info"); dw2_asm_output_data (2, dwarf_version, "DWARF version number"); - ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label, - DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0); dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_abbrev_section_label, debug_abbrev_section, "Offset Into Abbrev. Section"); @@ -11950,14 +11990,7 @@ output_skeleton_debug_sections (void) output_die_abbrevs (SKELETON_COMP_DIE_ABBREV, comp_unit); if (dwarf_version >= 4) - { - /* Because all skeleton type_units have identical dies, just generate - one, and output it repeatedly. */ - skeleton_type_unit = new_die (DW_TAG_type_unit, NULL, NULL); - add_top_level_skeleton_die_attrs (skeleton_type_unit); - skeleton_type_unit->die_abbrev = SKELETON_TYPE_DIE_ABBREV; - output_die_abbrevs (SKELETON_TYPE_DIE_ABBREV, skeleton_type_unit); - } + output_die_abbrevs (SKELETON_TYPE_DIE_ABBREV, get_skeleton_type_unit ()); dw2_asm_output_data (1, 0, "end of skeleton .debug_abbrev"); } @@ -12020,7 +12053,6 @@ output_comdat_type_unit (comdat_type_nod { /* Produce the skeleton type-unit header. */ const char *secname = ".debug_types"; - gcc_assert (skeleton_type_unit); targetm.asm_out.named_section (secname, SECTION_DEBUG | SECTION_LINKONCE, @@ -12033,7 +12065,7 @@ output_comdat_type_unit (comdat_type_nod dw2_asm_output_data (DWARF_OFFSET_SIZE, DWARF_COMPILE_UNIT_HEADER_SIZE - DWARF_INITIAL_LENGTH_SIZE - + size_of_die (skeleton_type_unit) + + size_of_die (get_skeleton_type_unit ()) + DWARF_TYPE_SIGNATURE_SIZE + DWARF_OFFSET_SIZE, "Length of Type Unit Info"); dw2_asm_output_data (2, dwarf_version, "DWARF version number"); @@ -12045,7 +12077,7 @@ output_comdat_type_unit (comdat_type_nod output_signature (node->signature, "Type Signature"); dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, "Offset to Type DIE"); - output_die (skeleton_type_unit); + output_die (get_skeleton_type_unit ()); /* dw2_asm_output_data (1, 0, "end of skeleton .debug_types"); */ } } @@ -14477,9 +14509,7 @@ mem_loc_descriptor (rtx rtl, enum machin break; symref: - mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0); - mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; - mem_loc_result->dw_loc_oprnd1.v.val_addr = rtl; + mem_loc_result = new_addr_loc_descr (rtl, 0); VEC_safe_push (rtx, gc, used_rtx_array, rtl); break; @@ -15341,9 +15371,7 @@ loc_descriptor (rtx rtl, enum machine_mo if (mode != VOIDmode && GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE && (dwarf_version >= 4 || !dwarf_strict)) { - loc_result = new_loc_descr (DW_OP_addr, 0, 0); - loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; - loc_result->dw_loc_oprnd1.v.val_addr = rtl; + loc_result = new_addr_loc_descr (rtl, 0); add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0)); VEC_safe_push (rtx, gc, used_rtx_array, rtl); } @@ -16084,9 +16112,15 @@ loc_list_from_tree (tree loc, int want_a if (! CONSTANT_P (rtl)) return 0; - ret = new_loc_descr (first_op, 0, 0); - ret->dw_loc_oprnd1.val_class = dw_val_class_addr; - ret->dw_loc_oprnd1.v.val_addr = rtl; + if (dwarf_split_debug_info && first_op == DW_OP_addr) + ret = new_addr_loc_descr (rtl, dtprel); + else + { + ret = new_loc_descr (first_op, 0, 0); + ret->dw_loc_oprnd1.val_class = dw_val_class_addr; + ret->dw_loc_oprnd1.v.val_addr = rtl; + } + ret->dtprel = dtprel; ret1 = new_loc_descr (second_op, 0, 0); @@ -16134,11 +16168,7 @@ loc_list_from_tree (tree loc, int want_a return 0; } else if (CONSTANT_P (rtl) && const_ok_for_output (rtl)) - { - ret = new_loc_descr (DW_OP_addr, 0, 0); - ret->dw_loc_oprnd1.val_class = dw_val_class_addr; - ret->dw_loc_oprnd1.v.val_addr = rtl; - } + ret = new_addr_loc_descr (rtl, 0); else { enum machine_mode mode; @@ -17072,9 +17102,7 @@ add_const_value_attribute (dw_die_ref di dw_loc_descr_ref loc_result; resolve_one_addr (&rtl, NULL); rtl_addr: - loc_result = new_loc_descr (DW_OP_addr, 0, 0); - loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; - loc_result->dw_loc_oprnd1.v.val_addr = rtl; + loc_result = new_addr_loc_descr (rtl, 0); add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0)); add_AT_loc (die, DW_AT_location, loc_result); VEC_safe_push (rtx, gc, used_rtx_array, rtl); @@ -20211,7 +20239,7 @@ gen_variable_die (tree decl, tree origin { /* Optimize the common case. */ if (single_element_loc_list_p (loc) - && loc->expr->dw_loc_opc == DW_OP_addr + && loc->expr->dw_loc_opc == DW_OP_addr && loc->expr->dw_loc_next == NULL && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF) loc->expr->dw_loc_oprnd1.v.val_addr @@ -22956,6 +22984,8 @@ dwarf2out_init (const char *filename ATT SECTION_DEBUG, NULL); debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION, SECTION_DEBUG, NULL); + ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label, + DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0); /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in the main .o, but the skeleton_line goes into the split off dwo. */ @@ -22965,6 +22995,8 @@ dwarf2out_init (const char *filename ATT DEBUG_SKELETON_LINE_SECTION_LABEL, 0); debug_str_offsets_section = get_section (DEBUG_STR_OFFSETS_SECTION, SECTION_DEBUG, NULL); + ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label, + DEBUG_SKELETON_INFO_SECTION_LABEL, 0); } debug_aranges_section = get_section (DEBUG_ARANGES_SECTION, SECTION_DEBUG, NULL); @@ -23042,7 +23074,7 @@ output_indirect_string (void **h, void * { struct indirect_string_node *node = (struct indirect_string_node *) *h; - if (node->label && node->refcount) + if (node->form == DW_FORM_strp) { switch_to_section (debug_str_section); ASM_OUTPUT_LABEL (asm_out_file, node->label); @@ -23124,6 +23156,12 @@ output_addr_table (void) dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (node), "%s", name); break; + case dw_val_class_loc: + gcc_assert (targetm.asm_out.output_dwarf_dtprel); + targetm.asm_out.output_dwarf_dtprel (asm_out_file, + DWARF2_ADDR_SIZE, + AT_addr (node)); + break; case dw_val_class_lbl_id: dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (node), "%s", name); break; @@ -23629,23 +23667,32 @@ static bool resolve_addr_in_expr (dw_loc_descr_ref loc) { for (; loc; loc = loc->dw_loc_next) - if (((loc->dw_loc_opc == DW_OP_addr || loc->dtprel) - && resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL)) - || (loc->dw_loc_opc == DW_OP_implicit_value - && loc->dw_loc_oprnd2.val_class == dw_val_class_addr - && resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL))) - return false; - else if (loc->dw_loc_opc == DW_OP_GNU_implicit_pointer - && loc->dw_loc_oprnd1.val_class == dw_val_class_decl_ref) - { - dw_die_ref ref - = lookup_decl_die (loc->dw_loc_oprnd1.v.val_decl_ref); - if (ref == NULL) - return false; - loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref; - loc->dw_loc_oprnd1.v.val_die_ref.die = ref; - loc->dw_loc_oprnd1.v.val_die_ref.external = 0; - } + { + if (loc->dw_loc_opc == DW_OP_GNU_addr_index) + { + unsigned int idx = loc->dw_loc_oprnd1.v.val_unsigned; + dw_attr_node *node = VEC_index (dw_attr_node, addr_index_table, idx); + if (resolve_one_addr (&node->dw_attr_val.v.val_addr, NULL)) + return false; + } + else if (((loc->dw_loc_opc == DW_OP_addr || loc->dtprel) + && resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL)) + || (loc->dw_loc_opc == DW_OP_implicit_value + && loc->dw_loc_oprnd2.val_class == dw_val_class_addr + && resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL))) + return false; + else if (loc->dw_loc_opc == DW_OP_GNU_implicit_pointer + && loc->dw_loc_oprnd1.val_class == dw_val_class_decl_ref) + { + dw_die_ref ref + = lookup_decl_die (loc->dw_loc_oprnd1.v.val_decl_ref); + if (ref == NULL) + return false; + loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + loc->dw_loc_oprnd1.v.val_die_ref.die = ref; + loc->dw_loc_oprnd1.v.val_die_ref.external = 0; + } + } return true; } @@ -23856,6 +23903,18 @@ hash_loc_operands (dw_loc_descr_ref loc, } hash = iterative_hash_rtx (val1->v.val_addr, hash); break; + case DW_OP_GNU_addr_index: + { + dw_attr_ref attr = VEC_index (dw_attr_node, addr_index_table, + val1->v.val_unsigned); + if (loc->dtprel) + { + unsigned char dtprel = 0xd1; + hash = iterative_hash_object (dtprel, hash); + } + hash = iterative_hash_rtx (attr->dw_attr_val.v.val_addr, hash); + } + break; case DW_OP_GNU_implicit_pointer: hash = iterative_hash_object (val2->v.val_int, hash); break; @@ -24011,6 +24070,17 @@ compare_loc_operands (dw_loc_descr_ref x case DW_OP_addr: hash_addr: return rtx_equal_p (valx1->v.val_addr, valy1->v.val_addr); + case DW_OP_GNU_addr_index: + { + dw_attr_node *attrx1 = VEC_index (dw_attr_node, + addr_index_table, + valx1->v.val_unsigned); + dw_attr_node *attry1 = VEC_index (dw_attr_node, + addr_index_table, + valy1->v.val_unsigned); + return rtx_equal_p (attrx1->dw_attr_val.v.val_addr, + attry1->dw_attr_val.v.val_addr); + } case DW_OP_GNU_implicit_pointer: return valx1->val_class == dw_val_class_die_ref && valx1->val_class == valy1->val_class @@ -24133,6 +24203,15 @@ dwarf2out_finish (const char *filename) comdat_type_node *ctnode; htab_t comdat_type_table; unsigned int i; + dw_die_ref main_comp_unit_die; + + /* When splitting DWARF info, we put some attributes in the + skeleton compile_unit DIE that remains in the .o, while + most attributes go in the DWO compile_unit_die. */ + if (dwarf_split_debug_info) + main_comp_unit_die = gen_compile_unit_die (NULL); + else + main_comp_unit_die = comp_unit_die (); gen_scheduled_generic_parms_dies (); gen_remaining_tmpl_value_param_die_attribute (); @@ -24305,10 +24384,10 @@ dwarf2out_finish (const char *filename) add_AT_addr (comp_unit_die (), DW_AT_entry_pc, const0_rtx); if (text_section_used) - add_ranges_by_labels (comp_unit_die (), text_section_label, + add_ranges_by_labels (main_comp_unit_die, text_section_label, text_end_label, &range_list_added); if (cold_text_section_used) - add_ranges_by_labels (comp_unit_die (), cold_text_section_label, + add_ranges_by_labels (main_comp_unit_die, cold_text_section_label, cold_end_label, &range_list_added); for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++) @@ -24316,10 +24395,10 @@ dwarf2out_finish (const char *filename) dw_fde_ref fde = &fde_table[fde_idx]; if (!fde->in_std_section) - add_ranges_by_labels (comp_unit_die (), fde->dw_fde_begin, + add_ranges_by_labels (main_comp_unit_die, fde->dw_fde_begin, fde->dw_fde_end, &range_list_added); if (fde->dw_fde_second_begin && !fde->second_in_std_section) - add_ranges_by_labels (comp_unit_die (), fde->dw_fde_second_begin, + add_ranges_by_labels (main_comp_unit_die, fde->dw_fde_second_begin, fde->dw_fde_second_end, &range_list_added); } @@ -24328,11 +24407,11 @@ dwarf2out_finish (const char *filename) } if (generate_debug_line_table) - add_AT_lineptr (comp_unit_die (), DW_AT_stmt_list, + add_AT_lineptr (main_comp_unit_die, DW_AT_stmt_list, debug_line_section_label); if (debug_info_level >= DINFO_LEVEL_VERBOSE) - add_AT_macptr (comp_unit_die (), DW_AT_macro_info, macinfo_section_label); + add_AT_macptr (main_comp_unit_die, DW_AT_macro_info, macinfo_section_label); if (have_location_lists) { @@ -24340,15 +24419,6 @@ dwarf2out_finish (const char *filename) index_location_lists (comp_unit_die ()); } - if (dwarf_split_debug_info) - { - /* Add a place-holder for the dwo_id to the comp-unit die. Similarly, the - skeleton die gets a placeholder inside - output_skeleton_debug_sections. */ - add_AT_data8 (comp_unit_die (), DW_AT_GNU_dwo_id, dwo_id_placeholder); - output_skeleton_debug_sections (); - } - /* Output all of the compilation units. We put the main one last so that the offsets are available to output_pubnames. */ for (node = limbo_die_list; node; node = node->next) @@ -24380,10 +24450,17 @@ dwarf2out_finish (const char *filename) if (!dwarf_split_debug_info) add_AT_pubnames (comp_unit_die ()); + if (dwarf_split_debug_info) + /* Add a place-holder for the dwo_id to the comp-unit die. */ + add_AT_data8 (comp_unit_die (), DW_AT_GNU_dwo_id, dwo_id_placeholder); + /* Output the main compilation unit if non-empty or if .debug_macinfo will be emitted. */ output_comp_unit (comp_unit_die (), debug_info_level >= DINFO_LEVEL_VERBOSE); + if (dwarf_split_debug_info && info_section_emitted) + output_skeleton_debug_sections (main_comp_unit_die); + /* Output the abbreviation table. */ switch_to_section (debug_abbrev_section); ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label); @@ -24465,7 +24542,7 @@ dwarf2out_finish (const char *filename) dw2_asm_output_data (1, 0, "End compilation unit"); } - if (dwarf_split_debug_info) + if (dwarf_split_debug_info && info_section_emitted) { switch_to_section (debug_skeleton_line_section); ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_line_section_label); -- This patch is available for review at http://codereview.appspot.com/5844043