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]

Re: [PATCH] Eliminate duplicate dwarf2 data


Hi Daniel,

> You need to be able to restart the search from after the last
> section found, and you need to concatenate the sections' contents
> into one stash for processing by the rest of the function.

: Maybe i'm just stupid today, but i can't see why we need to
: concatenate them into one stash. Doesn't the rest of the code
: already handle walking through multiple compilation units to find
: the info needed for debug_line?

: It has to, because we've always had multiple compilation units in
: the executable if you linked >1 .o file with dwarf2 info in it.
: Given this, I don't see what's changed besides the name of the
: section that requires special processing. Like i said, maybe i'm
: just daft today.  Or maybe i never tried to set a breakpoint in
: something that was really in a seperate CU generated specifically by
: this patch.

The point is that the 'stash' is actually a saved copy of the contents
of the .debug_info section for the BFD concerned.  This stash may/will
contain debug info for multiple compilation units, as you say, but the
pre-patch code only expects there to be ONE .debug_info section in the
BFD, so it only allocates & reads in the stash once.

With the new scheme there will be multiple debug info sections in the
BFD, so it is necessary to read them all in, build one large "stash"
and then pass this stash off to the rest of the function so that it
can process the compilation units in them.  (The rest of the function
does not care where the compilation unit info came from).

Hence the realloc'ing and the do...while loop in my patch.

: Thanks for doing all the hard work. I was actually going to submit
: the binutils stuff seperately, and was only really including it so
: people could try out the gcc part of the patch, but when i leave for
: 5 seconds, you take a hack and make it work properly. :)

he he he

I have tweaked the patch a little bit to avoid the calls to
bfd_realloc, by creating two passes over the section list.  This
should speed things up slightly.  New patch below.  I am going to
apply this patch to the repository.

Cheers
	Nick

2000-09-02  Nick Clifton  <nickc@redhat.com>

	* dwarf2.c (find_debug_info): New function: Locate a section
	containing dwarf2 debug information.
	(bfd_dwarf2_find_nearest_line): Find all sections containing
	debug information and include them in the stash.

Index: bfd/dwarf2.c
===================================================================
RCS file: /cvs/src//src/bfd/dwarf2.c,v
retrieving revision 1.14
diff -p -r1.14 dwarf2.c
*** dwarf2.c	2000/04/19 10:53:01	1.14
--- dwarf2.c	2000/09/02 20:07:36
*************** comp_unit_find_nearest_line (unit, addr,
*** 1463,1468 ****
--- 1463,1505 ----
    return line_p || func_p;
  }
  
