This is the mail archive of the binutils@sourceware.org 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: ld/2338: objdump -d -l doesn't work correctly


On Tue, Feb 28, 2006 at 01:50:53PM -0500, Daniel Jacobowitz wrote:
> On Tue, Feb 28, 2006 at 10:23:52AM -0800, H. J. Lu wrote:
> > On Tue, Feb 28, 2006 at 09:14:41AM -0800, H. J. Lu wrote:
> > > > HJ, "may not work correctly" doesn't say anything about why you really
> > > > need a gap.  If you do need a gap, then there is a bug somewhere else.
> > > > That should be fixed.  Presumably the same problem, whatever it is,
> > > > could affect final linked executables with more than one text section.
> > > 
> > > decode_line_info in dwarf2.c calls add_line_info for both low_pc
> > > and high_pc. If there is no gap, there may be 2 entries in line info
> > > table with the same address. The line info looks up will fail if
> > > an address matches more than 2 lines.
> > > 
> > 
> > add_line_info should sort entries with the same address by line number.
> > This patch does that.
> 
> Anything related to debug info line mappings that needs to sort by line
> number is very suspect.  It sounds like you're hacking around invalid
> or misinterpreted data.
> 
> Maybe you just need to handle end_sequence specially, possibly again
> by sorting it before other entries.
> 

Here is the updated patch.


H.J.
---
2006-02-28  H.J. Lu  <hongjiu.lu@intel.com>

	PR binutils/2338
	* dwarf2.c (loadable_section): New struct.
	(dwarf2_debug): Add loadable_section_count and
	loadable_sections.
	(add_line_info): Insert entries of the same address with the
	proper order of end_sequence.
	(check_function_name): Removed.
	(unset_sections): New.
	(place_sections): New.
	(_bfd_dwarf2_find_nearest_line): Updated. Call place_sections
	and unset_sections on relocatable files.
	(_bfd_dwarf2_find_line): Likewise.

--- bfd/dwarf2.c.rel	2006-02-16 10:08:05.000000000 -0800
+++ bfd/dwarf2.c	2006-02-28 11:39:27.000000000 -0800
@@ -74,6 +74,12 @@ struct dwarf_block
   bfd_byte *data;
 };
 
+struct loadable_section
+{
+  asection *section;
+  bfd_vma adj_vma;
+};
+
 struct dwarf2_debug
 {
   /* A list of all previously read comp_units.  */
@@ -124,6 +130,12 @@ struct dwarf2_debug
      calling chain for subsequent calls to bfd_find_inliner_info to
      use. */
   struct funcinfo *inliner_chain;
+
+  /* Number of loadable sections.  */
+  unsigned int loadable_section_count;
+
+  /* Array of loadable sections.  */
+  struct loadable_section *loadable_sections;
 };
 
 struct arange
