[PATCH] Location lists, with dwarf 2.1 support

Daniel Berlin dan@www.cgsoftware.com
Tue Apr 24 09:42:00 GMT 2001


As requested by jason, i have added dwarf 2.1 support.

Please ignore the is_symbol_die change, it's not supposed to be there,
but i really don't want to redo this diff to remove 5 lines of code.

Also, i'm assuming i'll get rid of the FIXME about the maximum address
before i check it in, if approved, just as soon as somene tells me what
the right thing to do is.

I didn't check in the old version, since  2.1 support forces a change to
the interface of the loc list createion stuff (So you can specify the
section to base the addresses on).

2001-04-12  Daniel Berlin  <dan@cgsoftware.com>

	* dwarf2out.c: Add dw_loc_list_ref, a reference to a location
	list.
	Add have_location_lists, a variable to determine whether we need a
	.debug_loc section or not.
	(enum dw_val_class): Add dw_val_class_loc_list.
	(dw_val_struct): Add val_loc_list.
	(dw_loc_list_struct): New structure, represents location lists.
	(new_loc_list): New function, return a new location list, given
	the range and location expression.
	(add_loc_descr_to_loc_list): New function, add a location
	expression to a location list, given the expression and range.
	(output_loc_list): New function, output a location list.
	(gen_internal_sym): Modified to take symbol prefix, so we can
	reuse it for location list symbols.
	(add_AT_loc_list): New function, add a location list to a DIE at
	the named attribute.
	(AT_loc_list): New function, return the location list reference
	for a given attribute, if it's a location list.
	(print_die): Handle dw_val_class_loc_list.
	(size_of_die): Ditto.
	(value_format): Ditto.
	(output_die): Ditto.
	(output_location_lists): New function, output all of the location
	lists for a DIE and it's children.
	(dwarf2out_finish): Call output_location_lists if we have location
	lists.


Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarf2out.c,v
retrieving revision 1.263
diff -c -3 -p -w -B -b -r1.263 dwarf2out.c
*** dwarf2out.c	2001/04/12 01:44:21	1.263
--- dwarf2out.c	2001/04/24 15:51:46
*************** dwarf2out_frame_finish ()
*** 1995,2000 ****
--- 1989,1995 ----
  typedef struct dw_val_struct *dw_val_ref;
  typedef struct die_struct *dw_die_ref;
  typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
