Fix support for PECOFF weak symbols

This commit is contained in:
Nick Clifton 2004-11-08 08:12:53 +00:00
parent 998b002970
commit 977cdf5aa7
18 changed files with 305 additions and 97 deletions

View File

@ -1,3 +1,11 @@
2004-11-08 Aaron W. LaFramboise <aaron98wiridge9@aaronwl.com>
* coff-i386.c (coff_i386_reloc): Fix weak symbols.
* cofflink.c (_bfd_coff_link_input_bfd): Don't process
C_NT_WEAK aux entries.
(_bfd_coff_generic_relocate_section): Handle undefined
aliases.
2004-11-07 Andreas Schwab <schwab@suse.de>
* elf32-m68k.c (elf_m68k_adjust_dynamic_symbol): Use

View File

@ -4,21 +4,21 @@
Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
@ -119,6 +119,8 @@ coff_i386_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
here. */
if (howto->pc_relative && howto->pcrel_offset)
diff = -(1 << howto->size);
else if (symbol->flags & BSF_WEAK)
diff = reloc_entry->addend - symbol->value;
else
diff = -reloc_entry->addend;
}

View File

@ -1,3 +1,7 @@
2004-11-08 Aaron W. LaFramboise <aaron98wiridge9@aaronwl.com>
* doc/binutils.texi (nm): Update description of weak symbols.
2004-11-03 Nick Clifton <nickc@redhat.com>
* readelf.c (do_debug_ranges): New variable.

View File

@ -749,7 +749,9 @@ weak object symbol. When a weak defined symbol is linked with a normal
defined symbol, the normal defined symbol is used with no error.
When a weak undefined symbol is linked and the symbol is not defined,
the value of the symbol is determined in a system-specific manner without
error. Uppercase indicates that a default value has been specified.
error. On some systems, uppercase indicates that a default value has been
specified.
@item -
The symbol is a stabs symbol in an a.out object file. In this case, the

View File

@ -1,3 +1,27 @@
2004-11-08 Aaron W. LaFramboise <aaron98wiridge9@aaronwl.com>
* symbols.c (any_external_name): Define.
(resolve_symbol_value): Do not convert weak symbols.
(S_SET_EXTERNAL): Support any_external_name.
(S_SET_NAME): Qualify parameter const.
(symbol_equated_reloc_p): Don't equate weaks when relocating.
* symbols.h (S_SET_NAME): Qualfiy parameter const.
* tc.h (any_external_name): Declare.
* config/obj-coff.c ("coff/pe.h"): Include for BFD
assemblers also.
(weak_is_altname): Declare and define.
(weak_name2altname): Same.
(weak_altname2name): Same.
(weak_uniquify): Same.
(weak_altprefix): Define.
(obj_coff_weak): Change .weak syntax and handling.
(coff_frob_symbol): Fix PE weak symbol alternates.
* config/obj-coff.h (USE_UNIQUE): Define.
* config/tc-i386.c (md_apply_fix3): Assume weak symbols
are in another segment.
(tc_gen_reloc): Remove broken addend hack.
doc/as.texinfo: Update.
2004-11-05 Sterling Augustine <sterling@tensilica.com>
* config/tc-xtensa.c (total_frag_text_expansion): New.

View File

