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: cygwin/mingw32 Standard weak externals on PE COFF


Hi,

This patch implements the weak externals specified in _Microsoft Portable Executable and Common Object File Format Specification_, section 5.5.3 for the assembler and the linker. It also adds some documentation.

I've tested the assembler and linker patches against the Microsoft assembler and linker for compatibility, and everything seems to work fine. However, most of the time non-aliased weak symbols (which are a GNU extension) cause the Microsoft linker to reject the input object (but they do work in some situations).

Since the Microsoft assembler's notation of weak symbols is inappropriate for GAS, I used the Intel assembler's syntax, which is more expressive anyway.

One thing I'd like to add to this is a few tests to ensure weak symbols are working properly, but I'm not entirely sure how to do this.

I'm also not entirely sure that I've altered the documentation in the correct manner.

There is also a comment on the "ld and WIN32 (cygwin/mingw)" node that suggests using "__attribute__ ((weak, alias ("foo")))", which as far as I know has never worked, because neither GCC nor binutils has had the appropriate support. I'm planning on submitting a patch to GCC that will add this support.

2004-06-05 Aaron W. LaFramboise <aaron98wiridge9@aaronwl.com>

	* bfd/cofflink.c (_bfd_coff_generic_relocate_section): Resolve
	PE weak externals properly.
	* src/gas/config/obj-coff.c (obj_coff_weak): New .weak syntax for
	PE weak externals.
	* binutils/doc/binutils.texi (nm): Clarify weak symbol description.
	* gas/doc/as.texinfo (Weak): Document PE weak symbols.
	* ld/ld.texinfo (WIN32): Document PE weak symbols.