+ typedef struct dw_loc_list_struct *dw_loc_list_ref;

  /* Each DIE may have a series of attribute/value pairs.  Values
     can take on several forms.  The forms that are used in this
*************** typedef enum
*** 2004,2009 ****
--- 1999,2005 ----
  {
    dw_val_class_addr,
    dw_val_class_loc,
+   dw_val_class_loc_list,
    dw_val_class_const,
    dw_val_class_unsigned_const,
    dw_val_class_long_long,
*************** typedef struct dw_val_struct
*** 2045,2050 ****
--- 2041,2047 ----
    union
      {
        rtx val_addr;
+       dw_loc_list_ref  val_loc_list;
        dw_loc_descr_ref val_loc;
        long int val_int;
        long unsigned val_unsigned;
*************** typedef struct dw_loc_descr_struct
*** 2076,2081 ****
--- 2073,2091 ----
  }
  dw_loc_descr_node;

+ /* Location lists are ranges + location descriptions for that range,
+    so you can track variables that are in different places over
+    their entire life. */
+ typedef struct dw_loc_list_struct
+ {
+   dw_loc_list_ref dw_loc_next;
+   const char *begin; /* Label for begin address of range */
+   const char *end;  /* Label for end address of range */
+   char *ll_symbol; /* Label for beginning of location list. Only on head of list */
+   const char *section; /* Section this loclist is relative to */
+   dw_loc_descr_ref expr;
+ } dw_loc_list_node;
+
  static const char *dwarf_stack_op_name	PARAMS ((unsigned));
  static dw_loc_descr_ref new_loc_descr	PARAMS ((enum dwarf_location_atom,
  						 unsigned long,
*************** static unsigned long size_of_locs	PARAMS
*** 2087,2092 ****
--- 2097,2110 ----
  static void output_loc_operands		PARAMS ((dw_loc_descr_ref));
  static void output_loc_sequence		PARAMS ((dw_loc_descr_ref));

+ static dw_loc_list_ref new_loc_list     PARAMS ((dw_loc_descr_ref,
+ 						 const char *, const char *,
+ 						 const char *, unsigned));
+ static void add_loc_descr_to_loc_list   PARAMS ((dw_loc_list_ref *,
+ 						 dw_loc_descr_ref,
+ 						 const char *, const char *, const char *));
+ static void output_loc_list		PARAMS ((dw_loc_list_ref));
+ static char *gen_internal_sym 		PARAMS ((const char *));
  /* Convert a DWARF stack opcode into its string name.  */

  static const char *
*************** new_loc_descr (op, oprnd1, oprnd2)
*** 2414,2419 ****
--- 2432,2460 ----
    return descr;
  }

+ /* Return a new location list, given the begin and end range, and the
+    expression. gensym tells us whether to generate a new internal
+    symbol for this location list node, which is done for the head of
+    the list only. */
+ static inline dw_loc_list_ref
+ new_loc_list (expr, begin, end, section, gensym)
+      register dw_loc_descr_ref expr;
+      register const char *begin;
+      register const char *end;
+      register const char *section;
+      register unsigned gensym;
+ {
+   register dw_loc_list_ref retlist
+     = (dw_loc_list_ref) xcalloc (1, sizeof (dw_loc_list_node));
+   retlist->begin = begin;
+   retlist->end = end;
+   retlist->expr = expr;
+   retlist->section = section;
+   if (gensym)
+     retlist->ll_symbol = gen_internal_sym ("LLST");
+   return retlist;
+ }
+
  /* Add a location description term to a location description expression.  */

  static inline void
*************** add_loc_descr (list_head, descr)
*** 2430,2435 ****
--- 2471,2494 ----
    *d = descr;
  }

+ /* Add a location description expression to a location list */
+ static inline void
+ add_loc_descr_to_loc_list (list_head, descr, begin, end, section)
+      register dw_loc_list_ref *list_head;
+      register dw_loc_descr_ref descr;
+      register const char *begin;
+      register const char *end;
+      register const char *section;
+ {
+   register dw_loc_list_ref *d;
+
+   /* Find the end of the chain. */
+   for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
+     ;
+   /* Add a new location list node to the list */
+   *d = new_loc_list (descr, begin, end, section, 0);
+ }
+
  /* Return the size of a location descriptor.  */

  static unsigned long
*************** static unsigned arange_table_in_use;
*** 3168,3173 ****
--- 3227,3235 ----
     arange_table.  */
  #define ARANGE_TABLE_INCREMENT 64

+ /* Whether we have location lists that need outputting */
+ static unsigned have_location_lists;
+
  /* A pointer to the base of a list of incomplete types which might be
     completed at some later time.  */

