This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH: Check if DW_OP_fbreg has DW_AT_frame_base


On Tue, Jan 04, 2005 at 10:32:37AM -0800, H. J. Lu wrote:
> DW_OP_fbreg needs DW_AT_frame_base. But gcc generates it without
> DW_AT_frame_base:
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19124
> 
> This patch checks if DW_OP_fbreg has DW_AT_frame_base.
> 
> 

I also noticed that base address isn't handled for location list at
all. This updated patch fixes it.


H.J.
----
2005-01-04  H.J. Lu  <hongjiu.lu@intel.com>

	* readelf.c (have_frame_base): New.
	(need_base_address): Likewise.
	(saved_base_address): Likewise.
	(decode_location_expression): Return 1 if DW_AT_frame_base is
	needed.
	(debug_info): Add base_address and a have_frame_base pointer.
	(read_and_display_attr_value): Replace saved_DW_AT_low_pc with
	saved_base_address. Record base address. Set have_frame_base.
	Record if a location list has DW_AT_frame_base. Display if a
	location expression has no DW_AT_frame_base but needs one. Set
	saved_base_address only if needed.
	(process_debug_info): Clear have_frame_base, saved_base_address
	and set need_base_address.
	(display_debug_loc): Display if a location expression has no
	DW_AT_frame_base but needs one. Display if start >= end.
	Properly handle base address.
	(process_object): Free the have_frame_base pointer in
	debug_info.

--- binutils/readelf.c.frame	2005-01-04 09:20:26.000000000 -0800
+++ binutils/readelf.c	2005-01-04 13:58:20.085892273 -0800
@@ -168,6 +168,9 @@ int do_debug_loc;
 int do_arch;
 int do_notes;
 int is_32bit_elf;
