This is the mail archive of the binutils@sources.redhat.com 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] Revise Windows PECOFF weak symbols


My initial PECOFF weak symbol implementation, submitted here
<http://sources.redhat.com/ml/binutils/2004-07/msg00036.html>, had the
problem that it was unlike weak symbols on other platforms and other
features in gas.  In the non-alias case, it was also not compliant with
regards to the specification, as PECOFF does not natively support
non-alias weak symbols.  I had based it off a description of the Intel
assembler's .weak from their manual.  However, I now do not think this
is the right way to go here.  There were also a few bugs in weak symbol
relocation handling.

With this patch, weak symbols on PE behave as on other platforms, with
the same syntax, in full compliance with the specification.  This is
accomplished by creating an alternate symbol that is given the value of
the weak symbol, if the weak symbol would not refer to another symbol.
These weak symbols have semantics a lot better than Intel's, and make it
much easier for compilers and users alike.

Handling of the alternate symbols forms the majority of this patch.  The
first complication is that they should not be emitted when not needed.
(Despite this, there is still one case where this happens.  If a weak
symbol is equated to a symbol which is defined within the same file, an
alternate symbol will be created with the same value.  This is not
harmful, and seems particularly difficult to fix.)

The second complication is that since alternate names are external, they
must be unique to a file.  Uniqueness is accomplished by creating the
symbol name from the name of the weak symbol and the name of an
arbitrary external symbol.  (Randomness should not be used because it
wouldn't be guaranteed to work, and would cause nondeterminism.)

Besides the modifications to gas, there are small two modifications to
bfd that fix handling of weak symbols on PE.  There are also some minor
documentation updates.

The ld testcase is also altered to let some of the weak symbol test
cases (that previously only ran on ELF) run for PE.

I have a copyright assignment, but no CVS access.

Aaron W. LaFramboise

2004-10-19  Aaron W. LaFramboise <aaron98wiridge9@aaronwl.com>

bfd
	* 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.

binutils
	* doc/binutils.texi (nm): Update.

gas
	* 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.

include
	coff/pe.h (IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY): Define.
	(IMAGE_WEAK_EXTERN_SEARCH_LIBRARY): Same.
	(IMAGE_WEAK_EXTERN_SEARCH_ALIAS): Same.

ld
	* testsuite/ld-scripts/weak.exp: Test is_pecoff_format.
	* testsuite/ld-undefined/weak-undef.exp: Test on
	mingw32, cygwin, and pe targets.
	* testsuite/lib/ld-lib.exp (is_pecoff_format): New.

Index: src/bfd/coff-i386.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-i386.c,v
retrieving revision 1.20
diff -c -3 -p -r1.20 coff-i386.c
*** src/bfd/coff-i386.c	22 Jun 2004 05:35:37 -0000	1.20
--- src/bfd/coff-i386.c	19 Oct 2004 10:28:34 -0000
*************** coff_i386_reloc (abfd, reloc_entry, symb
*** 122,127 ****
--- 122,132 ----
  	  else
  	    diff = -reloc_entry->addend;
  	}
+       else if (symbol->flags & BSF_WEAK)
+ 	{
+ 	  reloc_howto_type *howto = reloc_entry->howto;
+ 	  diff = reloc_entry->addend - symbol->value;
+ 	}
        else
  #endif
  	diff = reloc_entry->addend;
Index: src/bfd/cofflink.c
===================================================================
RCS file: /cvs/src/src/bfd/cofflink.c,v
retrieving revision 1.49
diff -c -3 -p -r1.49 cofflink.c
*** src/bfd/cofflink.c	18 Aug 2004 09:44:11 -0000	1.49
--- src/bfd/cofflink.c	19 Oct 2004 10:28:40 -0000
*************** _bfd_coff_link_input_bfd (struct coff_fi
*** 1976,1982 ****
  		      auxp->x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
  		    }
  		}
! 	      else if (isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
  		{
  		  unsigned long indx;
  
--- 1976,1983 ----
  		      auxp->x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
  		    }
  		}