*************** static void add_AT_fde_ref		PARAMS ((dw_
*** 3238,3243 ****
--- 3300,3308 ----
  static void add_AT_loc			PARAMS ((dw_die_ref,
  						 enum dwarf_attribute,
  						 dw_loc_descr_ref));
+ static void add_AT_loc_list		PARAMS ((dw_die_ref,
+ 						 enum dwarf_attribute,
+ 						 dw_loc_list_ref));
  static void add_AT_addr			PARAMS ((dw_die_ref,
  						 enum dwarf_attribute,
  						 rtx));
*************** static void compute_section_prefix	PARAM
*** 3285,3295 ****
  static int is_type_die			PARAMS ((dw_die_ref));
  static int is_comdat_die 		PARAMS ((dw_die_ref));
  static int is_symbol_die 		PARAMS ((dw_die_ref));
- static char *gen_internal_sym 		PARAMS ((void));
  static void assign_symbol_names		PARAMS ((dw_die_ref));
  static void break_out_includes		PARAMS ((dw_die_ref));
  static void add_sibling_attributes	PARAMS ((dw_die_ref));
  static void build_abbrev_table		PARAMS ((dw_die_ref));
  static unsigned long size_of_string	PARAMS ((const char *));
  static int constant_size		PARAMS ((long unsigned));
  static unsigned long size_of_die	PARAMS ((dw_die_ref));
--- 3350,3360 ----
  static int is_type_die			PARAMS ((dw_die_ref));
  static int is_comdat_die 		PARAMS ((dw_die_ref));
  static int is_symbol_die 		PARAMS ((dw_die_ref));
  static void assign_symbol_names		PARAMS ((dw_die_ref));
  static void break_out_includes		PARAMS ((dw_die_ref));
  static void add_sibling_attributes	PARAMS ((dw_die_ref));
  static void build_abbrev_table		PARAMS ((dw_die_ref));
+ static void output_location_lists   	PARAMS ((dw_die_ref));
  static unsigned long size_of_string	PARAMS ((const char *));
  static int constant_size		PARAMS ((long unsigned));
  static unsigned long size_of_die	PARAMS ((dw_die_ref));
*************** static int file_info_cmp		PARAMS ((const
*** 3454,3459 ****
--- 3519,3527 ----
  #ifndef ABBREV_SECTION_LABEL
  #define ABBREV_SECTION_LABEL     "Ldebug_abbrev"
  #endif
+ #ifndef LOC_SECTION_LABEL
+ #define LOC_SECTION_LABEL	 "Ldebug_loc"
+ #endif

  /* Definitions of defaults for formats and names of various special
     (artificial) labels which may be generated within this file (when the -g
*************** static char text_section_label[MAX_ARTIF
*** 3466,3472 ****
  static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
  static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
  static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
!
  #ifndef TEXT_END_LABEL
  #define TEXT_END_LABEL		"Letext"
  #endif
--- 3534,3540 ----
  static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
  static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
  static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
! static char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
  #ifndef TEXT_END_LABEL
  #define TEXT_END_LABEL		"Letext"
  #endif
*************** AT_loc (a)
*** 4300,4305 ****
--- 4368,4401 ----
    abort ();
  }

+ static inline void
+ add_AT_loc_list (die, attr_kind, loc_list)
+      register dw_die_ref die;
+      register enum dwarf_attribute attr_kind;
+      register dw_loc_list_ref loc_list;
+ {
+   register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+
+   attr->dw_attr_next = NULL;
+   attr->dw_attr = attr_kind;
+   attr->dw_attr_val.val_class = dw_val_class_loc_list;
+   attr->dw_attr_val.v.val_loc_list = loc_list;
+   add_dwarf_attr (die, attr);
+   have_location_lists = 1;
+ }
+
+ static inline dw_loc_list_ref AT_loc_list PARAMS ((dw_attr_ref));
+
+ static inline dw_loc_list_ref
+ AT_loc_list (a)
+      register dw_attr_ref a;
+ {
+   if (a && AT_class (a) == dw_val_class_loc_list)
+     return a->dw_attr_val.v.val_loc_list;
+
+   abort ();
+ }
+
  /* Add an address constant attribute value to a DIE.  */

  static inline void
*************** print_die (die, outfile)
*** 4777,4782 ****
--- 4873,4881 ----
  	case dw_val_class_loc:
  	  fprintf (outfile, "location descriptor");
  	  break;
+ 	case dw_val_class_loc_list:
+ 	  fprintf (outfile, "location list -> label:%s", AT_loc_list (a)->ll_symbol);
+ 	  break;
  	case dw_val_class_const:
  	  fprintf (outfile, "%ld", AT_int (a));
  	  break;
*************** is_symbol_die (c)
*** 5171,5188 ****
  {
    if (is_type_die (c))
      return 1;
!   if (get_AT (c, DW_AT_declaration)
        && ! get_AT (c, DW_AT_specification))
      return 1;
    return 0;
  }

  static char *
! gen_internal_sym ()
  {
    char buf[256];
    static int label_num;
!   ASM_GENERATE_INTERNAL_LABEL (buf, "LDIE", label_num++);
    return xstrdup (buf);
  }

--- 5270,5288 ----
  {
    if (is_type_die (c))
      return 1;
!   if ((get_AT (c, DW_AT_declaration) || get_AT (c, DW_AT_abstract_origin))
        && ! get_AT (c, DW_AT_specification))
      return 1;
    return 0;
  }

  static char *
! gen_internal_sym (prefix)
! 	const char *prefix;
  {
    char buf[256];
    static int label_num;
!   ASM_GENERATE_INTERNAL_LABEL (buf, prefix, label_num++);
    return xstrdup (buf);
  }

*************** assign_symbol_names (die)
*** 5204,5210 ****
  	  die->die_symbol = xstrdup (p);
  	}
        else
! 	die->die_symbol = gen_internal_sym ();
      }

    for (c = die->die_child; c != NULL; c = c->die_sib)
--- 5304,5310 ----
  	  die->die_symbol = xstrdup (p);
  	}
        else
! 	die->die_symbol = gen_internal_sym ("LDIE");
      }

    for (c = die->die_child; c != NULL; c = c->die_sib)