+int have_frame_base;
+int need_base_address;
+unsigned long saved_base_address;
 
 struct group_list
 {
@@ -7551,7 +7554,7 @@ display_block (unsigned char *data, unsi
   return data;
 }
 
-static void
+static int
 decode_location_expression (unsigned char * data,
 			    unsigned int pointer_size,
 			    unsigned long length,
@@ -7561,6 +7564,7 @@ decode_location_expression (unsigned cha
   int bytes_read;
   unsigned long uvalue;
   unsigned char *end = data + length;
+  int need_frame_base = 0;
 
   while (data < end)
     {
@@ -7823,6 +7827,7 @@ decode_location_expression (unsigned cha
 	  data += bytes_read;
 	  break;
 	case DW_OP_fbreg:
+	  need_frame_base = 1;
 	  printf ("DW_OP_fbreg: %ld", read_leb128 (data, &bytes_read, 1));
 	  data += bytes_read;
 	  break;
@@ -7879,13 +7884,15 @@ decode_location_expression (unsigned cha
 	  else
 	    printf (_("(Unknown location op)"));
 	  /* No way to tell where the next op is, so just bail.  */
-	  return;
+	  return need_frame_base;
 	}
 
       /* Separate the ops.  */
       if (data < end)
 	printf ("; ");
     }
+
+  return need_frame_base;
 }
 
 /* Decode a DW_AT_ranges attribute for 64bit DWARF3 .  */
@@ -8008,8 +8015,10 @@ typedef struct
 {
   unsigned int   pointer_size;
   unsigned long  cu_offset;
+  unsigned long	 base_address;
   /* This is an array of offsets to the location list table.  */
   unsigned long *loc_offsets;
+  int		*have_frame_base;
   unsigned int   num_loc_offsets;
   unsigned int   max_loc_offsets;
 }
@@ -8031,7 +8040,6 @@ read_and_display_attr_value (unsigned lo
 			     debug_info *debug_info_p,
 			     int do_loc)
 {
-  static unsigned long saved_DW_AT_low_pc = 0;
   unsigned long uvalue = 0;
   unsigned char *block_start = NULL;
   int bytes_read;
@@ -8221,6 +8229,7 @@ read_and_display_attr_value (unsigned lo
       switch (attribute)
 	{
 	case DW_AT_frame_base:
+	  have_frame_base = 1;
 	case DW_AT_location:
 	case DW_AT_data_member_location:
 	case DW_AT_vtable_elem_location:
@@ -8242,12 +8251,21 @@ read_and_display_attr_value (unsigned lo
 		  debug_info_p->loc_offsets
 		    = xrealloc (debug_info_p->loc_offsets,
 				max * sizeof (*debug_info_p->loc_offsets));
+		  debug_info_p->have_frame_base
+		    = xrealloc (debug_info_p->have_frame_base,
+				max * sizeof (*debug_info_p->have_frame_base));
 		  debug_info_p->max_loc_offsets = max;
 		}
 	      debug_info_p->loc_offsets [num] = uvalue;
+	      debug_info_p->have_frame_base [num] = have_frame_base;
 	      debug_info_p->num_loc_offsets++;
 	    }
 	  break;
+	
+	case DW_AT_low_pc:
+	  if (need_base_address)
+	    debug_info_p->base_address = uvalue;
+	  break;
 
 	default:
 	  break;
@@ -8401,6 +8419,7 @@ read_and_display_attr_value (unsigned lo
       break;
 
     case DW_AT_frame_base:
+      have_frame_base = 1;
     case DW_AT_location:
     case DW_AT_data_member_location:
     case DW_AT_vtable_elem_location:
@@ -8412,9 +8431,16 @@ read_and_display_attr_value (unsigned lo
     case DW_AT_lower_bound:
       if (block_start)
 	{
+	  int need_frame_base;
+
 	  printf ("(");
-	  decode_location_expression (block_start, pointer_size, uvalue, cu_offset);
+	  need_frame_base = decode_location_expression (block_start,
+							pointer_size,
+							uvalue,
+							cu_offset);
 	  printf (")");
+	  if (need_frame_base && !have_frame_base)
+	    printf (_(" [without DW_AT_frame_base]"));
 	}
       else if (form == DW_FORM_data4 || form == DW_FORM_data8)
 	printf (_("(location list)"));
@@ -8422,15 +8448,12 @@ read_and_display_attr_value (unsigned lo
       break;
 
     case DW_AT_low_pc:
-      /* This is a hack.  We keep track of the DW_AT_low_pc attributes
-	 and use them when decoding DW_AT_ranges attributes.  The
-	 assumption here is that we are decoding the attributes in order
-	 and so the correct base address for the range is the low_pc.  */
-      saved_DW_AT_low_pc = uvalue;
+      if (need_base_address)
+	saved_base_address = uvalue;
       break;
 
     case DW_AT_ranges:
-      decode_range (uvalue, saved_DW_AT_low_pc);
+      decode_range (uvalue, saved_base_address);
       break;
 
     default:
@@ -8691,7 +8714,9 @@ process_debug_info (Elf_Internal_Shdr *s
 	  debug_information [unit].cu_offset = cu_offset;
 	  debug_information [unit].pointer_size
 	    = compunit.cu_pointer_size;
+	  debug_information [unit].base_address = 0;
 	  debug_information [unit].loc_offsets = NULL;
+	  debug_information [unit].have_frame_base = NULL;
 	  debug_information [unit].max_loc_offsets = 0;
 	  debug_information [unit].num_loc_offsets = 0;
 	}
@@ -8779,6 +8804,24 @@ process_debug_info (Elf_Internal_Shdr *s
 		    abbrev_number,
 		    get_TAG_name (entry->tag));
  
+	  switch (entry->tag)
+	    {
+	    default:
+	      need_base_address = 0;
+	      break;
+	    case DW_TAG_compile_unit:
+	      need_base_address = 1;
+	      saved_base_address = 0;
+	      break;
+	    case DW_TAG_entry_point:
+	    case DW_TAG_inlined_subroutine:
+	    case DW_TAG_subprogram:
+	      need_base_address = 0;
+	      /* Assuming that there is no DW_AT_frame_base.  */
+	      have_frame_base = 0;
+	      break;
+	    }
+
 	  for (attr = entry->first_attr; attr; attr = attr->next)
 	    tags = read_and_display_attr (attr->attribute,
 					  attr->form,
@@ -9468,14 +9511,19 @@ display_debug_loc (Elf_Internal_Shdr *se
       unsigned long offset;
       unsigned int pointer_size;
       unsigned long cu_offset;
+      unsigned long base_address;
+      int need_frame_base;
+      int has_frame_base;
 
       pointer_size = debug_information [i].pointer_size;
       cu_offset = debug_information [i].cu_offset;
 
       for (j = 0; j < debug_information [i].num_loc_offsets; j++)
 	{
+	  has_frame_base = debug_information [i].have_frame_base [j];
 	  offset = debug_information [i].loc_offsets [j];
 	  next = section_begin + offset;
+	  base_address = debug_information [i].base_address;
 
 	  if (!seen_first_offset)
 	    seen_first_offset = 1;
@@ -9500,9 +9548,12 @@ display_debug_loc (Elf_Internal_Shdr *se
 	      if (begin == 0 && end == 0)
 		break;
 
-	      /* For now, skip any base address specifiers.  */
-	      if (begin == 0xffffffff)
-		continue;
+	      /* Check base address specifiers.  */
+	      if (begin == -1UL && end != -1UL)
+		{
+		  base_address = end;
+		  continue;
+		}
 
 	      begin += addr;
 	      end += addr;
@@ -9511,14 +9562,22 @@ display_debug_loc (Elf_Internal_Shdr *se
 	      start += 2;
 
 	      printf ("    %8.8lx %8.8lx %8.8lx (",
-		      offset, begin, end);
-	      decode_location_expression (start, pointer_size, length,
-					  cu_offset);
-	      printf (")\n");
-
-	      if (begin >= end)
-		warn ("Bad location list at %8.8lx from %8.8lx to %8.8lx\n",
-		      offset, begin, end);
+		      offset, begin + base_address, end + base_address);
+	      need_frame_base = decode_location_expression (start,
+							    pointer_size,
+							    length,
+							    cu_offset);
+	      putchar (')');
+
+	      if (need_frame_base && !has_frame_base)
+		printf (_(" [without DW_AT_frame_base]"));
+
+	      if (begin == end)
+		fputs (_(" (start == end)"), stdout);
+	      else if (begin > end)
+		fputs (_(" (start > end)"), stdout);
+
+	      putchar ('\n');
 
 	      start += length;
 	    }
@@ -11748,8 +11807,11 @@ process_object (char *file_name, FILE *f
   if (debug_information)
     {
       for (i = 0; i < num_debug_info_entries; i++)
-	if (debug_information [i].loc_offsets != NULL)
-	  free (debug_information [i].loc_offsets);
+	if (!debug_information [i].max_loc_offsets)
+	  {
+	    free (debug_information [i].loc_offsets);
+	    free (debug_information [i].have_frame_base);
+	  }
       free (debug_information);
       debug_information = NULL;
       num_debug_info_entries = 0;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]