! 	      else if ((isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
! 		&& isymp->n_sclass != C_NT_WEAK)
  		{
  		  unsigned long indx;
  
*************** _bfd_coff_generic_relocate_section (bfd 
*** 2948,2956 ****
  		    input_bfd->tdata.coff_obj_data->sym_hashes[
  		    h->aux->x_sym.x_tagndx.l];
  
! 		  sec = h2->root.u.def.section;
! 		  val = h2->root.u.def.value + sec->output_section->vma
! 		    + sec->output_offset;
  		}
  	      else
                  /* This is a GNU extension. */
--- 2949,2965 ----
  		    input_bfd->tdata.coff_obj_data->sym_hashes[
  		    h->aux->x_sym.x_tagndx.l];
  
! 		  if (!h2 || h2->root.type == bfd_link_hash_undefined)
! 		    {
! 		      sec = bfd_abs_section_ptr;
! 		      val = 0;
! 		    }
! 		  else
! 		    {
! 		      sec = h2->root.u.def.section;
! 		      val = h2->root.u.def.value
! 			+ sec->output_section->vma + sec->output_offset;
! 		    }
  		}
  	      else
                  /* This is a GNU extension. */
Index: src/binutils/doc/binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.58
diff -c -3 -p -r1.58 binutils.texi
*** src/binutils/doc/binutils.texi	8 Oct 2004 14:54:04 -0000	1.58
--- src/binutils/doc/binutils.texi	19 Oct 2004 10:28:49 -0000
*************** weak object symbol.  When a weak defined
*** 749,755 ****
  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.
  
  @item -
  The symbol is a stabs symbol in an a.out object file.  In this case, the
--- 749,756 ----
  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.  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
Index: src/gas/symbols.c
===================================================================
RCS file: /cvs/src/src/gas/symbols.c,v
retrieving revision 1.50
diff -c -3 -p -r1.50 symbols.c
*** src/gas/symbols.c	21 Jun 2004 10:59:54 -0000	1.50
--- src/gas/symbols.c	19 Oct 2004 10:28:54 -0000
*************** static void report_op_error (symbolS *, 
*** 77,82 ****
--- 77,89 ----
     set, and you are certain that this symbol won't be wanted in the
     output file, you can call symbol_create.  */
  
+ #ifdef USE_UNIQUE
+ /* The name of any external symbol is used to make weak symbol names
+  * unique.  USE_UNIQUE is defined in a target or object header if this
+  * is needed. */
+ const char *any_external_name;
+ #endif
+ 
  symbolS *
  symbol_new (const char *name, segT segment, valueT valu, fragS *frag)
  {
*************** resolve_symbol_value (symbolS *symp)
*** 992,998 ****
  	     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 (finalize_syms)
  		{
--- 999,1009 ----
  	     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)
! #if defined(BFD_ASSEMBLER) || defined(S_IS_WEAK)
! 	   || S_IS_WEAK (add_symbol)
! #endif
! 	   || S_IS_COMMON (add_symbol))
  	    {
  	      if (finalize_syms)
  		{
*************** S_SET_EXTERNAL (symbolS *s)
*** 1908,1913 ****
--- 1919,1929 ----
      }
    s->bsym->flags |= BSF_GLOBAL;
    s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
+ 
+ #ifdef USE_UNIQUE
+   if (! any_external_name && S_GET_NAME(s)[0] != '.' )
+     any_external_name = S_GET_NAME (s);
+ #endif
  }
  
  void
*************** S_SET_THREAD_LOCAL (symbolS *s)
*** 1952,1958 ****
  }
  
  void
! S_SET_NAME (symbolS *s, char *name)
  {
    if (LOCAL_SYMBOL_CHECK (s))
      {
--- 1968,1974 ----
  }
  
  void
! S_SET_NAME (symbolS *s, const char *name)
  {
    if (LOCAL_SYMBOL_CHECK (s))
      {
*************** symbol_equated_reloc_p (symbolS *s)
*** 2228,2233 ****
--- 2244,2252 ----
       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)));
Index: src/gas/symbols.h
===================================================================
RCS file: /cvs/src/src/gas/symbols.h,v
retrieving revision 1.15
diff -c -3 -p -r1.15 symbols.h
*** src/gas/symbols.h	30 Nov 2003 19:07:12 -0000	1.15
--- src/gas/symbols.h	19 Oct 2004 10:28:54 -0000
*************** extern const char *S_GET_NAME (symbolS *
*** 105,111 ****
  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_CLEAR_EXTERNAL (symbolS *);
  extern void S_SET_WEAK (symbolS *);
  extern void S_SET_THREAD_LOCAL (symbolS *);
--- 105,111 ----
  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 *, const char *);
  extern void S_CLEAR_EXTERNAL (symbolS *);
  extern void S_SET_WEAK (symbolS *);
  extern void S_SET_THREAD_LOCAL (symbolS *);
Index: src/gas/tc.h
===================================================================
RCS file: /cvs/src/src/gas/tc.h,v
retrieving revision 1.7
diff -c -3 -p -r1.7 tc.h
*** src/gas/tc.h	17 Aug 2004 12:19:55 -0000	1.7
--- src/gas/tc.h	19 Oct 2004 10:28:55 -0000
*************** void    tc_headers_hook (object_headers 
*** 104,106 ****
--- 104,114 ----
  #endif
  
  #endif /* BFD_ASSEMBLER */
+ 
+ #ifdef USE_UNIQUE
+ /* The name of any external symbol is used to make weak symbol names
+  * unique.  USE_UNIQUE is defined in a target or object header if this
+  * is needed. */
+ extern const char *any_external_name;
+ #endif
+ 
Index: src/gas/config/obj-coff.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-coff.c,v
retrieving revision 1.73
diff -c -3 -p -r1.73 obj-coff.c
*** src/gas/config/obj-coff.c	27 Jul 2004 11:37:08 -0000	1.73
--- src/gas/config/obj-coff.c	19 Oct 2004 10:29:02 -0000
***************
*** 26,31 ****
--- 26,35 ----
  #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
*************** static void obj_coff_ident PARAMS ((int)
*** 78,83 ****
--- 82,99 ----
  #ifdef BFD_ASSEMBLER
  static void obj_coff_loc PARAMS((int));
  #endif
+ 
+ #ifdef TE_PE
+ 
+ static int weak_is_altname PARAMS ((const char *));
+ static const char *weak_name2altname PARAMS ((const char *));
+ static const char *weak_altname2name PARAMS ((const char *));
+ static const char *weak_uniquify PARAMS ((const char *));
+ 
+ /* PE weak alternate symbols begin with this string */
+ static const char weak_altprefix[] = ".weak.";
+ 
+ #endif /* TE_PE */
  
  /* stack stuff */
  
*************** obj_coff_weak (ignore)
*** 1104,1109 ****
--- 1120,1128 ----
    char *name;
    int c;
    symbolS *symbolP;
+ #ifdef TE_PE
+   symbolS *alternateP;
+ #endif
  
    do
      {
*************** obj_coff_weak (ignore)
*** 1115,1120 ****
--- 1134,1140 ----
  	  ignore_rest_of_line ();
  	  return;
  	}
+       c = 0;
        symbolP = symbol_find_or_make (name);
        *input_line_pointer = c;
        SKIP_WHITESPACE ();
*************** obj_coff_weak (ignore)
*** 1126,1165 ****
  #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.
!        */
        S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
  
!       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;
  
! 	  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 */
  
        if (c == ',')
--- 1146,1163 ----
  #ifdef TE_PE
        /* See _Microsoft Portable Executable and Common Object
         * 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);
  
!       alternateP = symbol_find_or_make (weak_name2altname (name));
!       S_SET_EXTERNAL (alternateP);
!       S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
  
!       SA_SET_SYM_TAGNDX (symbolP, alternateP);
  #endif  /* TE_PE */
  
        if (c == ',')
*************** obj_coff_weak (ignore)
*** 1176,1181 ****
--- 1174,1239 ----
    demand_empty_rest_of_line ();
  }
  
+ #ifdef TE_PE
+ 
+ /* Return nonzero if name begins with weak alternate symbol prefix */
+ static int weak_is_altname (name)
+   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 (name)
+   const char *name;
+ {
+   char *alt_name;
+   alt_name = xmalloc (sizeof (weak_altprefix)
+     + strlen (name));
+   strcpy (alt_name, weak_altprefix);
+   strcat (alt_name, name);
+   return alt_name;
+ }
+ 
+ /* Return the name of the weak symbol corresponding to an 
+  * alterate symbol. */
+ static const char *weak_altname2name (name)
+   const char *name;
+ {
+   char *weak_name, *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 (name)
+   const char *name;
+ {
+   char *ret;
+   const char *unique = any_external_name ? any_external_name : "";
+ 
+   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 */
+ 
  void
  coff_obj_read_begin_hook ()
  {
*************** coff_frob_symbol (symp, punt)
*** 1214,1228 ****
    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_IS_DEFINED (symp)
        && !S_IS_WEAK (symp)
        && S_GET_STORAGE_CLASS (symp) != C_STAT)
--- 1272,1343 ----
    if (!block_stack)
      block_stack = stack_init (512, sizeof (symbolS*));
  
  #ifdef TE_PE
! 
!   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)
        && S_GET_STORAGE_CLASS (symp) != C_STAT)
*************** symbol_dump ()
*** 1722,1731 ****
  #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
--- 1837,1842 ----
Index: src/gas/config/obj-coff.h
===================================================================
RCS file: /cvs/src/src/gas/config/obj-coff.h,v
retrieving revision 1.20
diff -c -3 -p -r1.20 obj-coff.h
*** src/gas/config/obj-coff.h	20 Nov 2003 00:01:54 -0000	1.20
--- src/gas/config/obj-coff.h	19 Oct 2004 10:29:04 -0000
***************
*** 71,76 ****
--- 71,78 ----
  
  #ifdef TE_PE
  #define TARGET_FORMAT "pe-i386"
+ /* Weak symbols need USE_UNIQUE */
+ #define USE_UNIQUE 1
  #endif
  
  #ifndef TARGET_FORMAT
Index: src/gas/config/tc-i386.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.c,v
retrieving revision 1.158
diff -c -3 -p -r1.158 tc-i386.c
*** src/gas/config/tc-i386.c	18 Oct 2004 12:32:13 -0000	1.158
--- src/gas/config/tc-i386.c	19 Oct 2004 10:29:15 -0000
*************** md_apply_fix3 (fixP, valP, seg)
*** 4692,4698 ****
  #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)
  	value += md_pcrel_from (fixP);
  #endif
      }
--- 4692,4703 ----
  #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
! #if defined(BFD_ASSEMBLER) || defined(S_IS_WEAK)
! 	|| S_IS_WEAK (fixP->fx_addsy)
! #endif
! 	)
! 
  	value += md_pcrel_from (fixP);
  #endif
      }