*************** add_sibling_attributes (die)
*** 5289,5294 ****
--- 5389,5412 ----
      add_sibling_attributes (c);
  }

+ /* Output all location lists for the DIE and it's children */
+ static void
+ output_location_lists (die)
+      register dw_die_ref die;
+ {
+   dw_die_ref c;
+   dw_attr_ref d_attr;
+   for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next)
+     {
+       if (AT_class (d_attr) == dw_val_class_loc_list)
+ 	{
+ 	  output_loc_list (AT_loc_list (d_attr));
+ 	}
+     }
+   for (c = die->die_child; c != NULL; c = c->die_sib)
+     output_location_lists (c);
+
+ }
  /* The format of each DIE (and its attribute value pairs)
     is encoded in an abbreviation table.  This routine builds the
     abbreviation table and assigns a unique abbreviation id for
*************** size_of_die (die)
*** 5427,5432 ****
--- 5545,5553 ----
  	    size += lsize;
  	  }
  	  break;
+ 	case dw_val_class_loc_list:
+ 	  size += DWARF_OFFSET_SIZE;
+ 	  break;
  	case dw_val_class_const:
  	  size += size_of_sleb128 (AT_int (a));
  	  break;
*************** value_format (a)
*** 5562,5567 ****
--- 5683,5690 ----
      {
      case dw_val_class_addr:
        return DW_FORM_addr;
+     case dw_val_class_loc_list:
+ 	return DW_FORM_data4; /* FIXME: Could be DW_FORM_data8, with a > 32 bit size .debug_loc section */
      case dw_val_class_loc:
        switch (constant_size (size_of_locs (AT_loc (a))))
  	{
*************** output_die_symbol (die)
*** 5680,5685 ****
--- 5803,5836 ----
    ASM_OUTPUT_LABEL (asm_out_file, sym);
  }

+ /* Output the location list given to us */
+ static void
+ output_loc_list (list_head)
+      register dw_loc_list_ref list_head;
+ {
+   register dw_loc_list_ref curr;
+   ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol);
+   if (strcmp (curr->section, ".text") == 0)
+     {
+       /*FIXME: 0xffffffff should be the max address representable, so on 64 bit machines, this is wrong. */
+       dw2_asm_output_data (DWARF2_ADDR_SIZE, 0xffffffff, "Location list base address specifier fake entry");
+       dw2_asm_output_offset (DWARF2_ADDR_SIZE, curr->section, "Location list base address specifier base");
+     }
+   for (curr = list_head; curr != NULL; curr=curr->dw_loc_next)
+     {
+       int size;
+       dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section, "Location list begin address (%s)", list_head->ll_symbol);
+       dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->end, curr->section, "Location list end address (%s)", list_head->ll_symbol);
+       size = size_of_locs (curr->expr);
+
+       /* Output the block length for this list of location operations.  */
+       dw2_asm_output_data (constant_size (size), size, "%s", "Location expression size");
+
+       output_loc_sequence (curr->expr);
+     }
+   dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, "Location list terminator begin (%s)", list_head->ll_symbol);
+   dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, "Location list terminator end (%s)", list_head->ll_symbol);
+ }
  /* Output the DIE and its attributes.  Called recursively to generate
     the definitions of each child DIE.  */