@ -26,6 +26,10 @@
#include "obstack.h"
#include "subsegs.h"
#ifdef TE_PE
#include "coff/pe.h"
#endif
/* I think this is probably always correct. */
#ifndef KEEP_RELOC_INFO
#define KEEP_RELOC_INFO
@ -41,6 +45,10 @@
/* This is used to hold the symbol built by a sequence of pseudo-ops
from .def and .endef. */
static symbolS *def_symbol_in_progress;
#ifdef TE_PE
/* PE weak alternate symbols begin with this string. */
static const char weak_altprefix[] = ".weak.";
#endif /* TE_PE */
typedef struct
{
@ -1096,14 +1104,84 @@ obj_coff_val (ignore)
demand_empty_rest_of_line ();
}
#ifdef TE_PE
/* Return nonzero if name begins with weak alternate symbol prefix. */
static int
weak_is_altname (const char * name)
{
return ! strncmp (name, weak_altprefix, sizeof (weak_altprefix) - 1);
}
/* Return the name of the alternate symbol
name corresponding to a weak symbol's name. */
static const char *
weak_name2altname (const char * name)
{
char *alt_name;
alt_name = xmalloc (sizeof (weak_altprefix) + strlen (name));
strcpy (alt_name, weak_altprefix);
return strcat (alt_name, name);
}
/* Return the name of the weak symbol corresponding to an
alterate symbol. */
static const char *
weak_altname2name (const char * name)
{
char * weak_name;
char * dot;
assert (weak_is_altname (name));
weak_name = xstrdup (name + 6);
if ((dot = strchr (weak_name, '.')))
*dot = 0;
return weak_name;
}
/* Make a weak symbol name unique by
appending the name of an external symbol. */
static const char *
weak_uniquify (const char * name)
{
char *ret;
const char * unique = "";
#ifdef USE_UNIQUE
if (an_external_name != NULL)
unique = an_external_name;
#endif
assert (weak_is_altname (name));
if (strchr (name + sizeof (weak_altprefix), '.'))
return name;
ret = xmalloc (strlen (name) + strlen (unique) + 2);
strcpy (ret, name);
strcat (ret, ".");
strcat (ret, unique);
return ret;
}
#endif /* TE_PE */
/* Handle .weak. This is a GNU extension in formats other than PE. */
static void
obj_coff_weak (ignore)
int ignore ATTRIBUTE_UNUSED;
obj_coff_weak (int ignore ATTRIBUTE_UNUSED)
{
char *name;
int c;
symbolS *symbolP;
#ifdef TE_PE
symbolS *alternateP;
#endif
do
{
@ -1115,6 +1193,7 @@ obj_coff_weak (ignore)
ignore_rest_of_line ();
return;
}
c = 0;
symbolP = symbol_find_or_make (name);
*input_line_pointer = c;
SKIP_WHITESPACE ();
@ -1125,42 +1204,20 @@ obj_coff_weak (ignore)
#ifdef TE_PE
/* See _Microsoft Portable Executable and Common Object
* File Format Specification_, section 5.5.3.
* Note that weak symbols without aux records are a GNU
* extension.
*/
File Format Specification_, section 5.5.3.
Create a symbol representing the alternate value.
coff_frob_symbol will set the value of this symbol from
the value of the weak symbol itself. */
S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
S_SET_NUMBER_AUXILIARY (symbolP, 1);
SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_LIBRARY);
if (c == '=')
{
symbolS *alternateP;
long characteristics = 2;
++input_line_pointer;
if (*input_line_pointer == '=')
{
characteristics = 1;
++input_line_pointer;
}
alternateP = symbol_find_or_make (weak_name2altname (name));
S_SET_EXTERNAL (alternateP);
S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
SKIP_WHITESPACE();
name = input_line_pointer;
c = get_symbol_end();
if (*name == 0)
{
as_warn (_("alternate name missing in .weak directive"));
ignore_rest_of_line ();
return;
}
alternateP = symbol_find_or_make (name);
*input_line_pointer = c;
S_SET_NUMBER_AUXILIARY (symbolP, 1);
SA_SET_SYM_TAGNDX (symbolP, alternateP);
SA_SET_SYM_FSIZE (symbolP, characteristics);
}
#else /* TE_PE */
S_SET_STORAGE_CLASS (symbolP, C_WEAKEXT);
#endif /* TE_PE */
SA_SET_SYM_TAGNDX (symbolP, alternateP);
#endif
if (c == ',')
{
@ -1214,14 +1271,67 @@ coff_frob_symbol (symp, punt)
if (!block_stack)
block_stack = stack_init (512, sizeof (symbolS*));
if (S_IS_WEAK (symp))
{
#ifdef TE_PE
S_SET_STORAGE_CLASS (symp, C_NT_WEAK);
#else
S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
#endif
if (S_GET_STORAGE_CLASS (symp) == C_NT_WEAK
&& ! S_IS_WEAK (symp)
&& weak_is_altname (S_GET_NAME (symp)))
{
/* This is a weak alternate symbol. All processing of
PECOFFweak symbols is done here, through the alternate. */
symbolS *weakp = symbol_find (weak_altname2name (S_GET_NAME (symp)));
assert (weakp);
assert (S_GET_NUMBER_AUXILIARY (weakp) == 1);
if (symbol_equated_p (weakp))
{
/* The weak symbol has an alternate specified; symp is unneeded. */
S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
SA_SET_SYM_TAGNDX (weakp,
symbol_get_value_expression (weakp)->X_add_symbol);
S_CLEAR_EXTERNAL (symp);
*punt = 1;
return;
}
else
{
/* The weak symbol has been assigned an alternate value.
Copy this value to symp, and set symp as weakp's alternate. */
if (S_GET_STORAGE_CLASS (weakp) != C_NT_WEAK)
{
S_SET_STORAGE_CLASS (symp, S_GET_STORAGE_CLASS (weakp));
S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
}
if (S_IS_DEFINED (weakp))
{
/* This is a defined weak symbol. Copy value information
from the weak symbol itself to the alternate symbol. */
symbol_set_value_expression (symp,
symbol_get_value_expression (weakp));
symbol_set_frag (symp, symbol_get_frag (weakp));
S_SET_SEGMENT (symp, S_GET_SEGMENT (weakp));
}
else
{
/* This is an undefined weak symbol.
Define the alternate symbol to zero. */
S_SET_VALUE (symp, 0);
S_SET_SEGMENT (symp, absolute_section);
}
S_SET_NAME (symp, weak_uniquify (S_GET_NAME (symp)));
S_SET_STORAGE_CLASS (symp, C_EXT);
S_SET_VALUE (weakp, 0);
S_SET_SEGMENT (weakp, undefined_section);
}
}
#else /* TE_PE */
if (S_IS_WEAK (symp))
S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
#endif /* TE_PE */
if (!S_IS_DEFINED (symp)
&& !S_IS_WEAK (symp)
@ -1722,10 +1832,6 @@ symbol_dump ()
#include "libbfd.h"
#include "libcoff.h"
#ifdef TE_PE
#include "coff/pe.h"
#endif
/* The NOP_OPCODE is for the alignment fill value. Fill with nop so
that we can stick sections together without causing trouble. */
#ifndef NOP_OPCODE

View File

@ -1,6 +1,6 @@
/* coff object file format
Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2002, 2003
1999, 2000, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GAS.
@ -180,14 +180,19 @@
#endif
#endif
#ifdef TE_PE
/* PE weak symbols need USE_UNIQUE. */
#define USE_UNIQUE 1
#endif
/* Targets may also set this. Also, if BFD_ASSEMBLER is defined, this
will already have been defined. */
#undef SYMBOLS_NEED_BACKPOINTERS
#undef SYMBOLS_NEED_BACKPOINTERS
#define SYMBOLS_NEED_BACKPOINTERS 1
#ifndef OBJ_COFF_MAX_AUXENTRIES
#define OBJ_COFF_MAX_AUXENTRIES 1
#endif /* OBJ_COFF_MAX_AUXENTRIES */
#endif
extern void coff_obj_symbol_new_hook PARAMS ((symbolS *));
#define obj_symbol_new_hook coff_obj_symbol_new_hook

View File

@ -4801,9 +4801,13 @@ md_apply_fix3 (fixP, valP, seg)
}
#endif
#if defined (OBJ_COFF) && defined (TE_PE)
/* For some reason, the PE format does not store a section
address offset for a PC relative symbol. */
if (S_GET_SEGMENT (fixP->fx_addsy) != seg)
/* For some reason, the PE format does not store a
section address offset for a PC relative symbol. */
if (S_GET_SEGMENT (fixP->fx_addsy) != seg
#if defined(BFD_ASSEMBLER) || defined(S_IS_WEAK)
|| S_IS_WEAK (fixP->fx_addsy)
#endif
)
value += md_pcrel_from (fixP);
#endif
}
@ -5378,11 +5382,6 @@ tc_gen_reloc (section, fixp)
rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
#ifdef TE_PE
if (S_IS_WEAK (fixp->fx_addsy))
rel->addend = rel->address - (*rel->sym_ptr_ptr)->value + 4;
else
#endif
if (!use_rela_relocations)
{
/* HACK: Since i386 ELF uses Rel instead of Rela, encode the

View File

@ -5872,24 +5872,13 @@ parent name of @code{0} is treated as refering the @code{*ABS*} section.
This directive sets the weak attribute on the comma separated list of symbol
@code{names}. If the symbols do not already exist, they will be created.
Weak symbols are supported in COFF as a GNU extension. This directive
sets the weak attribute on the comma separated list of symbol
On COFF targets other than PE, weak symbols are a GNU extension. This
directive sets the weak attribute on the comma separated list of symbol
@code{names}. If the symbols do not already exist, they will be created.
@smallexample
@code{.weak @var{name} [ < = | == > @var{alternate}] [, ...]}
@end smallexample
On the PE target, weak aliases are supported natively. Weak aliases
(usually called "weak externals" in PE) are created when an alternate
name is specified. When a weak symbol is linked and the symbol is not
defined, the weak symbol becomes an alias for the alternate symbol. If
one equal sign is used, the linker searches for defined symbols within
other objects and libraries. This is the usual mode, historically
called "lazy externals." Otherwise, when two equal signs are used,
the linker searches for defined symbols only within other objects.
Non-alias weak symbols are supported on PE as a GNU extension.
On the PE target, weak symbols are supported natively as weak aliases.
When a weak symbol is created that is not an alias, GAS creates an
alternate symbol to hold the default value.
@node Word
@section @code{.word @var{expressions}}

View File

@ -59,6 +59,11 @@ symbolS abs_symbol;
#define LOCAL_LABEL_CHAR '\002'
struct obstack notes;
#ifdef USE_UNIQUE
/* The name of an external symbol which is
used to make weak PE symbol names unique. */
const char * an_external_name;
#endif
static char *save_symbol_name (const char *);
static void fb_label_init (void);
@ -989,7 +994,11 @@ resolve_symbol_value (symbolS *symp)
relocation to detect this case, and convert the
relocation to be against the symbol to which this symbol
is equated. */
if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol))
if (! S_IS_DEFINED (add_symbol)
#if defined(BFD_ASSEMBLER) || defined(S_IS_WEAK)
|| S_IS_WEAK (add_symbol)
#endif
|| S_IS_COMMON (add_symbol))
{
if (finalize_syms)
{
@ -1905,6 +1914,11 @@ S_SET_EXTERNAL (symbolS *s)
}
s->bsym->flags |= BSF_GLOBAL;
s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
#ifdef USE_UNIQUE
if (! an_external_name && S_GET_NAME(s)[0] != '.')
an_external_name = S_GET_NAME (s);
#endif
}
void
@ -1949,7 +1963,7 @@ S_SET_THREAD_LOCAL (symbolS *s)
}
void
S_SET_NAME (symbolS *s, char *name)
S_SET_NAME (symbolS *s, const char *name)
{
if (LOCAL_SYMBOL_CHECK (s))
{
@ -2225,6 +2239,9 @@ symbol_equated_reloc_p (symbolS *s)
resolve_symbol_value to flag expression syms that have been
equated. */
return (s->sy_value.X_op == O_symbol
#if defined(BFD_ASSEMBLER) || defined(S_IS_WEAK)
&& ! S_IS_WEAK (s)
#endif
&& ((s->sy_resolved && s->sy_value.X_op_symbol != NULL)
|| ! S_IS_DEFINED (s)
|| S_IS_COMMON (s)));

View File

@ -1,6 +1,6 @@
/* symbols.h -
Copyright 1987, 1990, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001,
2002, 2003 Free Software Foundation, Inc.
2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -105,7 +105,7 @@ extern const char *S_GET_NAME (symbolS *);
extern segT S_GET_SEGMENT (symbolS *);
extern void S_SET_SEGMENT (symbolS *, segT);
extern void S_SET_EXTERNAL (symbolS *);
extern void S_SET_NAME (symbolS *, char *);
extern void S_SET_NAME (symbolS *, const char *);
extern void S_CLEAR_EXTERNAL (symbolS *);
extern void S_SET_WEAK (symbolS *);
extern void S_SET_THREAD_LOCAL (symbolS *);

View File

@ -1,6 +1,6 @@
/* tc.h - target cpu dependent
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 2000, 2001, 2003
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 2000, 2001, 2003, 2004
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -59,6 +59,12 @@ extern int md_short_jump_size;
extern int md_long_jump_size;
#endif
#ifdef USE_UNIQUE
/* The name of an external symbol which is
used to make weak PE symbol names unique. */
extern const char * an_external_name;
#endif
#ifndef md_create_long_jump
void md_create_long_jump (char *, addressT, addressT, fragS *, symbolS *);
#endif

View File

@ -1,3 +1,9 @@
2004-11-08 Aaron W. LaFramboise <aaron98wiridge9@aaronwl.com>
* pe.h (IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY): Define.
(IMAGE_WEAK_EXTERN_SEARCH_LIBRARY): Same.
(IMAGE_WEAK_EXTERN_SEARCH_ALIAS): Same.
2004-08-13 Mark Kettenis <kettenis@gnu.org>
* symconst.h (langMax): Fix typo in comment.

View File

@ -1,6 +1,6 @@
/* pe.h - PE COFF header information
Copyright 2000, 2001, 2003 Free Software Foundation, Inc.
Copyright 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@ -310,4 +310,9 @@ typedef struct
#define IMPORT_NAME_NOPREFIX 2
#define IMPORT_NAME_UNDECORATE 3
/* Weak external characteristics. */
#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
#endif /* _PE_H */

View File

@ -1,3 +1,11 @@
2004-11-08 Aaron W. LaFramboise <aaron98wiridge9@aaronwl.com>
* testsuite/ld-scripts/weak.exp: Enable test on PE,
XFAIL non-i386 PE.
* testsuite/ld-undefined/weak-undef.exp: Enable test on PE,
XFAIL non-i386 PE.
* testsuite/lib/ld-lib.exp (is_pecoff_format): New.
2004-11-04 Daniel Jacobowitz <dan@debian.org>
* Makefile.am (ALL_EMULATIONS): Remove earmelf_oabi.o.

View File

@ -1,6 +1,6 @@
# Test weak symbols.
# By Ian Lance Taylor, Cygnus Solutions.
# Copyright 2001
# Copyright 2001, 2004
# Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify
@ -19,12 +19,17 @@
set testname "weak symbols"
# This test only works for ELF targets. It ought to work for some
# a.out targets, but it doesn't.
if ![is_elf_format] {
# This test only works for ELF targets.
# It ought to work for some a.out targets, but it doesn't.
if {! [is_elf_format] && ! [is_pecoff_format]} {
unsupported $testname
return
}
# Weak symbols are broken for non-i386 PE targets.
if {! [istarget i?86-*-*]} {
setup_xfail *-*-pe*
}
if {! [ld_assemble $as $srcdir/$subdir/weak1.s tmpdir/weak1.o]
|| ! [ld_assemble $as $srcdir/$subdir/weak2.s tmpdir/weak2.o]} then {

View File

@ -1,5 +1,5 @@
# Test handling of weak undefined symbols
# Copyright 2001
# Copyright 2001, 2004
# Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify
@ -29,15 +29,23 @@ if { ![istarget *-*-sysv4*] \
&& ![istarget *-*-linux*] \
&& ![istarget *-*-irix5*] \
&& ![istarget *-*-irix6*] \
&& ![is_pecoff_format] \
&& ![istarget *-*-solaris2*] } then {
unsupported $testname
return
}
if { [istarget *-*-linux*aout*] \
|| [istarget *-*-linux*oldld*] } {
unsupported $testname
return
}
# Weak symbols are broken for non-i386 PE targets.
if {! [istarget i?86-*-*]} {
setup_xfail *-*-pe*
}
if {! [ld_assemble $as $srcdir/$subdir/weak-undef.s tmpdir/weak-undef.o]} then {
# It's OK if .weak doesn't work on this target.
unresolved $testname

View File

@ -1,5 +1,5 @@
# Support routines for LD testsuite.
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
# Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify
@ -416,6 +416,20 @@ proc is_elf64 { binary_file } {
return 0
}
#
# is_pecoff_format
# true if the object format is known to be PECOFF
#
proc is_pecoff_format {} {
if { ![istarget *-*-mingw32*] \
&& ![istarget *-*-cygwin*] \
&& ![istarget *-*-pe*] } {
return 0
}
return 1
}
#
# simple_diff
# compares two files line-by-line