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]

bfd_find_nearest_line without debug info


bfd_find_nearest_line returns not just line info, but also function
and source file name.

This change adds STT_FILE symbols in strategic places when creating a
binary, with the aim of improving bfd_find_nearest_line output in the
absence of debugging info.  Currently we get file info returned that
is just plain wrong, due to a number of problems in elf_find_function,
the fallback that attempts to return some info for local functions.

Firstly, if some input file lacks an STT_FILE symbol, then
elf_find_function determines that their local functions belong to a
previous input file having an STT_FILE symbol.  Secondly, global
functions that have been forced local for any reason are associated
with the last input file having an STT_FILE symbol.  So the idea here
is to supply missing STT_FILE symbols to input files, and add another
STT_FILE symbol before outputting forced_local or linker generated
symbols.  We obviously can't supply the source file name for these
STT_FILE symbols, so I use the input object file name and a NULL
name.  Another alternative would be to use the output file name in
the latter case.

I'm posting this for comment now, as I'd rather not make all the
necessary testsuite changes if this idea turns out to be a bad one.
Costs a small increase in .symtab size, and another pass over the
linker global symbol hash table.

	* elflink.c (elf_link_input_bfd): Provide a file symbol for
	each input file with local syms, if the input lacks such.
	(bfd_elf_final_link): Add a file symbol to mark end of locals
	for which we can associate with input files.
	(struct elf_final_link_info): Add filesym_count field.
	(struct elf_outext_info): Add need_second_pass and second_pass.
	(elf_link_output_extsym): Detect symbols defined in the output
	file, emit them on second pass through locals.

Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.446
diff -u -p -r1.446 elflink.c
--- bfd/elflink.c	27 May 2012 13:55:45 -0000	1.446
+++ bfd/elflink.c	2 Jun 2012 01:03:24 -0000
@@ -7403,6 +7403,8 @@ struct elf_final_link_info
   size_t symbuf_size;
   /* And same for symshndxbuf.  */
   size_t shndxbuf_size;
+  /* Number of STT_FILE syms seen.  */
+  size_t filesym_count;
 };
 
 /* This struct is used to pass information to elf_link_output_extsym.  */
@@ -7411,6 +7413,8 @@ struct elf_outext_info
 {
   bfd_boolean failed;
   bfd_boolean localsyms;
+  bfd_boolean need_second_pass;
+  bfd_boolean second_pass;
   struct elf_final_link_info *flinfo;
 };
 
@@ -8759,6 +8763,17 @@ elf_link_output_extsym (struct bfd_hash_
 	input_sec = h->root.u.def.section;
 	if (input_sec->output_section != NULL)
 	  {
+	    if (eoinfo->localsyms)
+	      {
+		bfd_boolean second_pass_sym;
+
+		second_pass_sym = (input_sec->owner == flinfo->output_bfd
+				   || input_sec->owner == NULL);
+		eoinfo->need_second_pass |= second_pass_sym;
+		if (eoinfo->second_pass != second_pass_sym)
+		  return TRUE;
+	      }
+
 	    sym.st_shndx =
 	      _bfd_elf_section_from_bfd_section (flinfo->output_bfd,
 						 input_sec->output_section);
@@ -9111,6 +9126,7 @@ elf_link_input_bfd (struct elf_final_lin
   bfd_size_type address_size;
   bfd_vma r_type_mask;
   int r_sym_shift;
+  bfd_boolean have_file_sym = FALSE;
 
   output_bfd = flinfo->output_bfd;
   bed = get_elf_backend_data (output_bfd);
@@ -9246,6 +9262,29 @@ elf_link_input_bfd (struct elf_final_lin
 	      && bfd_is_local_label_name (input_bfd, name)))
 	continue;
 
+      if (ELF_ST_TYPE (isym->st_info) == STT_FILE)
+	{
+	  have_file_sym = TRUE;
+	  flinfo->filesym_count += 1;
+	}
+      if (!have_file_sym)
+	{
+	  /* In the absence of debug info, bfd_find_nearest_line uses
+	     FILE symbols to determine the source file for local
+	     function symbols.  Provide a FILE symbol here if input
+	     files lack such, so that their symbols won't be
+	     associated with a previous input file.  It's not the
+	     source file, but the best we can do.  */
+	  have_file_sym = TRUE;
+	  flinfo->filesym_count += 1;
+	  memset (&osym, 0, sizeof (osym));
+	  osym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
+	  osym.st_shndx = SHN_ABS;
+	  if (!elf_link_output_sym (flinfo, input_bfd->filename, &osym,
+				    bfd_abs_section_ptr, NULL))
+	    return FALSE;
+	}
+
       osym = *isym;
 
       /* Adjust the section index for the output file.  */
@@ -10318,6 +10357,7 @@ bfd_elf_final_link (bfd *abfd, struct bf
   flinfo.symshndxbuf = NULL;
   flinfo.symbuf_count = 0;
   flinfo.shndxbuf_size = 0;
+  flinfo.filesym_count = 0;
 
   /* The object attributes have been merged.  Remove the input
      sections from the link, and set the contents of the output
@@ -10792,6 +10832,17 @@ bfd_elf_final_link (bfd *abfd, struct bf
 	  }
     }
 
+  /* Output a FILE symbol so that following locals are not associated
+     with the wrong input file.  */
+  memset (&elfsym, 0, sizeof (elfsym));
+  elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
+  elfsym.st_shndx = SHN_ABS;
+
+  if (flinfo.filesym_count != 1
+      && !elf_link_output_sym (&flinfo, NULL, &elfsym,
+			       bfd_abs_section_ptr, NULL))
+    return FALSE;
+
   /* Output any global symbols that got converted to local in a
      version script or due to symbol visibility.  We do this in a
      separate step since ELF requires all local symbols to appear
@@ -10801,10 +10852,25 @@ bfd_elf_final_link (bfd *abfd, struct bf
   eoinfo.failed = FALSE;
   eoinfo.flinfo = &flinfo;
   eoinfo.localsyms = TRUE;
+  eoinfo.need_second_pass = FALSE;
+  eoinfo.second_pass = FALSE;
   bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
   if (eoinfo.failed)
     return FALSE;
 
+  if (flinfo.filesym_count == 1
+      && !elf_link_output_sym (&flinfo, NULL, &elfsym,
+			       bfd_abs_section_ptr, NULL))
+    return FALSE;
+
+  if (eoinfo.need_second_pass)
+    {
+      eoinfo.second_pass = TRUE;
+      bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
+      if (eoinfo.failed)
+	return FALSE;
+    }
+
   /* If backend needs to output some local symbols not present in the hash
      table, do it now.  */
   if (bed->elf_backend_output_arch_local_syms)

-- 
Alan Modra
Australia Development Lab, IBM


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