aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2011-11-02 14:53:04 +0000
committerJan Beulich <jbeulich@novell.com>2011-11-02 14:53:04 +0000
commite7ebb214834628b2b0d9d3233febc9fef2912515 (patch)
tree6547575e5850f8d7afc4455a0c3089ed8ef77863
parent207d428dce7dc9169fd5a59f10593f88c3a55f17 (diff)
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-11-02 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.
-rw-r--r--bfd/ChangeLog13
-rw-r--r--bfd/coffgen.c34
-rw-r--r--bfd/cofflink.c88
-rw-r--r--bfd/libcoff-in.h3
-rw-r--r--bfd/libcoff.h3
5 files changed, 131 insertions, 10 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index f20d7cc836..d4b33c5b5e 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,16 @@
+2011-11-02 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-11-01 DJ Delorie <dj@redhat.com>
* Makefile.am (ALL_MACHINES): Add cpu-rl78.lo.
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index 87a3bfaff8..c0505c6c02 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -983,31 +983,36 @@ 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;
struct bfd_link_info *link_info = coff_data (abfd)->link_info;
+ bfd_boolean ret;
if ((!link_info || link_info->strip_discarded)
&& !bfd_is_abs_section (symbol->section)
&& symbol->section->output_section == bfd_abs_section_ptr)
{
symbol->name = "";
+ if (isym != NULL)
+ memset (isym, 0, sizeof(*isym));
return TRUE;
}
- 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;
@@ -1018,6 +1023,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
@@ -1025,6 +1035,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
@@ -1045,16 +1057,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. */
@@ -1170,8 +1186,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;
}
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index bca136445d..1ebdfdd800 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -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;
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 8bfda723b4..0cd8de5d3b 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -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
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index 958650ca52..8aef552701 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -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