Hi, The DWARF spec says (since version 4) that DW_AT_high_pc can be represented by a constant form.
If the value of the DW_AT_high_pc is of class address, it is the relocated address of the first location past the last instruction associated with the entity; if it is of class constant, the value is an unsigned integer offset which when added to the low PC gives the address of the first location past the last instruction associated with the entity. Encoding DW_AT_high_pc as constant offset saves a lot of relocations. Which is what this patch does. I also have patches for elfutils, binutils and gdb to handle the new form. Jakub has a patch for dwz to make the format encoding optimal, which saves some space too. I couldn't figure out a way to do this from dwarf2out.c even though in almost all cases using a full DW_FORM_data4/8 is way too much. Any ideas? But even without this, I think the patch is worth it just to get rid of all the relocations necessary otherwise. At first I thought of using a dw_val_class_delta class that held two labels (a generic form of dw_val_class_vms_delta), but that seemed overkill since the first label is always associated with the DW_AT_low_pc attribute of the DIE. So I just made it a special new class. 2012-04-27 Mark Wielaard <m...@redhat.com> * dwarf2out.h (enum dw_val_class): Add dw_val_class_high_pc. * dwarf2out.c (dw_val_equal_p): Handle dw_val_class_high_pc. (add_AT_low_high_pc): New function. (AT_lbl): Handle dw_val_class_high_pc. (print_die): Likewise. (attr_checksum): Likewise. (attr_checksum_ordered): Likewise. (same_dw_val_p): Likewise. (size_of_die): Likewise. (value_format): Likewise. (output_die): Likewise. (gen_subprogram_die): Use add_AT_low_high_pc. (add_high_low_attributes): Likewise. (dwarf2out_finish): Likewise. Tested on x86_64-unknown-linux-gnu. Cheers, Mark
From 5e601bc28e283511b3f5d1bb1d2904251d909563 Mon Sep 17 00:00:00 2001 From: Mark Wielaard <m...@redhat.com> Date: Fri, 27 Apr 2012 14:27:14 +0200 Subject: [PATCH] dwarf2out.c: For DWARF 4+, output DW_AT_high_pc as constant offset. * dwarf2out.h (enum dw_val_class): Add dw_val_class_high_pc. * dwarf2out.c (dw_val_equal_p): Handle dw_val_class_high_pc. (add_AT_low_high_pc): New function. (AT_lbl): Handle dw_val_class_high_pc. (print_die): Likewise. (attr_checksum): Likewise. (attr_checksum_ordered): Likewise. (same_dw_val_p): Likewise. (size_of_die): Likewise. (value_format): Likewise. (output_die): Likewise. (gen_subprogram_die): Use add_AT_low_high_pc. (add_high_low_attributes): Likewise. (dwarf2out_finish): Likewise. --- gcc/ChangeLog | 17 +++++++++++ gcc/dwarf2out.c | 87 +++++++++++++++++++++++++++++++++++++++---------------- gcc/dwarf2out.h | 3 +- 3 files changed, 81 insertions(+), 26 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a93d3cd..66a32ad 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2012-04-27 Mark Wielaard <m...@redhat.com> + + * dwarf2out.h (enum dw_val_class): Add dw_val_class_high_pc. + * dwarf2out.c (dw_val_equal_p): Handle dw_val_class_high_pc. + (add_AT_low_high_pc): New function. + (AT_lbl): Handle dw_val_class_high_pc. + (print_die): Likewise. + (attr_checksum): Likewise. + (attr_checksum_ordered): Likewise. + (same_dw_val_p): Likewise. + (size_of_die): Likewise. + (value_format): Likewise. + (output_die): Likewise. + (gen_subprogram_die): Use add_AT_low_high_pc. + (add_high_low_attributes): Likewise. + (dwarf2out_finish): Likewise. + 2012-04-25 Jakub Jelinek <ja...@redhat.com> PR target/53110 diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 766edba..fa2963b 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -1647,6 +1647,7 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b) 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_high_pc: return strcmp (a->v.val_lbl_id, b->v.val_lbl_id) == 0; case dw_val_class_str: return a->v.val_str == b->v.val_str; @@ -4350,6 +4351,26 @@ add_AT_data8 (dw_die_ref die, enum dwarf_attribute attr_kind, add_dwarf_attr (die, &attr); } +/* Add DW_AT_low_pc and DW_AT_high_pc to a DIE. */ +static inline void +add_AT_low_high_pc (dw_die_ref die, const char *lbl_low, const char *lbl_high) +{ + dw_attr_node attr; + + attr.dw_attr = DW_AT_low_pc; + attr.dw_attr_val.val_class = dw_val_class_lbl_id; + attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_low); + add_dwarf_attr (die, &attr); + + attr.dw_attr = DW_AT_high_pc; + if (dwarf_version < 3) + attr.dw_attr_val.val_class = dw_val_class_lbl_id; + else + attr.dw_attr_val.val_class = dw_val_class_high_pc; + attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_high); + add_dwarf_attr (die, &attr); +} + /* Hash and equality functions for debug_str_hash. */ static hashval_t @@ -4723,7 +4744,8 @@ AT_lbl (dw_attr_ref 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_macptr + || AT_class (a) == dw_val_class_high_pc)); return a->dw_attr_val.v.val_lbl_id; } @@ -5602,6 +5624,7 @@ print_die (dw_die_ref die, FILE *outfile) case dw_val_class_lbl_id: case dw_val_class_lineptr: case dw_val_class_macptr: + case dw_val_class_high_pc: fprintf (outfile, "label: %s", AT_lbl (a)); break; case dw_val_class_str: @@ -5758,6 +5781,7 @@ attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark) case dw_val_class_lbl_id: case dw_val_class_lineptr: case dw_val_class_macptr: + case dw_val_class_high_pc: break; case dw_val_class_file: @@ -6030,6 +6054,7 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at, case dw_val_class_lbl_id: case dw_val_class_lineptr: case dw_val_class_macptr: + case dw_val_class_high_pc: break; case dw_val_class_file: @@ -6489,6 +6514,7 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark) case dw_val_class_lbl_id: case dw_val_class_lineptr: case dw_val_class_macptr: + case dw_val_class_high_pc: return 1; case dw_val_class_file: @@ -7780,6 +7806,9 @@ size_of_die (dw_die_ref die) case dw_val_class_vms_delta: size += DWARF_OFFSET_SIZE; break; + case dw_val_class_high_pc: + size += DWARF2_ADDR_SIZE; + break; default: gcc_unreachable (); } @@ -8097,6 +8126,17 @@ value_format (dw_attr_ref a) case dw_val_class_data8: return DW_FORM_data8; + case dw_val_class_high_pc: + switch (DWARF2_ADDR_SIZE) + { + case 4: + return DW_FORM_data4; + case 8: + return DW_FORM_data8; + default: + gcc_unreachable (); + } + default: gcc_unreachable (); } @@ -8521,6 +8561,11 @@ output_die (dw_die_ref die) break; } + case dw_val_class_high_pc: + dw2_asm_output_delta (DWARF2_ADDR_SIZE, AT_lbl (a), + get_AT_low_pc (die), "DW_AT_high_pc"); + break; + default: gcc_unreachable (); } @@ -17310,19 +17355,18 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) if (fde->dw_fde_begin) { /* We have already generated the labels. */ - add_AT_lbl_id (subr_die, DW_AT_low_pc, fde->dw_fde_begin); - add_AT_lbl_id (subr_die, DW_AT_high_pc, fde->dw_fde_end); + add_AT_low_high_pc (subr_die, fde->dw_fde_begin, fde->dw_fde_end); } else { /* Create start/end labels and add the range. */ - char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; - ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL, + char label_id_low[MAX_ARTIFICIAL_LABEL_BYTES]; + char label_id_high[MAX_ARTIFICIAL_LABEL_BYTES]; + ASM_GENERATE_INTERNAL_LABEL (label_id_low, FUNC_BEGIN_LABEL, current_function_funcdef_no); - add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id); - ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, + ASM_GENERATE_INTERNAL_LABEL (label_id_high, FUNC_END_LABEL, current_function_funcdef_no); - add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id); + add_AT_low_high_pc (subr_die, label_id_low, label_id_high); } #if VMS_DEBUGGING_INFO @@ -17388,10 +17432,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) dw_die_ref seg_die; /* Do the 'primary' section. */ - add_AT_lbl_id (subr_die, DW_AT_low_pc, - fde->dw_fde_begin); - add_AT_lbl_id (subr_die, DW_AT_high_pc, - fde->dw_fde_end); + add_AT_low_high_pc (subr_die, fde->dw_fde_begin, + fde->dw_fde_end); /* Add it. */ add_pubname (decl, subr_die); @@ -17417,18 +17459,15 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) add_AT_flag (seg_die, DW_AT_artificial, 1); name = concat ("__second_sect_of_", name, NULL); - add_AT_lbl_id (seg_die, DW_AT_low_pc, - fde->dw_fde_second_begin); - add_AT_lbl_id (seg_die, DW_AT_high_pc, - fde->dw_fde_second_end); + add_AT_low_high_pc (seg_die, fde->dw_fde_second_begin, + fde->dw_fde_second_end); add_name_attribute (seg_die, name); add_pubname_string (name, seg_die); } } else { - add_AT_lbl_id (subr_die, DW_AT_low_pc, fde->dw_fde_begin); - add_AT_lbl_id (subr_die, DW_AT_high_pc, fde->dw_fde_end); + add_AT_low_high_pc (subr_die, fde->dw_fde_begin, fde->dw_fde_end); add_pubname (decl, subr_die); } } @@ -18166,12 +18205,12 @@ add_high_low_attributes (tree stmt, dw_die_ref die) } else { + char label_high[MAX_ARTIFICIAL_LABEL_BYTES]; ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, BLOCK_NUMBER (stmt)); - add_AT_lbl_id (die, DW_AT_low_pc, label); - ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, + ASM_GENERATE_INTERNAL_LABEL (label_high, BLOCK_END_LABEL, BLOCK_NUMBER (stmt)); - add_AT_lbl_id (die, DW_AT_high_pc, label); + add_AT_low_high_pc (die, label, label_high); } } @@ -22635,10 +22674,8 @@ dwarf2out_finish (const char *filename) { /* Don't add if the CU has no associated code. */ if (text_section_used) - { - add_AT_lbl_id (comp_unit_die (), DW_AT_low_pc, text_section_label); - add_AT_lbl_id (comp_unit_die (), DW_AT_high_pc, text_end_label); - } + add_AT_low_high_pc (comp_unit_die (), text_section_label, + text_end_label); } else { diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h index 711e8ab..da3a578 100644 --- a/gcc/dwarf2out.h +++ b/gcc/dwarf2out.h @@ -154,7 +154,8 @@ enum dw_val_class dw_val_class_file, dw_val_class_data8, dw_val_class_decl_ref, - dw_val_class_vms_delta + dw_val_class_vms_delta, + dw_val_class_high_pc }; /* Describe a floating point constant value, or a vector constant value. */ -- 1.7.7.6