+ /* Locate a section in a BFD containing debugging info.  The search starts from the
+    section after AFTER_SEC, or from the first section in the BFD if AFTER_SEC is
+    NULL.  The search works by examining the names of the sections.  There are two
+    permissiable names.  The first is .debug_info.  This is the standard DWARF2 name.
+    The second is a prefix .gnu.linkonce.wi.  This is a variation on the .debug_info
+    section which has a checksum describing the contents appended onto the name.  This
+    allows the linker to identify and discard duplicate debugging sections for
+    different compilation units.  */
+ #define DWARF2_DEBUG_INFO ".debug_info"
+ #define GNU_LINKONCE_INFO ".gnu.linkonce.wi."
+ 
+ static asection *
+ find_debug_info (abfd, after_sec)
+      bfd * abfd;
+      asection * after_sec;
+ {
+   asection * msec;
+ 
+   if (after_sec)
+     msec = after_sec->next;
+   else
+     msec = abfd->sections;
+ 
+   while (msec)
+     {
+       if (strcmp (msec->name, DWARF2_DEBUG_INFO) == 0)
+ 	return msec;
+ 
+       if (strncmp (msec->name, GNU_LINKONCE_INFO, strlen (GNU_LINKONCE_INFO)) == 0)
+ 	return msec;
+ 
+       msec = msec->next;
+     }
+ 
+   return NULL;
+ }
+ 
  /* 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.
*************** _bfd_dwarf2_find_nearest_line (abfd, sec
*** 1513,1572 ****
      
    if (! stash)
      {
        asection *msec;
!       unsigned long size;
!       
        stash = elf_tdata (abfd)->dwarf2_find_line_info =
  	(struct dwarf2_debug*) bfd_zalloc (abfd, sizeof (struct dwarf2_debug));
-       
        if (! stash)
  	return false;
-       
-       msec = bfd_get_section_by_name (abfd, ".debug_info");
-       if (! msec)
- 	{
- 	  /* 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;
- 	}
  
!       size = msec->_raw_size;
!       if (size == 0)
  	return false;
!       
!       stash->info_ptr = (char *) bfd_alloc (abfd, size);
        
!       if (! stash->info_ptr)
  	return false;
  
!       if (! bfd_get_section_contents (abfd, msec, stash->info_ptr, 0, size))
  	{
! 	  stash->info_ptr = 0;
! 	  return false;
! 	}
  
!       stash->info_ptr_end = stash->info_ptr + size;
  
!       /* FIXME: There is a problem with the contents of the
! 	 .debug_info section.  The 'low' and 'high' addresses of the
! 	 comp_units are computed by relocs against symbols in the
! 	 .text segment.  We need these addresses in order to determine
! 	 the nearest line number, and so we have to resolve the
! 	 relocs.  There is a similar problem when the .debug_line
! 	 section is processed as well (e.g., there may be relocs
! 	 against the operand of the DW_LNE_set_address operator).
! 	 
! 	 Unfortunately getting hold of the reloc information is hard...
! 
! 	 For now, this means that disassembling object files (as
! 	 opposed to fully executables) does not always work as well as
! 	 we would like.  */
      }
    
    /* 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;
  
--- 1550,1623 ----
      
    if (! stash)
      {
+       unsigned long total_size;
        asection *msec;
! 
        stash = elf_tdata (abfd)->dwarf2_find_line_info =
  	(struct dwarf2_debug*) bfd_zalloc (abfd, sizeof (struct dwarf2_debug));
        if (! stash)
  	return false;
  
!       msec = find_debug_info (abfd, NULL);
!       if (! msec)
! 	/* 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;
! 
!       /* 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 (abfd, msec))
! 	total_size += msec->_raw_size;
        
!       stash->info_ptr = (char *) bfd_alloc (abfd, total_size);
!       if (stash->info_ptr == NULL)
  	return false;
  
!       stash->info_ptr_end = stash->info_ptr;
! 
!       for (msec = find_debug_info (abfd, NULL);
! 	   msec;
! 	   msec = find_debug_info (abfd, msec))
  	{
! 	  unsigned long size;
! 	  unsigned long start;
! 
! 	  size = msec->_raw_size;
! 	  if (size == 0)
! 	    continue;
! 
! 	  start = stash->info_ptr_end - stash->info_ptr;
  
! 	  if (! bfd_get_section_contents (abfd, msec, stash->info_ptr + start, 0, size))
! 	    continue;
  
! 	  stash->info_ptr_end = stash->info_ptr + start + size;
! 	}
! 
!       BFD_ASSERT (stash->info_ptr_end = stash->info_ptr + total_size);
      }
+ 
+   /* FIXME: There is a problem with the contents of the
+      .debug_info section.  The 'low' and 'high' addresses of the
+      comp_units are computed by relocs against symbols in the
+      .text segment.  We need these addresses in order to determine
+      the nearest line number, and so we have to resolve the
+      relocs.  There is a similar problem when the .debug_line
+      section is processed as well (e.g., there may be relocs
+      against the operand of the DW_LNE_set_address operator).
+      
+      Unfortunately getting hold of the reloc information is hard...
+      
+      For now, this means that disassembling object files (as
+      opposed to fully executables) does not always work as well as
+      we would like.  */
    
    /* 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;
  

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