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]

[PATCH] COFF/PE: insert local symbols from foreign input objects into output executable


Building EFI binaries, particularly larger ones (like e.g. Xen does), on Linux
(where relocatable objects are in ELF format) so far led to all local (aka
static) symbols to be discarded, making debugging quite a bit more difficult
(like Linux, Xen builds an internal symbol lookup table from nm output
generated on the binary produced by an earlier linking pass). Therefore, this
patch arranges to insert all (relevant) local symbols from non-COFF objects
into the final executable's symbol table between those coming from COFF input
files and the global ones.

bfd/
2011-09-28  Jan Beulich  <jbeulich@suse.com>

	* coffgen.c (coff_write_alien_symbol): Make public. Add 'struct
	internal_syment *' parameter. Extend 'dummy' to an array with two
	elements. Set n_numaux early. Handle BSF_FILE.
	(coff_write_symbols): Pass NULL as new third argument to
	coff_write_alien_symbol().
	* cofflink.c (_bfd_coff_final_link): Don't use COFF-specific
	obj_raw_syment_count() on non-COFF input BFD. Insert local symbols
	from non-COFF input BFDs.
	* libcoff-in.h (coff_write_alien_symbol): Declare.
	* libcoff.h (coff_write_alien_symbol): Re-generate.

--- 2011-09-28/bfd/coffgen.c	2011-09-16 08:37:33.000000000 +0200
+++ 2011-09-28/bfd/coffgen.c	2011-09-28 12:01:54.000000000 +0200
@@ -983,23 +983,26 @@ coff_write_symbol (bfd *abfd,
    file originally.  This symbol may have been created by the linker,
    or we may be linking a non COFF file to a COFF file.  */
 
-static bfd_boolean
+bfd_boolean
 coff_write_alien_symbol (bfd *abfd,
 			 asymbol *symbol,
+			 struct internal_syment *isym,
 			 bfd_vma *written,
 			 bfd_size_type *string_size_p,
 			 asection **debug_string_section_p,
 			 bfd_size_type *debug_string_size_p)
 {
   combined_entry_type *native;
-  combined_entry_type dummy;
+  combined_entry_type dummy[2];
   asection *output_section = symbol->section->output_section
 			       ? symbol->section->output_section
 			       : symbol->section;
+  bfd_boolean ret;
 
-  native = &dummy;
+  native = dummy;
   native->u.syment.n_type = T_NULL;
   native->u.syment.n_flags = 0;
+  native->u.syment.n_numaux = 0;
   if (bfd_is_und_section (symbol->section))
     {
       native->u.syment.n_scnum = N_UNDEF;
@@ -1010,6 +1013,11 @@ coff_write_alien_symbol (bfd *abfd,
       native->u.syment.n_scnum = N_UNDEF;
       native->u.syment.n_value = symbol->value;
     }
+  else if (symbol->flags & BSF_FILE)
+    {
+      native->u.syment.n_scnum = N_DEBUG;
+      native->u.syment.n_numaux = 1;
+    }
   else if (symbol->flags & BSF_DEBUGGING)
     {
       /* There isn't much point to writing out a debugging symbol
@@ -1017,6 +1025,8 @@ coff_write_alien_symbol (bfd *abfd,
          format.  So, we just ignore them.  We must clobber the symbol
          name to keep it from being put in the string table.  */
       symbol->name = "";
+      if (isym != NULL)
+        memset (isym, 0, sizeof(*isym));
       return TRUE;
     }
   else
@@ -1037,16 +1047,20 @@ coff_write_alien_symbol (bfd *abfd,
     }
 
   native->u.syment.n_type = 0;
-  if (symbol->flags & BSF_LOCAL)
+  if (symbol->flags & BSF_FILE)
+    native->u.syment.n_sclass = C_FILE;
+  else if (symbol->flags & BSF_LOCAL)
     native->u.syment.n_sclass = C_STAT;
   else if (symbol->flags & BSF_WEAK)
     native->u.syment.n_sclass = obj_pe (abfd) ? C_NT_WEAK : C_WEAKEXT;
   else
     native->u.syment.n_sclass = C_EXT;
-  native->u.syment.n_numaux = 0;
 
-  return coff_write_symbol (abfd, symbol, native, written, string_size_p,
-			    debug_string_section_p, debug_string_size_p);
+  ret = coff_write_symbol (abfd, symbol, native, written, string_size_p,
+			   debug_string_section_p, debug_string_size_p);
+  if (isym != NULL)
+    *isym = native->u.syment;
+  return ret;
 }
 
 /* Write a native symbol to a COFF file.  */
@@ -1153,8 +1167,8 @@ coff_write_symbols (bfd *abfd)
       if (c_symbol == (coff_symbol_type *) NULL
 	  || c_symbol->native == (combined_entry_type *) NULL)
 	{
-	  if (!coff_write_alien_symbol (abfd, symbol, &written, &string_size,
-					&debug_string_section,
+	  if (!coff_write_alien_symbol (abfd, symbol, NULL, &written,
+					&string_size, &debug_string_section,
 					&debug_string_size))
 	    return FALSE;
 	}
--- 2011-09-28/bfd/cofflink.c	2011-09-16 08:37:33.000000000 +0200
+++ 2011-09-28/bfd/cofflink.c	2011-09-28 12:01:54.000000000 +0200
@@ -866,7 +866,7 @@ _bfd_coff_final_link (bfd *abfd,
       size_t sz;
 
       sub->output_has_begun = FALSE;
-      sz = obj_raw_syment_count (sub);
+      sz = bfd_family_coff (sub) ? obj_raw_syment_count (sub) : 2;
       if (sz > max_sym_count)
 	max_sym_count = sz;
     }
@@ -943,6 +943,92 @@ _bfd_coff_final_link (bfd *abfd,
 	}
     }
 
+  if (finfo.info->strip != strip_all && finfo.info->discard != discard_all)
+    {
+      /* Add local symbols from foreign inputs.  */
+      for(sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+	{
+	  unsigned int i;
+
+	  if (bfd_family_coff (sub) || ! bfd_get_outsymbols (sub))
+	    continue;
+	  for (i = 0; i < bfd_get_symcount (sub); ++i)
+	    {
+	      asymbol *sym = bfd_get_outsymbols (sub) [i];
+	      file_ptr pos;
+	      struct internal_syment isym;
+	      bfd_size_type string_size = 0;
+	      bfd_vma written = 0;
+	      bfd_boolean rewrite = FALSE;
+
+	      if (! (sym->flags & BSF_LOCAL)
+		  || (sym->flags & (BSF_SECTION_SYM | BSF_DEBUGGING_RELOC
+				    | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC
+				    | BSF_SYNTHETIC))
+		  || ((sym->flags & BSF_DEBUGGING)
+		      && ! (sym->flags & BSF_FILE)))
+		continue;
+
+	      /* See if we are discarding symbols with this name.  */
+	      if ((finfo.info->strip == strip_some
+		   && (bfd_hash_lookup (finfo.info->keep_hash,
+					bfd_asymbol_name(sym), FALSE, FALSE)
+		       == NULL))
+		  || (((finfo.info->discard == discard_sec_merge
+			&& (bfd_get_section (sym)->flags & SEC_MERGE)
+			&& ! finfo.info->relocatable)
+		       || finfo.info->discard == discard_l)
+		      && bfd_is_local_label_name (sub, bfd_asymbol_name(sym))))
+		continue;
+
+	      pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd)
+					     * symesz;
+	      if (bfd_seek (abfd, pos, SEEK_SET) != 0)
+		goto error_return;
+	      if (! coff_write_alien_symbol(abfd, sym, &isym, &written,
+					    &string_size, NULL, NULL))
+		goto error_return;
+
+	      if (string_size)
+		{
+		  bfd_boolean hash = ! (abfd->flags & BFD_TRADITIONAL_FORMAT);
+		  bfd_size_type indx;
+
+		  indx = _bfd_stringtab_add (finfo.strtab,
+					     bfd_asymbol_name (sym), hash,
+					     FALSE);
+		  if (indx == (bfd_size_type) -1)
+		    goto error_return;
+		  isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+		  bfd_coff_swap_sym_out (abfd, &isym, finfo.outsyms);
+		  rewrite = TRUE;
+		}
+
+	      if (isym.n_sclass == C_FILE)
+		{
+		  if (finfo.last_file_index != -1)
+		    {
+		      finfo.last_file.n_value = obj_raw_syment_count (abfd);
+		      bfd_coff_swap_sym_out (abfd, &finfo.last_file,
+					     finfo.outsyms);
+		      pos = obj_sym_filepos (abfd) + finfo.last_file_index
+						     * symesz;
+		      rewrite = TRUE;
+		    }
+		  finfo.last_file_index = obj_raw_syment_count (abfd);
+		  finfo.last_file = isym;
+		}
+
+	      if (rewrite
+		  && (bfd_seek (abfd, pos, SEEK_SET) != 0
+		      || bfd_bwrite (finfo.outsyms, symesz, abfd) != symesz))
+		goto error_return;
+
+	      obj_raw_syment_count (abfd) += written;
+	    }
+	}
+    }
+
   if (! bfd_coff_final_link_postscript (abfd, & finfo))
     goto error_return;
 
--- 2011-09-28/bfd/libcoff-in.h	2011-09-16 08:37:39.000000000 +0200
+++ 2011-09-28/bfd/libcoff-in.h	2011-09-28 12:01:54.000000000 +0200
@@ -318,6 +318,9 @@ extern void coff_mangle_symbols
   (bfd *);
 extern bfd_boolean coff_write_symbols
   (bfd *);
+extern bfd_boolean coff_write_alien_symbol
+  (bfd *, asymbol *, struct internal_syment *, bfd_vma *,
+   bfd_size_type *, asection **, bfd_size_type *);
 extern bfd_boolean coff_write_linenumbers
   (bfd *);
 extern alent *coff_get_lineno
--- 2011-09-28/bfd/libcoff.h	2011-09-16 08:37:39.000000000 +0200
+++ 2011-09-28/bfd/libcoff.h	2011-09-28 12:01:54.000000000 +0200
@@ -322,6 +322,9 @@ extern void coff_mangle_symbols
   (bfd *);
 extern bfd_boolean coff_write_symbols
   (bfd *);
+extern bfd_boolean coff_write_alien_symbol
+  (bfd *, asymbol *, struct internal_syment *, bfd_vma *,
+   bfd_size_type *, asection **, bfd_size_type *);
 extern bfd_boolean coff_write_linenumbers
   (bfd *);
 extern alent *coff_get_lineno


Attachment: binutils-mainline-COFF-foreign-symbols.patch
Description: Text document


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