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]

PATCH: Check if DW_OP_fbreg has DW_AT_frame_base


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.


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

	* readelf.c (have_frame_base): New.
	(decode_location_expression): Return 1 if DW_AT_frame_base is
	needed.
	(debug_info): Add a have_frame_base pointer.
	(read_and_display_attr_value): 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.
	(process_debug_info): Clear have_frame_base.
	(display_debug_loc): Display if a location expression has no
	DW_AT_frame_base but needs one. Display if start >= end.
	(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 09:59:00.158542184 -0800
@@ -168,6 +168,7 @@ int do_debug_loc;
 int do_arch;
 int do_notes;
 int is_32bit_elf;
+int have_frame_base;
 
 struct group_list
 {
@@ -7551,7 +7552,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 +7562,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 +7825,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 +7882,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 .  */
@@ -8010,6 +8015,7 @@ typedef struct
   unsigned long  cu_offset;
   /* 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;
 }
@@ -8221,6 +8227,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,9 +8249,13 @@ 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;
@@ -8401,6 +8412,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 +8424,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)"));
@@ -8692,6 +8711,7 @@ process_debug_info (Elf_Internal_Shdr *s
 	  debug_information [unit].pointer_size
 	    = compunit.cu_pointer_size;
 	  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 +8799,18 @@ process_debug_info (Elf_Internal_Shdr *s
 		    abbrev_number,
 		    get_TAG_name (entry->tag));
  
+	  switch (entry->tag)
+	    {
+	    default:
+	      break;
+	    case DW_TAG_entry_point:
+	    case DW_TAG_inlined_subroutine:
+	    case DW_TAG_subprogram:
+	      /* 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,12 +9500,15 @@ display_debug_loc (Elf_Internal_Shdr *se
       unsigned long offset;
       unsigned int pointer_size;
       unsigned long cu_offset;
+      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;
 
@@ -9512,13 +9547,21 @@ display_debug_loc (Elf_Internal_Shdr *se
 
 	      printf ("    %8.8lx %8.8lx %8.8lx (",
 		      offset, begin, end);
-	      decode_location_expression (start, pointer_size, length,
-					  cu_offset);
-	      printf (")\n");
+	      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);
 
-	      if (begin >= end)
-		warn ("Bad location list at %8.8lx from %8.8lx to %8.8lx\n",
-		      offset, begin, end);
+	      putchar ('\n');
 
 	      start += length;
 	    }
@@ -11748,8 +11791,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]