@@ -803,6 +815,15 @@ add_line_info (struct line_info_table *t
       {
 	/* Abnormal but easy: lcl_head is 1) in the *middle* of the line
 	   list and 2) the head of 'info'.  */
+	if (address == table->lcl_head->prev_line->address
+	    && end_sequence != 0
+	    && table->lcl_head->end_sequence != 0
+	    && table->lcl_head->prev_line->end_sequence == 0)
+	  {
+	    /* If the new adress is the same, we need to make sure that
+	       the order of end_sequence is correct.  */
+	    table->lcl_head = table->lcl_head->prev_line;
+	  }
 	info->prev_line = table->lcl_head->prev_line;
 	table->lcl_head->prev_line = info;
 	break;
@@ -2179,28 +2200,91 @@ find_debug_info (bfd *abfd, asection *af
   return NULL;
 }
 
-/* Return TRUE if there is no mismatch bewteen function FUNC and
-   section SECTION from symbol table SYMBOLS in ABFD.  */
+/* Unset vmas for loadable sections in STASH.  */
+
+static void
+unset_sections (struct dwarf2_debug *stash)
+{
+  unsigned int i;
+  struct loadable_section *p;
+
+  i = stash->loadable_section_count;
+  p = stash->loadable_sections;
+  for (; i > 0; i--, p++)
+    p->section->vma = 0;
+}
+
+/* Set unique vmas for loadable sections in ABFD and save vmas in
+   STASH for unset_sections.  */
 
 static bfd_boolean
-check_function_name (bfd *abfd, asection *section, asymbol **symbols,
-		     const char *func)
+place_sections (bfd *abfd, struct dwarf2_debug *stash)
 {
-  /* Mismatch can only happen when we have 2 functions with the same
-     address. It can only occur in a relocatable file.  */
-  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
-      && func != NULL
-      && section != NULL
-      && symbols != NULL)
-    {
-      asymbol **p;
-
-      for (p = symbols; *p != NULL; p++)
-	{
-	  if (((*p)->flags & BSF_FUNCTION) != 0
-	      && (*p)->name != NULL
-	      && strcmp ((*p)->name, func) == 0)
-	    return (*p)->section == section;
+  struct loadable_section *p;
+  unsigned int i;
+
+  if (stash->loadable_section_count != 0)
+    {
+      i = stash->loadable_section_count;
+      p = stash->loadable_sections;
+      for (; i > 0; i--, p++)
+	p->section->vma = p->adj_vma;
+    }
+  else
+    {
+      asection *sect;
+      bfd_vma last_vma = 0;
+      bfd_size_type amt;
+      struct loadable_section *p;
+
+      i = 0;
+      for (sect = abfd->sections; sect != NULL; sect = sect->next)
+	{
+	  bfd_size_type sz;
+
+	  if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
+	    continue;
+
+	  sz = sect->rawsize ? sect->rawsize : sect->size;
+	  if (sz == 0)
+	    continue;
+
+	  i++;
+	}
+
+      amt = i * sizeof (struct loadable_section);
+      p = (struct loadable_section *) bfd_zalloc (abfd, amt);
+      if (! p)
+	return FALSE;
+
+      stash->loadable_sections = p;
+      stash->loadable_section_count = i;
+
+      for (sect = abfd->sections; sect != NULL; sect = sect->next)
+	{
+	  bfd_size_type sz;
+
+	  if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
+	    continue;
+
+	  sz = sect->rawsize ? sect->rawsize : sect->size;
+	  if (sz == 0)
+	    continue;
+
+	  p->section = sect;
+	  if (last_vma != 0)
+	    {
+	      /* Align the new address to the current section
+		 alignment.  */
+	      last_vma = ((last_vma
+			   + ~((bfd_vma) -1 << sect->alignment_power))
+			  & ((bfd_vma) -1 << sect->alignment_power));
+	      sect->vma = last_vma;
+	    }
+	  p->adj_vma = sect->vma;
+	  last_vma += sect->vma + sz;
+
+	  p++;
 	}
     }
 
@@ -2239,7 +2323,27 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 
   struct comp_unit* each;
 
+  bfd_vma found = FALSE;
+
   stash = *pinfo;
+
+  if (! stash)
+    {
+      bfd_size_type amt = sizeof (struct dwarf2_debug);
+
+      stash = bfd_zalloc (abfd, amt);
+      if (! stash)
+	return FALSE;
+    }
+
+  /* In a relocatable file, 2 functions may have the same address.
+     We change the section vma so that they won't overlap.  */
+  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+    {
+      if (! place_sections (abfd, stash))
+	return FALSE;
+    }
+
   addr = offset;
   if (section->output_section)
     addr += section->output_section->vma + section->output_offset;
@@ -2256,15 +2360,10 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
     addr_size = 4;
   BFD_ASSERT (addr_size == 4 || addr_size == 8);
 
-  if (! stash)
+  if (! *pinfo)
     {
       bfd_size_type total_size;
       asection *msec;
-      bfd_size_type amt = sizeof (struct dwarf2_debug);
-
-      stash = bfd_zalloc (abfd, amt);
-      if (! stash)
-	return FALSE;
 
       *pinfo = stash;
 
@@ -2273,7 +2372,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 	/* No dwarf2 info.  Note that at this point the stash
 	   has been allocated, but contains zeros, this lets
 	   future calls to this function fail quicker.  */
-	 return FALSE;
+	goto done;
 
       /* There can be more than one DWARF2 info section in a BFD these days.
 	 Read them all in and produce one large stash.  We do this in two
@@ -2285,7 +2384,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 
       stash->info_ptr = bfd_alloc (abfd, total_size);
       if (stash->info_ptr == NULL)
-	return FALSE;
+	goto done;
 
       stash->info_ptr_end = stash->info_ptr;
 
@@ -2319,7 +2418,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
   /* A null info_ptr indicates that there is no dwarf2 info
      (or that an error occured while setting up the stash).  */
   if (! stash->info_ptr)
-    return FALSE;
+    goto done;
 
   stash->inliner_chain = NULL;
 
@@ -2328,10 +2427,11 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
     if (comp_unit_contains_address (each, addr)
 	&& comp_unit_find_nearest_line (each, addr, filename_ptr,
 					functionname_ptr,
-					linenumber_ptr, stash)
-	&& check_function_name (abfd, section, symbols,
-				*functionname_ptr))
-      return TRUE;
+					linenumber_ptr, stash))
+      {
+	found = TRUE;
+	goto done;
+      }
 
   /* Read each remaining comp. units checking each as they are read.  */
   while (stash->info_ptr < stash->info_ptr_end)
@@ -2398,15 +2498,20 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 						  filename_ptr,
 						  functionname_ptr,
 						  linenumber_ptr,
-						  stash)
-		  && check_function_name (abfd, section, symbols,
-					  *functionname_ptr))
-		return TRUE;
+						  stash))
+		{
+		  found = TRUE;
+		  goto done;
+		}
 	    }
 	}
     }
 