*************** tc_gen_reloc (section, fixp)
*** 5266,5277 ****
    *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  
    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
--- 5271,5276 ----
Index: src/gas/doc/as.texinfo
===================================================================
RCS file: /cvs/src/src/gas/doc/as.texinfo,v
retrieving revision 1.107
diff -c -3 -p -r1.107 as.texinfo
*** src/gas/doc/as.texinfo	11 Oct 2004 16:39:34 -0000	1.107
--- src/gas/doc/as.texinfo	19 Oct 2004 10:29:29 -0000
*************** parent name of @code{0} is treated as re
*** 5870,5893 ****
  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
  @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.
  
  @node Word
  @section @code{.word @var{expressions}}
--- 5870,5882 ----
  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.
  
! 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.
  
! 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}}
Index: src/include/coff/pe.h
===================================================================
RCS file: /cvs/src/src/include/coff/pe.h,v
retrieving revision 1.11
diff -c -3 -p -r1.11 pe.h
*** src/include/coff/pe.h	17 Jul 2003 14:37:17 -0000	1.11
--- src/include/coff/pe.h	19 Oct 2004 10:29:38 -0000
*************** typedef struct 
*** 310,313 ****
--- 310,318 ----
  #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 */
Index: src/ld/testsuite/ld-scripts/weak.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-scripts/weak.exp,v
retrieving revision 1.6
diff -c -3 -p -r1.6 weak.exp
*** src/ld/testsuite/ld-scripts/weak.exp	7 May 2002 11:08:56 -0000	1.6
--- src/ld/testsuite/ld-scripts/weak.exp	19 Oct 2004 10:29:43 -0000
*************** set testname "weak symbols"
*** 21,27 ****
  
  # This test only works for ELF targets.  It ought to work for some
  # a.out targets, but it doesn't.