Index: src/bfd/cofflink.c
===================================================================
RCS file: /cvs/src/src/bfd/cofflink.c,v
retrieving revision 1.43
diff -c -3 -p -r1.43 cofflink.c
*** src/bfd/cofflink.c	24 Nov 2003 18:06:40 -0000	1.43
--- src/bfd/cofflink.c	5 Jun 2004 08:51:12 -0000
*************** _bfd_coff_generic_relocate_section (bfd
*** 2925,2930 ****
--- 2925,2931 ----
  	  if (h->root.type == bfd_link_hash_defined
  	      || h->root.type == bfd_link_hash_defweak)
  	    {
+ 	      /* Defined weak symbols are a GNU extension. */
  	      asection *sec;

  	      sec = h->root.u.def.section;
*************** _bfd_coff_generic_relocate_section (bfd
*** 2934,2940 ****
  	      }

  	  else if (h->root.type == bfd_link_hash_undefweak)
! 	    val = 0;

  	  else if (! info->relocatable)
  	    {
--- 2935,2965 ----
  	      }

  	  else if (h->root.type == bfd_link_hash_undefweak)
! 	    {
!               if (h->class == C_NT_WEAK && h->numaux == 1)
! 		{
! 		  /* 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.
! 		   * FIXME: All weak externals are treated as having
! 		   * characteristics IMAGE_WEAK_EXTERN_SEARCH_LIBRARY (2).
! 		   * There are no known uses of the other two types of
! 		   * weak externals.
! 		   */
! 		  asection *sec;
! 		  struct coff_link_hash_entry *h2 =
! 		    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. */
! 		val = 0;
! 	    }

  	  else if (! info->relocatable)
  	    {
Index: src/binutils/doc/binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.52
diff -c -3 -p -r1.52 binutils.texi
*** src/binutils/doc/binutils.texi	23 Dec 2003 13:01:11 -0000	1.52
--- src/binutils/doc/binutils.texi	5 Jun 2004 09:04:59 -0000
*************** The symbol is a weak symbol that has not
*** 748,754 ****
  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 weak symbol becomes zero with no error.

  @item -
  The symbol is a stabs symbol in an a.out object file.  In this case, the
--- 748,755 ----
  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.

  @item -
  The symbol is a stabs symbol in an a.out object file.  In this case, the
Index: src/gas/config/obj-coff.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-coff.c,v
retrieving revision 1.69
diff -c -3 -p -r1.69 obj-coff.c
*** src/gas/config/obj-coff.c	20 Nov 2003 00:01:54 -0000	1.69
--- src/gas/config/obj-coff.c	5 Jun 2004 08:52:04 -0000
*************** obj_coff_bss (ignore)
*** 212,258 ****
      s_lcomm (0);
  }

- /* Handle .weak.  This is a GNU extension.  */
-
- static void
- obj_coff_weak (ignore)
-      int ignore ATTRIBUTE_UNUSED;
- {
-   char *name;
-   int c;
-   symbolS *symbolP;
-
-   do
-     {
-       name = input_line_pointer;
-       c = get_symbol_end ();
-       symbolP = symbol_find_or_make (name);
-       *input_line_pointer = c;
-       SKIP_WHITESPACE ();
-
- #if defined BFD_ASSEMBLER || defined S_SET_WEAK
-       S_SET_WEAK (symbolP);
- #endif
-
- #ifdef TE_PE
-       S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
- #else
-       S_SET_STORAGE_CLASS (symbolP, C_WEAKEXT);
- #endif
-
-       if (c == ',')
- 	{
- 	  input_line_pointer++;
- 	  SKIP_WHITESPACE ();
- 	  if (*input_line_pointer == '\n')
- 	    c = '\n';
- 	}
-     }
-   while (c == ',');
-
-   demand_empty_rest_of_line ();
- }
-
  #ifdef BFD_ASSEMBLER

  static segT fetch_coff_debug_section PARAMS ((void));
--- 212,217 ----
*************** obj_coff_val (ignore)
*** 1135,1140 ****
--- 1094,1178 ----
    demand_empty_rest_of_line ();
  }

+ /* Handle .weak.  This is a GNU extension in formats other than PE. */
+ static void
+ obj_coff_weak (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   char *name;
+   int c;
+   symbolS *symbolP;
+
+   do
+     {
+       name = input_line_pointer;
+       c = get_symbol_end ();
+       if (*name == 0)
+ 	{
+ 	  as_warn (_("badly formed .weak directive ignored"));
+ 	  ignore_rest_of_line ();
+ 	  return;
+ 	}
+       symbolP = symbol_find_or_make (name);
+       *input_line_pointer = c;
+       SKIP_WHITESPACE ();
+
+ #if defined BFD_ASSEMBLER || defined S_SET_WEAK
+       S_SET_WEAK (symbolP);
+ #endif
+
+ #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 == ',')
+ 	{
+ 	  input_line_pointer++;
+ 	  SKIP_WHITESPACE ();
+ 	  if (*input_line_pointer == '\n')
+ 	    c = '\n';
+ 	}
+
+     }
+   while (c == ',');
+
+   demand_empty_rest_of_line ();
+ }
+
  void
  coff_obj_read_begin_hook ()
  {
Index: src/gas/doc/as.texinfo
===================================================================
RCS file: /cvs/src/src/gas/doc/as.texinfo,v
retrieving revision 1.100
diff -c -3 -p -r1.100 as.texinfo
*** src/gas/doc/as.texinfo	11 May 2004 15:53:47 -0000	1.100
--- src/gas/doc/as.texinfo	5 Jun 2004 08:52:19 -0000
*************** respectively, with @code{.val} and @code
*** 3400,3407 ****

@cindex auxiliary attributes, COFF symbols
The @command{@value{AS}} directives @code{.dim}, @code{.line}, @code{.scl},
! @code{.size}, and @code{.tag} can generate auxiliary symbol table
! information for COFF.
@end ifset


  @ifset SOM
--- 3400,3407 ----

@cindex auxiliary attributes, COFF symbols
The @command{@value{AS}} directives @code{.dim}, @code{.line}, @code{.scl},
! @code{.size}, @code{.tag}, and @code{.weak} can generate auxiliary symbol
! table information for COFF.
@end ifset


@ifset SOM
*************** Some machine configurations provide addi
*** 3823,3831 ****
* Version:: @code{.version "@var{string}"}
* VTableEntry:: @code{.vtable_entry @var{table}, @var{offset}}
* VTableInherit:: @code{.vtable_inherit @var{child}, @var{parent}}
- * Weak:: @code{.weak @var{names}}
@end ifset


* Word:: @code{.word @var{expressions}}
* Deprecated:: Deprecated Directives
@end menu
--- 3823,3831 ----
* Version:: @code{.version "@var{string}"}
* VTableEntry:: @code{.vtable_entry @var{table}, @var{offset}}
* VTableInherit:: @code{.vtable_inherit @var{child}, @var{parent}}
@end ifset


+ * Weak::                        @code{.weak @var{names}}
  * Word::                        @code{.word @var{expressions}}
  * Deprecated::                  Deprecated Directives
  @end menu
*************** parent whose addend is the value of the
*** 5808,5821 ****
  parent name of @code{0} is treated as refering the @code{*ABS*} section.
  @end ifset

- @ifset ELF
  @node Weak
  @section @code{.weak @var{names}}

@cindex @code{weak} directive
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.
! @end ifset


  @node Word
  @section @code{.word @var{expressions}}
--- 5808,5838 ----
  parent name of @code{0} is treated as refering the @code{*ABS*} section.
  @end ifset

  @node Weak
  @section @code{.weak @var{names}}

@cindex @code{weak} directive
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}}
Index: src/ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.117
diff -c -3 -p -r1.117 ld.texinfo
*** src/ld/ld.texinfo 23 May 2004 09:30:31 -0000 1.117
--- src/ld/ld.texinfo 5 Jun 2004 08:53:19 -0000
*************** to handle the other symbols, then the bo
*** 5292,5297 ****
--- 5292,5315 ----
the original names for the renamed symbols will be exported.
In effect, you'd be aliasing those symbols, not renaming them,
which is probably not what you wanted.
+
+ @cindex weak externals
+ @item weak externals
+ The Windows object format, PE, specifies a form of weak symbols called
+ weak externals. When a weak symbol is linked and the symbol is not
+ defined, the weak symbol becomes an alias for some other symbol. There
+ are three variants of weak externals:
+ @itemize
+ @item Definition is searched for in objects and libraries, historically
+ called lazy externals.
+ @item Definition is searched for only in other objects, not in libraries.
+ This form is not presently implemented.
+ @item No search; the symbol is an alias. This form is not presently
+ implemented.
+ @end itemize
+ As a GNU extension, weak symbols that do not specify an alternate symbol
+ are supported. If the symbol is undefined when linking, the symbol
+ uses a default value.
@end table


@ifclear GENERIC


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