-  return FALSE;
+done:
+  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+    unset_sections (stash);
+
+  return found;
 }
 
 /* The DWARF2 version of find_line.  Return TRUE if the line is found
@@ -2438,10 +2543,29 @@ _bfd_dwarf2_find_line (bfd *abfd,
 
   asection *section;
 
-  bfd_boolean found;
+  bfd_boolean found = FALSE;
 
   section = bfd_get_section (symbol);
 
+  stash = *pinfo;
+
+  if (! stash)
+    {
+      bfd_size_type amt = sizeof (struct dwarf2_debug);
+
+      stash = bfd_zalloc (abfd, amt);
+      if (! stash)
+	return FALSE;
+    }
+
+  /* In a relocatable file, 2 functions may have the same address.
+     We change the section vma so that they won't overlap.  */
+  if (!stash && (abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+    {
+      if (! place_sections (abfd, stash))
+	return FALSE;
+    }
+
   addr = symbol->value;
   if (section->output_section)
     addr += section->output_section->vma + section->output_offset;
@@ -2449,19 +2573,13 @@ _bfd_dwarf2_find_line (bfd *abfd,
     addr += section->vma;
 
   *filename_ptr = NULL;
-  stash = *pinfo;
   *filename_ptr = NULL;
   *linenumber_ptr = 0;
 
-  if (! stash)
+  if (! *pinfo)
     {
       bfd_size_type total_size;
       asection *msec;
-      bfd_size_type amt = sizeof (struct dwarf2_debug);
-
-      stash = bfd_zalloc (abfd, amt);
-      if (! stash)
-	return FALSE;
 
       *pinfo = stash;
 
@@ -2470,7 +2588,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
 	/* No dwarf2 info.  Note that at this point the stash
 	   has been allocated, but contains zeros, this lets
 	   future calls to this function fail quicker.  */
-	 return FALSE;
+	goto done;
 
       /* There can be more than one DWARF2 info section in a BFD these days.
 	 Read them all in and produce one large stash.  We do this in two
@@ -2482,7 +2600,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
 
       stash->info_ptr = bfd_alloc (abfd, total_size);
       if (stash->info_ptr == NULL)
-	return FALSE;
+	goto done;
 
       stash->info_ptr_end = stash->info_ptr;
 
@@ -2516,7 +2634,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
   /* A null info_ptr indicates that there is no dwarf2 info
      (or that an error occured while setting up the stash).  */
   if (! stash->info_ptr)
-    return FALSE;
+    goto done;
 
   stash->inliner_chain = NULL;
 
@@ -2528,7 +2646,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
 	found = comp_unit_find_line (each, symbol, addr, filename_ptr,
 				     linenumber_ptr, stash);
 	if (found)
-	  return found;
+	  goto done;
       }
 
   /* The DWARF2 spec says that the initial length field, and the
@@ -2605,12 +2723,16 @@ _bfd_dwarf2_find_line (bfd *abfd,
 					       linenumber_ptr,
 					       stash));
 	      if (found)
-		return TRUE;
+		goto done;
 	    }
 	}
     }
 
-  return FALSE;
+done:
+  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+    unset_sections (stash);
+
+  return found;
 }
 
 bfd_boolean


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