_bfd_dwarf2_find_nearest_line returns wrong filename

Daniel Jacobowitz drow@mvista.com
Thu Jan 16 21:03:00 GMT 2003


On Fri, Jan 03, 2003 at 03:39:40PM +0100, Andreas Schwab wrote:
> Daniel Jacobowitz <drow@mvista.com> writes:
> 
> |> No regressions, but some pertinent facts:
> |> 
> |>  - Examine the ld.log with this patch applied.  Grep for BFD.  You'll
> |>    find several assertion failures indicating that the DWARF-2 data
> |>    is incorrect.  It's kind of sad that the testsuite doesn't notice any
> |>    of these.
> 
> I have now tried it on ia64, and it is getting worse.  They are using
> R_IA64_SECREL32LS relocations in .debug_info, which is causing
> bfd_perform_relocation to return bfd_reloc_outofrange, and
> bfd_generic_get_relocated_section_contents is aborting on that.

We needed to save and restore outputs in order to get the right answers
on i386 in some cases.  We also needed some other fixes to ia64 - I
missed it when I swept the hash table create functions to make them use
bfd_malloc, I guess - and to weaken an abort in elfNN_ia64_reloc.  But
now it works.  Tested on:

ia64-elf
i386-elf
m68k-elf
sh-elf
mips-elf
arm-elf
cris-elf
sparc-elf
alpha-elf
powerpc-elf

I also have a new testcase for NOCROSSREFS which showed some other
problems, I'll post it once I figure out how to fit it in to the
testsuite...

How's this revision?

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2003-01-16  Andreas Schwab  <schwab@suse.de>
	    Daniel Jacobowitz  <drow@mvista.com>

	* simple.c (bfd_simple_get_relocated_section_contents): Add
	parameter symbol_table.  Optionally use it instead of the symbol
	table from the bfd.  Save and restore output section offsets
	around bfd_get_relocated_section_contents.  Fix a memory leak.
	(simple_save_output_offsets, simple_restore_output_offsets): New
	functions.
	* bfd-in2.h: Regenerate.
	* dwarf2.c (read_abbrevs): Use
	bfd_simple_get_relocated_section_contents instead of
	bfd_get_section_contents.
	(decode_line_info): Likewise.
	(_bfd_dwarf2_find_nearest_line): Likewise.  Don't call
	find_rela_addend.
	(find_rela_addend): Remove.
	* elfxx-ia64.c (elfNN_ia64_reloc): Weaken sanity check for
	debugging sections.
	(elfNN_ia64_hash_table_create): Create the hash table with malloc,
	not bfd_zalloc.

Index: dwarf2.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/bfd/dwarf2.c,v
retrieving revision 1.42
diff -u -p -r1.42 dwarf2.c
--- dwarf2.c	2002/12/12 10:26:01	1.42
+++ dwarf2.c	2003/01/15 22:21:49
@@ -245,8 +245,6 @@ static bfd_boolean lookup_address_in_lin
 static bfd_boolean lookup_address_in_function_table
   PARAMS ((struct funcinfo *, bfd_vma, struct funcinfo **, const char **));
 static bfd_boolean scan_unit_for_functions PARAMS ((struct comp_unit *));
-static bfd_vma find_rela_addend
-  PARAMS ((bfd *, asection *, bfd_size_type, asymbol**));
 static struct comp_unit *parse_comp_unit
   PARAMS ((bfd *, struct dwarf2_debug *, bfd_vma, unsigned int));
 static bfd_boolean comp_unit_contains_address
@@ -546,13 +544,11 @@ read_abbrevs (abfd, offset, stash)
 	}
 
       stash->dwarf_abbrev_size = msec->_raw_size;
-      stash->dwarf_abbrev_buffer = (char*) bfd_alloc (abfd, msec->_raw_size);
+      stash->dwarf_abbrev_buffer
+	= bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
+						     stash->syms);
       if (! stash->dwarf_abbrev_buffer)
 	  return 0;
-
-      if (! bfd_get_section_contents (abfd, msec, stash->dwarf_abbrev_buffer,
-				      (bfd_vma) 0, msec->_raw_size))
-	return 0;
     }
 
   if (offset >= stash->dwarf_abbrev_size)
