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: Remove code duplication in dwarf2.c


On Sat, Jun 23, 2007 at 09:34:51AM +0100, Nick Clifton wrote:
> Hi H.J.
> 
> >Both _bfd_dwarf2_find_nearest_line and _bfd_dwarf2_find_line have
> >the same code to follow .gnu_debuglink section.  This patch uses
> >a function instead of duplicating the code. OK to install?
> 
> Sort-of.  Andreas has just posted a patch to provide a global debug 
> directory parameter to the call to bfd_follow_gnu_debuglink() which I 
> would like to see integrated into your patch.  Plus it seems to me that 
> there is a lot more code duplication between _bfd_dwarf2_find_line and 
> _bfd_dwarf2_find_nearest_line, so maybe you could expand your patch even 
> more ?
> 

How about this path?


H.J.
---
2007-06-23  H.J. Lu  <hongjiu.lu@intel.com>

	* dwarf2.c (find_line): New.
	(_bfd_dwarf2_find_nearest_line): Use it.
	(_bfd_dwarf2_find_line): Use it.

--- bfd/dwarf2.c.dup	2007-06-23 07:55:38.000000000 -0700
+++ bfd/dwarf2.c	2007-06-23 09:02:36.000000000 -0700
@@ -2301,22 +2301,17 @@ place_sections (bfd *abfd, struct dwarf2
   return TRUE;
 }
 
-/* The DWARF2 version of find_nearest_line.  Return TRUE if the line
-   is found without error.  ADDR_SIZE is the number of bytes in the
-   initial .debug_info length field and in the abbreviation offset.
-   You may use zero to indicate that the default value should be
-   used.  */
-
-bfd_boolean
-_bfd_dwarf2_find_nearest_line (bfd *abfd,
-			       asection *section,
-			       asymbol **symbols,
-			       bfd_vma offset,
-			       const char **filename_ptr,
-			       const char **functionname_ptr,
-			       unsigned int *linenumber_ptr,
-			       unsigned int addr_size,
-			       void **pinfo)
+/* Return TRUE if the line is found without error.  ADDR_SIZE is the
+   number of bytes in the initial .debug_info length field and in the
+   abbreviation offset.  You may use zero to indicate that the default
+   value should be used.  */
+
+static bfd_boolean
+find_line (bfd *abfd, asection *section, bfd_vma offset,
+	   asymbol *symbol, asymbol **symbols,
+	   const char **filename_ptr, const char **functionname_ptr,
+	   unsigned int *linenumber_ptr, unsigned int addr_size,
+	   void **pinfo)
 {
   /* Read each compilation unit from the section .debug_info, and check
      to see if it contains the address we are searching for.  If yes,
@@ -2331,6 +2326,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
   bfd_vma addr;
   struct comp_unit* each;
   bfd_vma found = FALSE;
+  bfd_boolean do_line;
 
   stash = *pinfo;
 
@@ -2351,7 +2347,22 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 	return FALSE;
     }
 
-  addr = offset;
+  do_line = (section == NULL
+	     && offset == 0
+	     && functionname_ptr == NULL
+	     && symbol != NULL);
+  if (do_line)
+    {
+      addr = symbol->value;
+      section = bfd_get_section (symbol);
+    }
+  else if (section != NULL
+	   && functionname_ptr != NULL
+	   && symbol == NULL)
+    addr = offset;
+  else
+    abort ();
+
   if (section->output_section)
     addr += section->output_section->vma + section->output_offset;
   else
@@ -2360,13 +2371,6 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
   *functionname_ptr = NULL;
   *linenumber_ptr = 0;
 
-  /* The DWARF2 spec says that the initial length field, and the
-     offset of the abbreviation table, should both be 4-byte values.
-     However, some compilers do things differently.  */
-  if (addr_size == 0)
-    addr_size = 4;
-  BFD_ASSERT (addr_size == 4 || addr_size == 8);
-
   if (! *pinfo)
     {
       bfd *debug_bfd;
@@ -2452,14 +2456,30 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 
   /* Check the previously read comp. units first.  */
   for (each = stash->all_comp_units; each; each = each->next_unit)
-    if (comp_unit_contains_address (each, addr)
-	&& comp_unit_find_nearest_line (each, addr, filename_ptr,
-					functionname_ptr,
-					linenumber_ptr, stash))
-      {
-	found = TRUE;
+    {
+      if (do_line)
+	found = (((symbol->flags & BSF_FUNCTION) == 0
+		  || comp_unit_contains_address (each, addr))
+		 && comp_unit_find_line (each, symbol, addr,
+					 filename_ptr, linenumber_ptr,
+					 stash));
+      else
+	found = (comp_unit_contains_address (each, addr)
+		 && comp_unit_find_nearest_line (each, addr,
+						 filename_ptr,
+						 functionname_ptr,
+						 linenumber_ptr,
+						 stash));
+      if (found)
 	goto done;
-      }
+    }
+
+  /* The DWARF2 spec says that the initial length field, and the
+     offset of the abbreviation table, should both be 4-byte values.
+     However, some compilers do things differently.  */
+  if (addr_size == 0)
+    addr_size = 4;
+  BFD_ASSERT (addr_size == 4 || addr_size == 8);
 
   /* Read each remaining comp. units checking each as they are read.  */
   while (stash->info_ptr < stash->info_ptr_end)
@@ -2526,17 +2546,24 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 		 unit->high == 0), we need to consult the line info
 		 table to see if a compilation unit contains the given
 		 address.  */
-	      if ((each->arange.high == 0
-		   || comp_unit_contains_address (each, addr))
-		  && comp_unit_find_nearest_line (each, addr,
-						  filename_ptr,
-						  functionname_ptr,
-						  linenumber_ptr,
-						  stash))
-		{
-		  found = TRUE;
-		  goto done;
-		}
+	      if (do_line)
+		found = (((symbol->flags & BSF_FUNCTION) == 0
+			  || each->arange.high == 0
+			  || comp_unit_contains_address (each, addr))
+			 && comp_unit_find_line (each, symbol, addr,
+						 filename_ptr,
+						 linenumber_ptr,
+						 stash));
+	      else
+		found = ((each->arange.high == 0
+			  || comp_unit_contains_address (each, addr))
+			 && comp_unit_find_nearest_line (each, addr,
+							 filename_ptr,
+							 functionname_ptr,
+							 linenumber_ptr,
+							 stash));
+	      if (found)
+		goto done;
 	    }
 	}
     }