! if ![is_elf_format] {
      return
  }
  
--- 21,27 ----
  
  # 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]} {
      return
  }
  
Index: src/ld/testsuite/ld-undefined/weak-undef.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-undefined/weak-undef.exp,v
retrieving revision 1.3
diff -c -3 -p -r1.3 weak-undef.exp
*** src/ld/testsuite/ld-undefined/weak-undef.exp	30 Jul 2002 07:41:15 -0000	1.3
--- src/ld/testsuite/ld-undefined/weak-undef.exp	19 Oct 2004 10:29:44 -0000
*************** if { ![istarget *-*-sysv4*] \
*** 29,34 ****
--- 29,37 ----
       && ![istarget *-*-linux*] \
       && ![istarget *-*-irix5*] \
       && ![istarget *-*-irix6*] \
+      && ![istarget *-*-mingw32*] \
+      && ![istarget *-*-cygwin*] \
+      && ![istarget *-*-pe*] \
       && ![istarget *-*-solaris2*] } then {
      return
  }
Index: src/ld/testsuite/lib/ld-lib.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/lib/ld-lib.exp,v
retrieving revision 1.27
diff -c -3 -p -r1.27 ld-lib.exp
*** src/ld/testsuite/lib/ld-lib.exp	12 May 2004 03:08:09 -0000	1.27
--- src/ld/testsuite/lib/ld-lib.exp	19 Oct 2004 10:29:46 -0000
*************** proc is_elf64 { binary_file } {
*** 417,422 ****
--- 417,436 ----
  }
  
  #
+ # 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
  #	returns differences if exist

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