+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
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"
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;
}
+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.
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
+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.
#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
/* 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
{
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
{
ignore_rest_of_line ();
return;
}
+ c = 0;
symbolP = symbol_find_or_make (name);
*input_line_pointer = c;
SKIP_WHITESPACE ();
#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;
- }
-
- 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;
+ alternateP = symbol_find_or_make (weak_name2altname (name));
+ S_SET_EXTERNAL (alternateP);
+ S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
- 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 == ',')
{
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)
#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
/* 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.
#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
}
#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
}
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
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}}
#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);
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)
{
}
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
}
void
-S_SET_NAME (symbolS *s, char *name)
+S_SET_NAME (symbolS *s, const char *name)
{
if (LOCAL_SYMBOL_CHECK (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)));
/* 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.
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 *);
/* 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.
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
+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.
/* 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.
#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 */
+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.
# 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
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 {
# 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
&& ![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
# 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
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