@@ -2548,6 +2575,25 @@ done:
   return found;
 }
 
+/* The DWARF2 version of find_nearest_line.  Return TRUE if the line
+   is found without error.  */
+
+bfd_boolean
+_bfd_dwarf2_find_nearest_line (bfd *abfd,
+			       asection *section,
+			       asymbol **symbols,
+			       bfd_vma offset,
+			       const char **filename_ptr,
+			       const char **functionname_ptr,
+			       unsigned int *linenumber_ptr,
+			       unsigned int addr_size,
+			       void **pinfo)
+{
+  return find_line (abfd, section, offset, NULL, symbols, filename_ptr,
+		    functionname_ptr, linenumber_ptr, addr_size,
+		    pinfo);
+}
+
 /* The DWARF2 version of find_line.  Return TRUE if the line is found
    without error.  */
 
@@ -2560,236 +2606,9 @@ _bfd_dwarf2_find_line (bfd *abfd,
 		       unsigned int addr_size,
 		       void **pinfo)
 {
-  /* Read each compilation unit from the section .debug_info, and check
-     to see if it contains the address we are searching for.  If yes,
-     lookup the address, and return the line number info.  If no, go
-     on to the next compilation unit.
-
-     We keep a list of all the previously read compilation units, and
-     a pointer to the next un-read compilation unit.  Check the
-     previously read units before reading more.  */
-  struct dwarf2_debug *stash;
-  /* What address are we looking for?  */
-  bfd_vma addr;
-  struct comp_unit* each;
-  asection *section;
-  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;
-  else
-    addr += section->vma;
-
-  *filename_ptr = NULL;
-  *filename_ptr = NULL;
-  *linenumber_ptr = 0;
-
-  if (! *pinfo)
-    {
-      bfd *debug_bfd;
-      bfd_size_type total_size;
-      asection *msec;
-
-      *pinfo = stash;
-
-      msec = find_debug_info (abfd, NULL);
-      if (msec == NULL)
-	{
-	  char * debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
-
-	  if (debug_filename == NULL)
-	    /* No dwarf2 info, and no gnu_debuglink to follow.
-	       Note that at this point the stash has been allocated, but
-	       contains zeros.  This lets future calls to this function
-	       fail more quickly.  */
-	    goto done;
-
-	  if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
-	      || ! bfd_check_format (debug_bfd, bfd_object)
-	      || (msec = find_debug_info (debug_bfd, NULL)) == NULL)
-	    {
-	      if (debug_bfd)
-		bfd_close (debug_bfd);
-	      /* FIXME: Should we report our failure to follow the debuglink ?  */
-	      free (debug_filename);
-	      goto done;
-	    }
-	}
-      else
-	debug_bfd = abfd;
-
-      /* 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
-	 passes - in the first pass we just accumulate the section sizes.
-	 In the second pass we read in the section's contents.  The allows
-	 us to avoid reallocing the data as we add sections to the stash.  */
-      for (total_size = 0; msec; msec = find_debug_info (debug_bfd, msec))
-	total_size += msec->size;
-
-      stash->info_ptr = bfd_alloc (debug_bfd, total_size);
-      if (stash->info_ptr == NULL)
-	goto done;
-
-      stash->info_ptr_end = stash->info_ptr;
-
-      for (msec = find_debug_info (debug_bfd, NULL);
-	   msec;
-	   msec = find_debug_info (debug_bfd, msec))
-	{
-	  bfd_size_type size;
-	  bfd_size_type start;
-
-	  size = msec->size;
-	  if (size == 0)
-	    continue;
-
-	  start = stash->info_ptr_end - stash->info_ptr;
-
-	  if ((bfd_simple_get_relocated_section_contents
-	       (debug_bfd, msec, stash->info_ptr + start, symbols)) == NULL)
-	    continue;
-
-	  stash->info_ptr_end = stash->info_ptr + start + size;
-	}
-
-      BFD_ASSERT (stash->info_ptr_end == stash->info_ptr + total_size);
-
-      stash->sec = find_debug_info (debug_bfd, NULL);
-      stash->sec_info_ptr = stash->info_ptr;
-      stash->syms = symbols;
-      stash->bfd = debug_bfd;
-    }
-
-  /* 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)
-    goto done;
-
-  stash->inliner_chain = NULL;
-
-  /* Check the previously read comp. units first.  */
-  for (each = stash->all_comp_units; each; each = each->next_unit)
-    if ((symbol->flags & BSF_FUNCTION) == 0
-	|| comp_unit_contains_address (each, addr))
-      {
-	found = comp_unit_find_line (each, symbol, addr, filename_ptr,
-				     linenumber_ptr, stash);
-	if (found)
-	  goto done;
-      }
-
-  /* The DWARF2 spec says that the initial length field, and the
-     offset of the abbreviation table, should both be 4-byte values.
-     However, some compilers do things differently.  */
-  if (addr_size == 0)
-    addr_size = 4;
-  BFD_ASSERT (addr_size == 4 || addr_size == 8);
-
-  /* Read each remaining comp. units checking each as they are read.  */
-  while (stash->info_ptr < stash->info_ptr_end)
-    {
-      bfd_vma length;
-      unsigned int offset_size = addr_size;
-      bfd_byte *info_ptr_unit = stash->info_ptr;
-
-      length = read_4_bytes (stash->bfd, stash->info_ptr);
-      /* A 0xffffff length is the DWARF3 way of indicating we use
-	 64-bit offsets, instead of 32-bit offsets.  */
-      if (length == 0xffffffff)
-	{
-	  offset_size = 8;
-	  length = read_8_bytes (stash->bfd, stash->info_ptr + 4);
-	  stash->info_ptr += 12;
-	}
-      /* A zero length is the IRIX way of indicating 64-bit offsets,
-	 mostly because the 64-bit length will generally fit in 32
-	 bits, and the endianness helps.  */
-      else if (length == 0)
-	{
-	  offset_size = 8;
-	  length = read_4_bytes (stash->bfd, stash->info_ptr + 4);
-	  stash->info_ptr += 8;
-	}
-      /* In the absence of the hints above, we assume 32-bit DWARF2
-	 offsets even for targets with 64-bit addresses, because:
-	   a) most of the time these targets will not have generated
-	      more than 2Gb of debug info and so will not need 64-bit
-	      offsets,
-	 and
-	   b) if they do use 64-bit offsets but they are not using
-	      the size hints that are tested for above then they are
-	      not conforming to the DWARF3 standard anyway.  */
-      else if (addr_size == 8)
-	{
-	  offset_size = 4;
-          stash->info_ptr += 4;
-	}
-      else
-	stash->info_ptr += 4;
-
-      if (length > 0)
-	{
-	  each = parse_comp_unit (stash, length, info_ptr_unit,
-				  offset_size);
-	  stash->info_ptr += length;
-
-	  if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
-	      == stash->sec->size)
-	    {
-	      stash->sec = find_debug_info (stash->bfd, stash->sec);
-	      stash->sec_info_ptr = stash->info_ptr;
-	    }
-
-	  if (each)
-	    {
-	      each->next_unit = stash->all_comp_units;
-	      stash->all_comp_units = each;
-
-	      /* DW_AT_low_pc and DW_AT_high_pc are optional for
-		 compilation units.  If we don't have them (i.e.,
-		 unit->high == 0), we need to consult the line info
-		 table to see if a compilation unit contains the given
-		 address.  */
-	      found = (((symbol->flags & BSF_FUNCTION) == 0
-			|| each->arange.high <= 0
-			|| comp_unit_contains_address (each, addr))
-		       && comp_unit_find_line (each, symbol, addr,
-					       filename_ptr,
-					       linenumber_ptr,
-					       stash));
-	      if (found)
-		goto done;
-	    }
-	}
-    }
-
-done:
-  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
-    unset_sections (stash);
-
-  return found;
+  return find_line (abfd, NULL, 0, symbol, symbols, filename_ptr,
+		    NULL, linenumber_ptr, addr_size,
+		    pinfo);
 }
 
 bfd_boolean


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