*************** output_die (die)
*** 5770,5776 ****
  	case dw_val_class_flag:
  	  dw2_asm_output_data (1, AT_flag (a), "%s", name);
  	  break;
!
  	case dw_val_class_die_ref:
  	  if (AT_ref_external (a))
  	    {
--- 5921,5934 ----
  	case dw_val_class_flag:
  	  dw2_asm_output_data (1, AT_flag (a), "%s", name);
  	  break;
!         case dw_val_class_loc_list:
! 	  {
! 	    char *sym = AT_loc_list (a)->ll_symbol;
! 	    if (sym == 0)
! 	      abort();
! 	    dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label, name);
! 	  }
! 	  break;
  	case dw_val_class_die_ref:
  	  if (AT_ref_external (a))
  	    {
*************** output_aranges ()
*** 6037,6043 ****

  	  dw_attr_ref a = get_AT (die, DW_AT_location);
  	  dw_loc_descr_ref loc;
! 	  if (! a || AT_class (a) != dw_val_class_loc)
  	    abort ();

  	  loc = AT_loc (a);
--- 6192,6198 ----

  	  dw_attr_ref a = get_AT (die, DW_AT_location);
  	  dw_loc_descr_ref loc;
! 	  if (! a || (AT_class (a) != dw_val_class_loc ))
  	    abort ();

  	  loc = AT_loc (a);
*************** dwarf2out_init (asm_out_file, main_input
*** 11016,11022 ****
       register const char *main_input_filename;
  {
    init_file_table ();
!
    /* Remember the name of the primary input file.  */
    primary_filename = main_input_filename;

--- 11183,11189 ----
       register const char *main_input_filename;
  {
    init_file_table ();
!   have_location_lists = 0;
    /* Remember the name of the primary input file.  */
    primary_filename = main_input_filename;

*************** dwarf2out_init (asm_out_file, main_input
*** 11045,11050 ****
--- 11212,11218 ----
    /* Zero-th entry is allocated, but unused */
    abbrev_die_table_in_use = 1;

+
    /* Allocate the initial hunk of the line_info_table.  */
    line_info_table
      = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
*************** dwarf2out_init (asm_out_file, main_input
*** 11073,11079 ****
  			       DEBUG_INFO_SECTION_LABEL, 0);
    ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
  			       DEBUG_LINE_SECTION_LABEL, 0);
!
    ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
    ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
    if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
--- 11241,11249 ----
  			       DEBUG_INFO_SECTION_LABEL, 0);
    ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
  			       DEBUG_LINE_SECTION_LABEL, 0);
!   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, LOC_SECTION_LABEL, 0);
!   ASM_OUTPUT_SECTION (asm_out_file, LOC_SECTION);
!   ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
    ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
    ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
    if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
*************** dwarf2out_finish ()
*** 11204,11208 ****
--- 11375,11388 ----
        ASM_OUTPUT_SECTION (asm_out_file, ARANGES_SECTION);
        output_aranges ();
      }
+   /* Output location list section if necessary */
+   if (have_location_lists)
+     {
+       /* Output the location lists info. */
+       ASM_OUTPUT_SECTION (asm_out_file, LOC_SECTION);
+       output_location_lists (die);
+       have_location_lists = 0;
+     }
+
  }
  #endif /* DWARF2_DEBUGGING_INFO */



More information about the Gcc-patches mailing list