@@ -1019,21 +1015,15 @@ decode_line_info (unit, stash)
 	}
 
       stash->dwarf_line_size = msec->_raw_size;
-      stash->dwarf_line_buffer = (char *) bfd_alloc (abfd, msec->_raw_size);
+      stash->dwarf_line_buffer
+	= bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
+						     stash->syms);
       if (! stash->dwarf_line_buffer)
 	return 0;
-
-      if (! bfd_get_section_contents (abfd, msec, stash->dwarf_line_buffer,
-				      (bfd_vma) 0, msec->_raw_size))
-	return 0;
-
-      /* FIXME: We ought to apply the relocs against this section before
-	 we process it...  */
     }
 
-  /* Since we are using un-relocated data, it is possible to get a bad value
-     for the line_offset.  Validate it here so that we won't get a segfault
-     below.  */
+  /* It is possible to get a bad value for the line_offset.  Validate
+     it here so that we won't get a segfault below.  */
   if (unit->line_offset >= stash->dwarf_line_size)
     {
       (*_bfd_error_handler) (_("Dwarf Error: Line offset (%lu) greater than or equal to .debug_line size (%lu)."),
@@ -1521,60 +1511,6 @@ scan_unit_for_functions (unit)
   return TRUE;
 }
 
-/* Look for a RELA relocation to be applied on OFFSET of section SEC,
-   and return the addend if such a relocation is found.  Since this is
-   only used to find relocations referring to the .debug_abbrev
-   section, we make sure the relocation refers to this section, but
-   this is not strictly necessary, and it can probably be safely
-   removed if needed.  However, it is important to note that this
-   function only returns the addend, it doesn't serve the purpose of
-   applying a generic relocation.
-
-   If no suitable relocation is found, or if it is not a real RELA
-   relocation, this function returns 0.  */
-
-static bfd_vma
-find_rela_addend (abfd, sec, offset, syms)
-     bfd* abfd;
-     asection* sec;
-     bfd_size_type offset;
-     asymbol** syms;
-{
-  long reloc_size = bfd_get_reloc_upper_bound (abfd, sec);
-  arelent **relocs = NULL;
-  long reloc_count, relc;
-
-  if (reloc_size <= 0)
-    return 0;
-
-  relocs = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
-  if (relocs == NULL)
-    return 0;
-
-  reloc_count = bfd_canonicalize_reloc (abfd, sec, relocs, syms);
-
-  if (reloc_count <= 0)
-    {
-      free (relocs);
-      return 0;
-    }
-
-  for (relc = 0; relc < reloc_count; relc++)
-    if (relocs[relc]->address == offset
-	&& (*relocs[relc]->sym_ptr_ptr)->flags & BSF_SECTION_SYM
-	&& strcmp ((*relocs[relc]->sym_ptr_ptr)->name,
-		   ".debug_abbrev") == 0)
-      {
-	bfd_vma addend = (relocs[relc]->howto->partial_inplace
-			  ? 0 : relocs[relc]->addend);
-	free (relocs);
-	return addend;
-      }
-
-  free (relocs);
-  return 0;
-}
-
 /* Parse a DWARF2 compilation unit starting at INFO_PTR.  This
    includes the compilation unit header that proceeds the DIE's, but
    does not include the length field that preceeds each compilation
@@ -1602,7 +1538,6 @@ parse_comp_unit (abfd, stash, unit_lengt
   char *info_ptr = stash->info_ptr;
   char *end_ptr = info_ptr + unit_length;
   bfd_size_type amt;
-  bfd_size_type off;
 
   version = read_2_bytes (abfd, info_ptr);
   info_ptr += 2;
@@ -1611,12 +1546,6 @@ parse_comp_unit (abfd, stash, unit_lengt
     abbrev_offset = read_4_bytes (abfd, info_ptr);
   else
     abbrev_offset = read_8_bytes (abfd, info_ptr);
-  /* The abbrev offset is generally a relocation pointing to
-     .debug_abbrev+offset.  On RELA targets, we have to find the
-     relocation and extract the addend to obtain the actual
-     abbrev_offset, so do it here.  */
-  off = info_ptr - stash->sec_info_ptr;
-  abbrev_offset += find_rela_addend (abfd, stash->sec, off, stash->syms);
   info_ptr += offset_size;
   addr_size = read_1_byte (abfd, info_ptr);
   info_ptr += 1;
@@ -1939,8 +1868,8 @@ _bfd_dwarf2_find_nearest_line (abfd, sec
 
 	  start = stash->info_ptr_end - stash->info_ptr;
 
-	  if (! bfd_get_section_contents (abfd, msec, stash->info_ptr + start,
-					  (bfd_vma) 0, size))
+	  if ((bfd_simple_get_relocated_section_contents
+	       (abfd, msec, stash->info_ptr + start, symbols)) == NULL)
 	    continue;
 
 	  stash->info_ptr_end = stash->info_ptr + start + size;
@@ -1953,21 +1882,6 @@ _bfd_dwarf2_find_nearest_line (abfd, sec
       stash->syms = symbols;
     }
 
-  /* 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)
@@ -2034,10 +1948,10 @@ _bfd_dwarf2_find_nearest_line (abfd, sec
 		{
 		  if (comp_unit_contains_address (each, addr))
 		    return comp_unit_find_nearest_line (each, addr,
-						       filename_ptr,
-						       functionname_ptr,
-						       linenumber_ptr,
-						       stash);
+							filename_ptr,
+							functionname_ptr,
+							linenumber_ptr,
+							stash);
 		}
 	      else
 		{
Index: elfxx-ia64.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/bfd/elfxx-ia64.c,v
retrieving revision 1.64
diff -u -p -r1.64 elfxx-ia64.c
--- elfxx-ia64.c	2002/12/06 01:48:24	1.64
+++ elfxx-ia64.c	2003/01/16 16:20:04
@@ -344,6 +344,10 @@ elfNN_ia64_reloc (abfd, reloc, sym, data
       reloc->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
+
+  if (input_section->flags & SEC_DEBUGGING)
+    return bfd_reloc_continue;
+
   *error_message = "Unsupported call to elfNN_ia64_reloc";
   return bfd_reloc_notsupported;
 }
@@ -1699,19 +1703,25 @@ elfNN_ia64_hash_table_create (abfd)
 {
   struct elfNN_ia64_link_hash_table *ret;
 
-  ret = bfd_zalloc (abfd, (bfd_size_type) sizeof (*ret));
+  ret = bfd_malloc ((bfd_size_type) sizeof (*ret));
   if (!ret)
     return 0;
+  memset (ret, 0, sizeof (*ret));
+
   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
 				      elfNN_ia64_new_elf_hash_entry))
     {
-      bfd_release (abfd, ret);
+      free (ret);
       return 0;
     }
 
   if (!elfNN_ia64_local_hash_table_init (&ret->loc_hash_table, abfd,
 				         elfNN_ia64_new_loc_hash_entry))
-    return 0;
+    {
+      free (ret);
+      return 0;
+    }
+
   return &ret->root.root;
 }
 
Index: simple.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/bfd/simple.c,v
retrieving revision 1.5
diff -u -p -r1.5 simple.c
--- simple.c	2002/11/30 08:39:40	1.5
+++ simple.c	2003/01/16 18:47:51
@@ -42,8 +42,14 @@ static bfd_boolean simple_dummy_reloc_da
 static bfd_boolean simple_dummy_unattached_reloc
   PARAMS ((struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma));
 
+static void simple_save_output_offsets
+  PARAMS ((bfd *, asection *, PTR));
+
+static void simple_restore_output_offsets
+  PARAMS ((bfd *, asection *, PTR));
+
 bfd_byte * bfd_simple_get_relocated_section_contents
-  PARAMS ((bfd *, asection *, bfd_byte *));
+  PARAMS ((bfd *, asection *, bfd_byte *, asymbol **));
 
 static bfd_boolean
 simple_dummy_warning (link_info, warning, symbol, abfd, section, address)
@@ -105,17 +111,39 @@ simple_dummy_unattached_reloc (link_info
   return TRUE;
 }
 
+static void
+simple_save_output_offsets (abfd, section, ptr)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *section;
+     PTR ptr;
+{
+  bfd_vma *offsets = (bfd_vma *) ptr;
+  offsets[section->index] = section->output_offset;
+  section->output_offset = 0;
+}
+
+static void
+simple_restore_output_offsets (abfd, section, ptr)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *section;
+     PTR ptr;
+{
+  bfd_vma *offsets = (bfd_vma *) ptr;
+  section->output_offset = offsets[section->index];
+}
+
 /*
 FUNCTION
 	bfd_simple_relocate_secton
 
 SYNOPSIS
-	bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf);
+	bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
 
 DESCRIPTION
-	Returns the relocated contents of section @var{sec}.  Only symbols
-	from @var{abfd} and the output offsets assigned to sections in
-	@var{abfd} are used.  The result will be stored at @var{outbuf}
+	Returns the relocated contents of section @var{sec}.  The symbols in
+	@var{symbol_table} will be used, or the symbols from @var{abfd} if
+	@var{symbol_table} is NULL.  The output offsets for all sections will
+	be temporarily reset to 0.  The result will be stored at @var{outbuf}
 	or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}.
 
 	Generally all sections in @var{abfd} should have their
@@ -126,17 +154,18 @@ DESCRIPTION
 */
 
 bfd_byte *
-bfd_simple_get_relocated_section_contents (abfd, sec, outbuf)
+bfd_simple_get_relocated_section_contents (abfd, sec, outbuf, symbol_table)
      bfd *abfd;
      asection *sec;
      bfd_byte *outbuf;
+     asymbol **symbol_table;
 {
   struct bfd_link_info link_info;
   struct bfd_link_order link_order;
   struct bfd_link_callbacks callbacks;
   bfd_byte *contents, *data;
   int storage_needed, number_of_symbols;
-  asymbol **symbol_table;
+  PTR saved_offsets;
 
   if (! (sec->flags & SEC_RELOC))
     {
@@ -183,12 +212,33 @@ bfd_simple_get_relocated_section_content
 	return NULL;
       outbuf = data;
     }
-  bfd_link_add_symbols (abfd, &link_info);
 
-  storage_needed = bfd_get_symtab_upper_bound (abfd);
-  symbol_table = (asymbol **) bfd_malloc (storage_needed);
-  number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+  /* The sections in ABFD may already have output sections and offsets set.
+     Because this function is primarily for debug sections, and GCC uses the
+     knowledge that debug sections will generally have VMA 0 when emiting
+     relocations between DWARF-2 sections (which are supposed to be
+     section-relative offsets anyway), we need to reset the output offsets
+     to zero.  Save them to restore later.  */
+  saved_offsets = malloc (sizeof (bfd_vma) * abfd->section_count);
+  if (saved_offsets == NULL)
+    {
+      if (data)
+	free (data);
+      return NULL;
+    }
+  bfd_map_over_sections (abfd, simple_save_output_offsets, saved_offsets);
+
+  if (symbol_table == NULL)
+    {
+      bfd_link_add_symbols (abfd, &link_info);
 
+      storage_needed = bfd_get_symtab_upper_bound (abfd);
+      symbol_table = (asymbol **) bfd_malloc (storage_needed);
+      number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+    }
+  else
+    storage_needed = 0;
+
   contents = bfd_get_relocated_section_contents (abfd,
 						 &link_info,
 						 &link_order,
@@ -197,6 +247,12 @@ bfd_simple_get_relocated_section_content
 						 symbol_table);
   if (contents == NULL && data != NULL)
     free (data);
+
+  if (storage_needed != 0)
+    free (symbol_table);
+
+  bfd_map_over_sections (abfd, simple_restore_output_offsets, saved_offsets);
+  free (saved_offsets);
 
   /* Foul hack to prevent bfd_section_size aborts.  This flag only controls
      that macro (and the related size macros), selecting between _raw_size



More information about the Binutils mailing list