Hi! This patch adds .debug_loclists and .debug_loclists.dwo support for -gdwarf-5 and -gdwarf-5 -gsplit-dwarf. The decrease of section size from .debug_loc section to .debug_loclists is really nice.
The patch doesn't handle -gdwarf-5 -gsplit-dwarf on targets where assembler doesn't support .uleb128, because in that case we really can't use DW_LLE_startx_length (no way to emit uleb128 region sizes - we don't have accurate instruction length computations) - we should use DW_LLE_startx_endx in that case, but would need .debug_addr entries not just for the region starts, but ends. Cary, could you resolve this incrementally (and, do you plan to convert other -gsplit-dwarf support parts to DWARF 5 for -gdwarf-5)? Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-10-20 Jakub Jelinek <ja...@redhat.com> * dwarf2out.h (enum dw_val_class): Add dw_val_class_loclistsptr. * dwarf2out.c (struct dw_loc_list_struct): Change emitted field from bool to 1-bit uchar bitfield. Add num_assigned and offset_emitted bitfields. (dw_val_equal_p): Compare v.val_lbl_id rather than v.val_unsigned for dw_val_class_lineptr and dw_val_class_macptr. Handle dw_val_class_loclistsptr. (new_addr_loc_descr): Fix up formatting. (DEBUG_LOCLISTS_SECTION, DEBUG_DWO_LOCLISTS_SECTION): Define. (add_AT_low_high_pc): Fix up formatting. (add_AT_loclistsptr): New function. (AT_lbl): Allow dw_val_class_loclistsptr. (print_dw_val, attr_checksum, attr_checksum_ordered, same_dw_val_p): Handle dw_val_class_loclistsptr. (loc_list_idx): New variable. (output_loclists_offsets): New function. (size_of_die): For dw_val_class_loc_list -gsplit-dwarf -gdwarf-5 add size_of_uleb128 of the index. Drop never used dwarf_split_debug_info AT_index handling. Handle dw_val_class_loclistsptr. (value_format): Return DW_FORM_loclistsx for dw_val_class_loc_list if -gsplit-dwarf -gdwarf-5. Handle dw_val_class_loclistsptr. (output_loc_list): Handle DWARF 5 .debug_loclists* format. (output_loc_list_offset): Handle -gsplit-dwarf -gdwarf-5 DW_FORM_loclistx indexes. (output_attr_index_or_value): Fix up formatting. Don't handle dw_val_class_loc_list here. (output_die): Formatting fixes. Handle dw_val_class_loclistsptr. For dw_val_class_loc_list call output_loc_list_offset rather than output_attr_index_or_value. (init_sections_and_labels): For -gdwarf-5 use .debug_loclists or .debug_loclists.dwo section name for debug_loc_section. (resolve_addr_in_expr): Formatting fix. (index_location_lists): Likewise. (assign_location_list_indexes): New function. (dwarf2out_finish): If there are any location lists, for -gsplit-dwarf -gdwarf-5 add DW_AT_loclists_base attribute. Call index_location_lists only if have_location_lists. Call assign_location_list_indexes for -gsplit-dwarf -gdwarf-5. Emit .debug_loclists{,.dwo} section header for -gdwarf-5, for -gdwarf-5 -gsplit-dwarf also emit offset table. --- gcc/dwarf2out.h.jj 2016-10-18 08:17:19.000000000 +0200 +++ gcc/dwarf2out.h 2016-10-19 23:09:53.456786659 +0200 @@ -147,6 +147,7 @@ enum dw_val_class dw_val_class_lineptr, dw_val_class_str, dw_val_class_macptr, + dw_val_class_loclistsptr, dw_val_class_file, dw_val_class_data8, dw_val_class_decl_ref, --- gcc/dwarf2out.c.jj 2016-10-19 14:37:23.000000000 +0200 +++ gcc/dwarf2out.c 2016-10-19 23:15:44.280352083 +0200 @@ -1279,7 +1279,13 @@ typedef struct GTY(()) dw_loc_list_struc bool resolved_addr; /* True if this list has been replaced by dw_loc_next. */ bool replaced; - bool emitted; + /* True if it has been emitted into .debug_loc* / .debug_loclists* + section. */ + unsigned char emitted : 1; + /* True if hash field is index rather than hash value. */ + unsigned char num_assigned : 1; + /* True if .debug_loclists.dwo offset has been emitted for it already. */ + unsigned char offset_emitted : 1; /* True if the range should be emitted even if begin and end are the same. */ bool force; @@ -1367,8 +1373,6 @@ dw_val_equal_p (dw_val_node *a, dw_val_n case dw_val_class_unsigned_const: case dw_val_class_const: case dw_val_class_range_list: - case dw_val_class_lineptr: - case dw_val_class_macptr: /* These are all HOST_WIDE_INT, signed or unsigned. */ return a->v.val_unsigned == b->v.val_unsigned; @@ -1381,6 +1385,9 @@ dw_val_equal_p (dw_val_node *a, dw_val_n case dw_val_class_fde_ref: return a->v.val_fde_index == b->v.val_fde_index; case dw_val_class_lbl_id: + case dw_val_class_lineptr: + case dw_val_class_macptr: + case dw_val_class_loclistsptr: case dw_val_class_high_pc: return strcmp (a->v.val_lbl_id, b->v.val_lbl_id) == 0; case dw_val_class_str: @@ -3180,6 +3187,8 @@ static inline rtx AT_addr (dw_attr_node static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *); static void add_AT_lineptr (dw_die_ref, enum dwarf_attribute, const char *); static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *); +static void add_AT_loclistsptr (dw_die_ref, enum dwarf_attribute, + const char *); static void add_AT_offset (dw_die_ref, enum dwarf_attribute, unsigned HOST_WIDE_INT); static void add_AT_range_list (dw_die_ref, enum dwarf_attribute, @@ -3480,8 +3489,8 @@ new_addr_loc_descr (rtx addr, enum dtpre ref->dtprel = dtprel; if (dwarf_split_debug_info) ref->dw_loc_oprnd1.val_entry - = add_addr_table_entry (addr, - dtprel ? ate_kind_rtx_dtprel : ate_kind_rtx); + = add_addr_table_entry (addr, + dtprel ? ate_kind_rtx_dtprel : ate_kind_rtx); else ref->dw_loc_oprnd1.val_entry = NULL; @@ -3532,6 +3541,12 @@ new_addr_loc_descr (rtx addr, enum dtpre #ifndef DEBUG_DWO_LOC_SECTION #define DEBUG_DWO_LOC_SECTION ".debug_loc.dwo" #endif +#ifndef DEBUG_LOCLISTS_SECTION +#define DEBUG_LOCLISTS_SECTION ".debug_loclists" +#endif +#ifndef DEBUG_DWO_LOCLISTS_SECTION +#define DEBUG_DWO_LOCLISTS_SECTION ".debug_loclists.dwo" +#endif #ifndef DEBUG_PUBNAMES_SECTION #define DEBUG_PUBNAMES_SECTION \ ((debug_generate_pub_sections == 2) \ @@ -4036,7 +4051,7 @@ add_AT_low_high_pc (dw_die_ref die, cons attr.dw_attr_val.v.val_lbl_id = lbl_id; if (dwarf_split_debug_info && !force_direct) attr.dw_attr_val.val_entry - = add_addr_table_entry (lbl_id, ate_kind_label); + = add_addr_table_entry (lbl_id, ate_kind_label); else attr.dw_attr_val.val_entry = NULL; add_dwarf_attr (die, &attr); @@ -4051,7 +4066,7 @@ add_AT_low_high_pc (dw_die_ref die, cons if (attr.dw_attr_val.val_class == dw_val_class_lbl_id && dwarf_split_debug_info && !force_direct) attr.dw_attr_val.val_entry - = add_addr_table_entry (lbl_id, ate_kind_label); + = add_addr_table_entry (lbl_id, ate_kind_label); else attr.dw_attr_val.val_entry = NULL; add_dwarf_attr (die, &attr); @@ -4587,6 +4602,22 @@ add_AT_lineptr (dw_die_ref die, enum dwa } /* Add a section offset attribute value to a DIE, an offset into the + debug_loclists section. */ + +static inline void +add_AT_loclistsptr (dw_die_ref die, enum dwarf_attribute attr_kind, + const char *label) +{ + dw_attr_node attr; + + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_loclistsptr; + attr.dw_attr_val.val_entry = NULL; + attr.dw_attr_val.v.val_lbl_id = xstrdup (label); + add_dwarf_attr (die, &attr); +} + +/* Add a section offset attribute value to a DIE, an offset into the debug_macinfo section. */ static inline void @@ -4668,6 +4699,7 @@ AT_lbl (dw_attr_node *a) gcc_assert (a && (AT_class (a) == dw_val_class_lbl_id || AT_class (a) == dw_val_class_lineptr || AT_class (a) == dw_val_class_macptr + || AT_class (a) == dw_val_class_loclistsptr || AT_class (a) == dw_val_class_high_pc)); return a->dw_attr_val.v.val_lbl_id; } @@ -5665,6 +5697,7 @@ print_dw_val (dw_val_node *val, bool rec case dw_val_class_lbl_id: case dw_val_class_lineptr: case dw_val_class_macptr: + case dw_val_class_loclistsptr: case dw_val_class_high_pc: fprintf (outfile, "label: %s", val->v.val_lbl_id); break; @@ -6053,6 +6086,7 @@ attr_checksum (dw_attr_node *at, struct case dw_val_class_lbl_id: case dw_val_class_lineptr: case dw_val_class_macptr: + case dw_val_class_loclistsptr: case dw_val_class_high_pc: break; @@ -6345,6 +6379,7 @@ attr_checksum_ordered (enum dwarf_tag ta case dw_val_class_lbl_id: case dw_val_class_lineptr: case dw_val_class_macptr: + case dw_val_class_loclistsptr: case dw_val_class_high_pc: break; @@ -6838,6 +6873,7 @@ same_dw_val_p (const dw_val_node *v1, co case dw_val_class_lbl_id: case dw_val_class_lineptr: case dw_val_class_macptr: + case dw_val_class_loclistsptr: case dw_val_class_high_pc: return 1; @@ -8118,6 +8154,36 @@ output_location_lists (dw_die_ref die) FOR_EACH_CHILD (die, c, output_location_lists (c)); } +/* During assign_location_list_indexes and output_loclists_offset the + current index, after it the number of assigned indexes (i.e. how + large the .debug_loclists* offset table should be). */ +static unsigned int loc_list_idx; + +/* Output all location list offsets for the DIE and its children. */ + +static void +output_loclists_offsets (dw_die_ref die) +{ + dw_die_ref c; + dw_attr_node *a; + unsigned ix; + + FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a) + if (AT_class (a) == dw_val_class_loc_list) + { + dw_loc_list_ref l = AT_loc_list (a); + if (l->offset_emitted) + continue; + dw2_asm_output_delta (DWARF_OFFSET_SIZE, l->ll_symbol, + loc_section_label, NULL); + gcc_assert (l->hash == loc_list_idx); + loc_list_idx++; + l->offset_emitted = true; + } + + FOR_EACH_CHILD (die, c, output_loclists_offsets (c)); +} + /* We want to limit the number of external references, because they are larger than local references: a relocation takes multiple words, and even a sig8 reference is always eight bytes, whereas a local reference @@ -8418,11 +8484,11 @@ size_of_die (dw_die_ref die) } break; case dw_val_class_loc_list: - if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED) - { - gcc_assert (AT_index (a) != NO_INDEX_ASSIGNED); - size += size_of_uleb128 (AT_index (a)); - } + if (dwarf_split_debug_info && dwarf_version >= 5) + { + gcc_assert (AT_loc_list (a)->num_assigned); + size += size_of_uleb128 (AT_loc_list (a)->hash); + } else size += DWARF_OFFSET_SIZE; break; @@ -8504,7 +8570,8 @@ size_of_die (dw_die_ref die) break; case dw_val_class_lineptr: case dw_val_class_macptr: - size += DWARF_OFFSET_SIZE; + case dw_val_class_loclistsptr: + size += DWARF_OFFSET_SIZE; break; case dw_val_class_str: form = AT_string_form (a); @@ -8769,8 +8836,13 @@ value_format (dw_attr_node *a) default: gcc_unreachable (); } - case dw_val_class_range_list: case dw_val_class_loc_list: + if (dwarf_split_debug_info + && dwarf_version >= 5 + && AT_loc_list (a)->num_assigned) + return DW_FORM_loclistx; + /* FALLTHRU */ + case dw_val_class_range_list: if (dwarf_version >= 4) return DW_FORM_sec_offset; /* FALLTHRU */ @@ -8888,6 +8960,7 @@ value_format (dw_attr_node *a) ? DW_FORM_addr : DW_FORM_GNU_addr_index); case dw_val_class_lineptr: case dw_val_class_macptr: + case dw_val_class_loclistsptr: return dwarf_version >= 4 ? DW_FORM_sec_offset : DW_FORM_data; case dw_val_class_str: return AT_string_form (a); @@ -9052,14 +9125,18 @@ gen_llsym (dw_loc_list_ref list) static void output_loc_list (dw_loc_list_ref list_head) { - dw_loc_list_ref curr = list_head; - if (list_head->emitted) return; list_head->emitted = true; ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol); + dw_loc_list_ref curr = list_head; +#ifdef HAVE_AS_LEB128 + const char *last_section = NULL; + const char *base_label = NULL; +#endif + /* Walk the location list, and output each range + expression. */ for (curr = list_head; curr != NULL; curr = curr->dw_loc_next) { @@ -9074,21 +9151,120 @@ output_loc_list (dw_loc_list_ref list_he in a single range are unlikely very useful. */ if (size > 0xffff) continue; - if (dwarf_split_debug_info) - { - dw2_asm_output_data (1, DW_LLE_GNU_start_length_entry, - "Location list start/length entry (%s)", - list_head->ll_symbol); - dw2_asm_output_data_uleb128 (curr->begin_entry->index, - "Location list range start index (%s)", - curr->begin); - /* The length field is 4 bytes. If we ever need to support - an 8-byte length, we can add a new DW_LLE code or fall back - to DW_LLE_GNU_start_end_entry. */ - dw2_asm_output_delta (4, curr->end, curr->begin, - "Location list range length (%s)", - list_head->ll_symbol); - } + if (dwarf_version >= 5) + { + if (dwarf_split_debug_info) + { + dw2_asm_output_data (1, DW_LLE_startx_length, + "DW_LLE_startx_length (%s)", + list_head->ll_symbol); + dw2_asm_output_data_uleb128 (curr->begin_entry->index, + "Location list range start index " + "(%s)", curr->begin); + /* FIXME: This will ICE ifndef HAVE_AS_LEB128. + For that case we probably need to emit DW_LLE_startx_endx, + but we'd need 2 .debug_addr entries rather than just one. */ + dw2_asm_output_delta_uleb128 (curr->end, curr->begin, + "Location list length (%s)", + list_head->ll_symbol); + } +#ifdef HAVE_AS_LEB128 + else if (!have_multiple_function_sections) + { + dw2_asm_output_data (1, DW_LLE_offset_pair, + "DW_LLE_offset_pair (%s)", + list_head->ll_symbol); + dw2_asm_output_delta_uleb128 (curr->begin, curr->section, + "Location list begin address (%s)", + list_head->ll_symbol); + dw2_asm_output_delta_uleb128 (curr->end, curr->section, + "Location list end address (%s)", + list_head->ll_symbol); + } + else + { + if (last_section == NULL || curr->section != last_section) + { + dw_loc_list_ref curr2; + for (curr2 = curr->dw_loc_next; curr2 != NULL; + curr2 = curr2->dw_loc_next) + { + if (strcmp (curr2->begin, curr2->end) == 0 + && !curr2->force) + continue; + if ((unsigned long) size_of_locs (curr2->expr) > 0xffff) + continue; + break; + } + if (curr2 == NULL || curr->section != curr2->section) + last_section = NULL; + else + { + last_section = curr->section; + base_label = curr->begin; + dw2_asm_output_data (1, DW_LLE_base_address, + "DW_LLE_base_address (%s)", + list_head->ll_symbol); + dw2_asm_output_addr (DWARF2_ADDR_SIZE, base_label, + "Base address (%s)", + list_head->ll_symbol); + } + } + if (last_section == NULL) + { + dw2_asm_output_data (1, DW_LLE_start_length, + "DW_LLE_start_length (%s)", + list_head->ll_symbol); + dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->begin, + "Location list begin address (%s)", + list_head->ll_symbol); + dw2_asm_output_delta_uleb128 (curr->end, curr->begin, + "Location list length " + "(%s)", list_head->ll_symbol); + } + else + { + dw2_asm_output_data (1, DW_LLE_offset_pair, + "DW_LLE_offset_pair (%s)", + list_head->ll_symbol); + dw2_asm_output_delta_uleb128 (curr->begin, base_label, + "Location list begin address " + "(%s)", list_head->ll_symbol); + dw2_asm_output_delta_uleb128 (curr->end, base_label, + "Location list end address " + "(%s)", list_head->ll_symbol); + } + } +#else + else + { + dw2_asm_output_data (1, DW_LLE_start_end, + "DW_LLE_start_end (%s)", + list_head->ll_symbol); + dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->begin, + "Location list begin address (%s)", + list_head->ll_symbol); + dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->end, + "Location list end address (%s)", + list_head->ll_symbol); + } +#endif + } + else if (dwarf_split_debug_info) + { + dw2_asm_output_data (1, DW_LLE_GNU_start_length_entry, + "Location list start/length entry (%s)", + list_head->ll_symbol); + dw2_asm_output_data_uleb128 (curr->begin_entry->index, + "Location list range start index (%s)", + curr->begin); + /* The length field is 4 bytes. If we ever need to support + an 8-byte length, we can add a new DW_LLE code or fall back + to DW_LLE_GNU_start_end_entry. */ + dw2_asm_output_delta (4, curr->end, curr->begin, + "Location list range length (%s)", + list_head->ll_symbol); + } else if (!have_multiple_function_sections) { dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section, @@ -9115,18 +9291,21 @@ output_loc_list (dw_loc_list_ref list_he output_loc_sequence (curr->expr, -1); } - if (dwarf_split_debug_info) + if (dwarf_version >= 5) + dw2_asm_output_data (1, DW_LLE_end_of_list, + "DW_LLE_end_of_list (%s)", list_head->ll_symbol); + else if (dwarf_split_debug_info) dw2_asm_output_data (1, DW_LLE_GNU_end_of_list_entry, - "Location list terminator (%s)", - list_head->ll_symbol); + "Location list terminator (%s)", + list_head->ll_symbol); else { dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, - "Location list terminator begin (%s)", - list_head->ll_symbol); + "Location list terminator begin (%s)", + list_head->ll_symbol); dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, - "Location list terminator end (%s)", - list_head->ll_symbol); + "Location list terminator end (%s)", + list_head->ll_symbol); } } @@ -9160,12 +9339,19 @@ output_loc_list_offset (dw_attr_node *a) char *sym = AT_loc_list (a)->ll_symbol; gcc_assert (sym); - if (dwarf_split_debug_info) - dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label, - "%s", dwarf_attr_name (a->dw_attr)); - else + if (!dwarf_split_debug_info) dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section, "%s", dwarf_attr_name (a->dw_attr)); + else if (dwarf_version >= 5) + { + gcc_assert (AT_loc_list (a)->num_assigned); + dw2_asm_output_data_uleb128 (AT_loc_list (a)->hash, "%s (%s)", + dwarf_attr_name (a->dw_attr), + sym); + } + else + dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label, + "%s", dwarf_attr_name (a->dw_attr)); } /* Output an attribute's index or value appropriately. */ @@ -9182,18 +9368,15 @@ output_attr_index_or_value (dw_attr_node } switch (AT_class (a)) { - case dw_val_class_addr: - dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name); - break; - case dw_val_class_high_pc: - case dw_val_class_lbl_id: - dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name); - break; - case dw_val_class_loc_list: - output_loc_list_offset (a); - break; - default: - gcc_unreachable (); + case dw_val_class_addr: + dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name); + break; + case dw_val_class_high_pc: + case dw_val_class_lbl_id: + dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name); + break; + default: + gcc_unreachable (); } } @@ -9384,7 +9567,7 @@ output_die (dw_die_ref die) break; case dw_val_class_loc_list: - output_attr_index_or_value (a); + output_loc_list_offset (a); break; case dw_val_class_die_ref: @@ -9392,8 +9575,8 @@ output_die (dw_die_ref die) { if (AT_ref (a)->comdat_type_p) { - comdat_type_node *type_node = - AT_ref (a)->die_id.die_type_node; + comdat_type_node *type_node + = AT_ref (a)->die_id.die_type_node; gcc_assert (type_node); output_signature (type_node->signature, name); @@ -9447,7 +9630,7 @@ output_die (dw_die_ref die) break; case dw_val_class_lbl_id: - output_attr_index_or_value (a); + output_attr_index_or_value (a); break; case dw_val_class_lineptr: @@ -9460,6 +9643,11 @@ output_die (dw_die_ref die) debug_macinfo_section, "%s", name); break; + case dw_val_class_loclistsptr: + dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a), + debug_loc_section, "%s", name); + break; + case dw_val_class_str: if (a->dw_attr_val.v.val_str->form == DW_FORM_strp) dw2_asm_output_offset (DWARF_OFFSET_SIZE, @@ -25811,7 +25999,9 @@ init_sections_and_labels (void) SECTION_DEBUG, NULL); debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION, SECTION_DEBUG, NULL); - debug_loc_section = get_section (DEBUG_LOC_SECTION, + debug_loc_section = get_section (dwarf_version >= 5 + ? DEBUG_LOCLISTS_SECTION + : DEBUG_LOC_SECTION, SECTION_DEBUG, NULL); debug_macinfo_section_name = dwarf_strict ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION; @@ -25846,7 +26036,9 @@ init_sections_and_labels (void) NULL); ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label, DEBUG_SKELETON_INFO_SECTION_LABEL, 0); - debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION, + debug_loc_section = get_section (dwarf_version >= 5 + ? DEBUG_DWO_LOCLISTS_SECTION + : DEBUG_DWO_LOC_SECTION, SECTION_DEBUG | SECTION_EXCLUDE, NULL); debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION, DEBUG_STR_DWO_SECTION_FLAGS, NULL); @@ -26955,8 +27147,8 @@ resolve_addr_in_expr (dw_loc_descr_ref l if (!resolve_one_addr (&rtl)) return false; remove_addr_table_entry (loc->dw_loc_oprnd1.val_entry); - loc->dw_loc_oprnd1.val_entry = - add_addr_table_entry (rtl, ate_kind_rtx); + loc->dw_loc_oprnd1.val_entry + = add_addr_table_entry (rtl, ate_kind_rtx); } break; case DW_OP_const4u: @@ -28014,14 +28206,36 @@ index_location_lists (dw_die_ref die) continue; curr->begin_entry - = add_addr_table_entry (xstrdup (curr->begin), - ate_kind_label); + = add_addr_table_entry (xstrdup (curr->begin), ate_kind_label); } } FOR_EACH_CHILD (die, c, index_location_lists (c)); } +/* Recursively set indexes of location lists. */ + +static void +assign_location_list_indexes (dw_die_ref die) +{ + dw_die_ref c; + dw_attr_node *a; + unsigned ix; + + FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a) + if (AT_class (a) == dw_val_class_loc_list) + { + dw_loc_list_ref list = AT_loc_list (a); + if (!list->num_assigned) + { + list->num_assigned = true; + list->hash = loc_list_idx++; + } + } + + FOR_EACH_CHILD (die, c, assign_location_list_indexes (c)); +} + /* Optimize location lists referenced from DIE children and share them whenever possible. */ @@ -28223,12 +28437,18 @@ dwarf2out_finish (const char *) if (dwarf_split_debug_info) { - /* optimize_location_lists calculates the size of the lists, - so index them first, and assign indices to the entries. - Although optimize_location_lists will remove entries from - the table, it only does so for duplicates, and therefore - only reduces ref_counts to 1. */ - index_location_lists (comp_unit_die ()); + if (have_location_lists) + { + if (dwarf_version >= 5) + add_AT_loclistsptr (comp_unit_die (), DW_AT_loclists_base, + loc_section_label); + /* optimize_location_lists calculates the size of the lists, + so index them first, and assign indices to the entries. + Although optimize_location_lists will remove entries from + the table, it only does so for duplicates, and therefore + only reduces ref_counts to 1. */ + index_location_lists (comp_unit_die ()); + } if (addr_index_table != NULL) { @@ -28239,8 +28459,14 @@ dwarf2out_finish (const char *) } } + loc_list_idx = 0; if (have_location_lists) - optimize_location_lists (comp_unit_die ()); + { + optimize_location_lists (comp_unit_die ()); + /* And finally assign indexes to the entries for -gsplit-dwarf. */ + if (dwarf_version >= 5 && dwarf_split_debug_info) + assign_location_list_indexes (comp_unit_die ()); + } save_macinfo_strings (); @@ -28338,10 +28564,39 @@ dwarf2out_finish (const char *) /* Output location list section if necessary. */ if (have_location_lists) { + char l1[MAX_ARTIFICIAL_LABEL_BYTES]; + char l2[MAX_ARTIFICIAL_LABEL_BYTES]; /* Output the location lists info. */ switch_to_section (debug_loc_section); + if (dwarf_version >= 5) + { + ASM_GENERATE_INTERNAL_LABEL (l1, DEBUG_LOC_SECTION_LABEL, 1); + ASM_GENERATE_INTERNAL_LABEL (l2, DEBUG_LOC_SECTION_LABEL, 2); + if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating " + "64-bit DWARF extension"); + dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1, + "Length of Location Lists"); + ASM_OUTPUT_LABEL (asm_out_file, l1); + dw2_asm_output_data (2, dwarf_version, "DWARF Version"); + dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size"); + dw2_asm_output_data (1, 0, "Segment Size"); + if (dwarf_split_debug_info) + dw2_asm_output_data (4, dwarf_split_debug_info ? loc_list_idx : 0, + "Offset Entry Count"); + } ASM_OUTPUT_LABEL (asm_out_file, loc_section_label); + if (dwarf_version >= 5 && dwarf_split_debug_info) + { + unsigned int save_loc_list_idx = loc_list_idx; + loc_list_idx = 0; + output_loclists_offsets (comp_unit_die ()); + gcc_assert (save_loc_list_idx == loc_list_idx); + } output_location_lists (comp_unit_die ()); + if (dwarf_version >= 5) + ASM_OUTPUT_LABEL (asm_out_file, l2); } output_pubtables (); Jakub