This is the mail archive of the binutils@sourceware.org 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] Support aligned common symbols on PE.


    Hi everyone,

  The attached patch implements aligned commons on PE targets, using
meta-information in the .drectve section to convey the alignment info, as
discussed previously on this list(*).

  As it only touches PE/COFF code, I could probably check this in on my own
recognizance these days.  But it's quite a big one, and the tests still have
24 hours or so to run, so I'd appreciate any review offered, particularly of
the texinfo markup.  It also touches the common GAS testsuite machinery,
although only trivially to add a function copied from LD's testsuite library,
but someone should still eyeball it.

  Note that at present, this patch uses default section flags if it creates
the .drectve section.  That's because GCC currently emits a plain ".section
.drectve" in the generated assembly.  By the time I've got the GCC end of this
ready, we should have Kai's NOREAD patch in, and then I'll update GCC and
binutils to both use it; until then, I don't want to trigger
clashing-section-flags warnings.  (It's not a problem that the .drectve
section gets marked CONTENTS, ALLOC, LOAD, DATA, because it gets dropped at
final link time anyway; it's only ever present in .o files.  Nonetheless, we
should still change it one the feature is there, to match the vendor tools.)

bfd/ChangeLog:

	* cofflink.c (process_embedded_commands):  Ignore "-aligncomm".

gas/ChangeLog:

	* NEWS:  Mention new feature.
	* config/obj-coff.c (obj_coff_common_parse):  New function.
	(obj_coff_comm):  Likewise.
	(coff_pseudo_table):  Override default ".comm" definition on PE.
	* doc/as.texinfo:  Document new feature.

gas/testsuite/ChangeLog

	* gas/pe/:  New directory for PE format-specific tests.
	* gas/pe/aligncomm-a.d:  New test pattern file.
	* gas/pe/aligncomm-a.s:  New test source file.
	* gas/pe/aligncomm-b.d:  New test pattern file.
	* gas/pe/aligncomm-b.s:  New test source file.
	* gas/pe/aligncomm-c.d:  New test pattern file.
	* gas/pe/aligncomm-c.s:  New test source file.
	* gas/pe/aligncomm-d.d:  New test pattern file.
	* gas/pe/aligncomm-d.s:  New test source file.
	* gas/pe/pe.exp:  New test control script.
	* lib/gas-defs.exp (is_pecoff_format):  New function.

ld/ChangeLog:

	* NEWS:  Mention new feature.
	* deffile.h (def_file_aligncomm):  Add new struct definition.
	(def_file):  Add new def_file_aligncomm member.
	* deffilep.y (%token):  Add new ALIGNCOMM token.
	(command):  Add production rule for ALIGNCOMM.
	(def_file_free):  Free any chained def_file_aligncomm structs.
	(diropts[]):  Add entry for '-aligncomm' .drectve command.
	(def_aligncomm):  New grammar function.
	* ld.texinfo:  Document new feature.
	* pe-dll.c (process_def_file):  Rename from this ...
	(process_def_file_and_drectve):  ... to this, updating all callers,
	and process any aligncomms chained to the def file after scanning
	all .drectve sections.
	(generate_edata):  Updated to match.
	(pe_dll_build_sections):  Likewise.

ld/testsuite/ChangeLog:

	* ld-pe/aligncomm-1.c:  New test source file.
	* ld-pe/aligncomm-2.c:  Likewise.
	* ld-pe/aligncomm-3.c:  Likewise.
	* ld-pe/aligncomm-4.c:  Likewise.
	* ld-pe/aligncomm.d:  New test pattern file.
	* ld-pe/pe.exp:  Run new aligned common tests.

  Tests still running, but otherwise, is this ok by all concerned?

    cheers,
      DaveK
-- 
(*) - http://sourceware.org/ml/binutils/2009-05/threads.html#00182
? ld/autom4te.cache
Index: bfd/cofflink.c
===================================================================
RCS file: /cvs/src/src/bfd/cofflink.c,v
retrieving revision 1.67
diff -p -u -r1.67 cofflink.c
--- bfd/cofflink.c	9 Oct 2008 09:00:07 -0000	1.67
+++ bfd/cofflink.c	16 May 2009 16:38:09 -0000
@@ -1282,6 +1282,15 @@ process_embedded_commands (bfd *output_b
       else if (CONST_STRNEQ (s, "-stack"))
 	s = dores_com (s + 6, output_bfd, 0);
 
+      /* GNU extension for aligned commons.  */
+      else if (CONST_STRNEQ (s, "-aligncomm:"))
+	{
+	  /* Common symbols must be aligned on reading, as it
+	  is too late to do anything here, after they have
+	  already been allocated, so just skip the directive.  */
+	  s += 11;
+	}
+
       else
 	s++;
     }
Index: gas/NEWS
===================================================================
RCS file: /cvs/src/src/gas/NEWS,v
retrieving revision 1.105
diff -p -u -r1.105 NEWS
--- gas/NEWS	30 Apr 2009 15:47:04 -0000	1.105
+++ gas/NEWS	16 May 2009 16:38:09 -0000
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Add support for common symbol alignment to PE formats.
+
 * Add support for the new discriminator column in the DWARF line table,
   with a discriminator operand for the .loc directive.
 
Index: gas/config/obj-coff.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-coff.c,v
retrieving revision 1.94
diff -p -u -r1.94 obj-coff.c
--- gas/config/obj-coff.c	4 Oct 2007 17:05:37 -0000	1.94
+++ gas/config/obj-coff.c	16 May 2009 16:38:10 -0000
@@ -169,6 +169,71 @@ obj_coff_bss (int ignore ATTRIBUTE_UNUSE
     s_lcomm (0);
 }
 
+#ifdef TE_PE
+/* Called from read.c:s_comm after we've parsed .comm symbol, size.
+   Parse a possible alignment value.  */
+
+static symbolS *
+obj_coff_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
+{
+  addressT align = 0;
+
+  if (*input_line_pointer == ',')
+    {
+      align = parse_align (0);
+      if (align == (addressT) -1)
+	return NULL;
+    }
+
+  S_SET_VALUE (symbolP, size);
+  S_SET_EXTERNAL (symbolP);
+  S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
+
+  symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
+
+  /* There is no S_SET_ALIGN (symbolP, align) in COFF/PE.
+     Instead we must add a note to the .drectve section.  */
+  if (align)
+    {
+      segT current_seg = now_seg;
+      subsegT current_subseg = now_subseg;
+      flagword oldflags;
+      asection *sec;
+      size_t pfxlen, numlen;
+      char *frag;
+      char numbuff[20];
+
+      sec = subseg_new (".drectve", 0);
+      oldflags = bfd_get_section_flags (stdoutput, sec);
+      if (oldflags == SEC_NO_FLAGS)
+	{
+	  if (!bfd_set_section_flags (stdoutput, sec,
+		TC_COFF_SECTION_DEFAULT_ATTRIBUTES))
+	    as_warn (_("error setting flags for \"%s\": %s"),
+		bfd_section_name (stdoutput, sec),
+		bfd_errmsg (bfd_get_error ()));
+	}
+
+      /* Emit a string.  Note no NUL-termination.  */
+      pfxlen = strlen (" -aligncomm:") + strlen (S_GET_NAME (symbolP)) + 1;
+      numlen = snprintf (numbuff, sizeof (numbuff), "%d", (int) align);
+      frag = frag_more (pfxlen + numlen);
+      (void) sprintf (frag, " -aligncomm:%s,", S_GET_NAME (symbolP));
+      memcpy (frag + pfxlen, numbuff, numlen);
+      /* Restore original subseg. */
+      subseg_set (current_seg, current_subseg);
+    }
+
+  return symbolP;
+}
+
+static void
+obj_coff_comm (int ignore ATTRIBUTE_UNUSED)
+{
+  s_comm_internal (ignore, obj_coff_common_parse);
+}
+#endif /* TE_PE */
+
 #define GET_FILENAME_STRING(X) \
   ((char *) (&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1])
 
@@ -1778,6 +1843,10 @@ const pseudo_typeS coff_pseudo_table[] =
   /* We accept the .bss directive for backward compatibility with
      earlier versions of gas.  */
   {"bss", obj_coff_bss, 0},
+#ifdef TE_PE
+  /* PE provides an enhanced version of .comm with alignment.  */
+  {"comm", obj_coff_comm, 0},
+#endif /* TE_PE */
   {"def", obj_coff_def, 0},
   {"dim", obj_coff_dim, 0},
   {"endef", obj_coff_endef, 0},
Index: gas/doc/as.texinfo
===================================================================
RCS file: /cvs/src/src/gas/doc/as.texinfo,v
retrieving revision 1.201
diff -p -u -r1.201 as.texinfo
--- gas/doc/as.texinfo	30 Apr 2009 15:47:12 -0000	1.201
+++ gas/doc/as.texinfo	16 May 2009 16:38:12 -0000
@@ -4308,16 +4308,23 @@ absolute expression.  If @code{@value{LD
 the same name, and they do not all have the same size, it will allocate space
 using the largest size.
 
-@ifset ELF
-When using ELF, the @code{.comm} directive takes an optional third argument.
-This is the desired alignment of the symbol, specified as a byte boundary (for
-example, an alignment of 16 means that the least significant 4 bits of the
-address should be zero).  The alignment must be an absolute expression, and it
-must be a power of two.  If @code{@value{LD}} allocates uninitialized memory
-for the common symbol, it will use the alignment when placing the symbol.  If
-no alignment is specified, @command{@value{AS}} will set the alignment to the
+@ifset COFF-ELF
+When using ELF or (as a GNU extension) PE, the @code{.comm} directive takes
+an optional third argument.  This is the desired alignment of the symbol, 
+specified for ELF as a byte boundary (for example, an alignment of 16 means
+that the least significant 4 bits of the address should be zero), and for PE
+as a power of two (for example, an alignment of 5 means aligned to a 32-byte
+boundary).  The alignment must be an absolute expression, and it must be a 
+power of two.  If @code{@value{LD}} allocates uninitialized memory for the
+common symbol, it will use the alignment when placing the symbol.  If no 
+alignment is specified, @command{@value{AS}} will set the alignment to the
 largest power of two less than or equal to the size of the symbol, up to a
-maximum of 16.
+maximum of 16 on ELF, or the default section alignment of 4 on PE@footnote{This
+is not the same as the executable image file alignment controlled by @code{@value{LD}}'s
+@samp{--section-alignment} option; image file sections in PE are aligned to
+multiples of 4096, which is far too large an alignment for ordinary variables.
+It is rather the default alignment for (non-debug) sections within object
+(@samp{*.o}) files, which are less strictly aligned.}.
 @end ifset
 
 @ifset HPPA
Index: gas/testsuite/gas/pe/aligncomm-a.d
===================================================================
RCS file: gas/testsuite/gas/pe/aligncomm-a.d
diff -N gas/testsuite/gas/pe/aligncomm-a.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/pe/aligncomm-a.d	16 May 2009 16:38:13 -0000
@@ -0,0 +1,12 @@
+#objdump: -s -j .drectve
+#name: aligned common A
+
+# Test the alignment pseudo-op.
+
+.*: .*
+
+Contents of section .drectve:
+ 0000 202d616c 69676e63 6f6d6d3a 5f682c35   -aligncomm:_h,5
+ 0010 202d616c 69676e63 6f6d6d3a 5f692c34   -aligncomm:_i,4
+ 0020 202d616c 69676e63 6f6d6d3a 5f6a2c33   -aligncomm:_j,3
+ 0030 202d616c 69676e63 6f6d6d3a 5f6b2c32   -aligncomm:_k,2
Index: gas/testsuite/gas/pe/aligncomm-a.s
===================================================================
RCS file: gas/testsuite/gas/pe/aligncomm-a.s
diff -N gas/testsuite/gas/pe/aligncomm-a.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/pe/aligncomm-a.s	16 May 2009 16:38:13 -0000
@@ -0,0 +1,11 @@
+	.file	"a.c"
+	.comm	_h, 16	 # 8
+	.comm	_i, 16	 # 4
+	.comm	_j, 16	 # 2
+	.comm	_k, 16	 # 1
+	.section .drectve
+	.ascii " -aligncomm:_h,5"
+	.ascii " -aligncomm:_i,4"
+	.ascii " -aligncomm:_j,3"
+	.ascii " -aligncomm:_k,2"
+
Index: gas/testsuite/gas/pe/aligncomm-b.d
===================================================================
RCS file: gas/testsuite/gas/pe/aligncomm-b.d
diff -N gas/testsuite/gas/pe/aligncomm-b.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/pe/aligncomm-b.d	16 May 2009 16:38:13 -0000
@@ -0,0 +1,16 @@
+#objdump: -s -j .drectve
+#name: aligned common B
+
+# Test the alignment pseudo-op.
+
+.*: .*
+
+Contents of section .drectve:
+ 0000 202d616c 69676e63 6f6d6d3a 5f682c38   -aligncomm:_h,8
+ 0010 202d616c 69676e63 6f6d6d3a 5f692c34   -aligncomm:_i,4
+ 0020 202d616c 69676e63 6f6d6d3a 5f6a2c32   -aligncomm:_j,2
+ 0030 202d616c 69676e63 6f6d6d3a 5f6b2c31   -aligncomm:_k,1
+ 0040 202d616c 69676e63 6f6d6d3a 5f682c35   -aligncomm:_h,5
+ 0050 202d616c 69676e63 6f6d6d3a 5f692c34   -aligncomm:_i,4
+ 0060 202d616c 69676e63 6f6d6d3a 5f6a2c33   -aligncomm:_j,3
+ 0070 202d616c 69676e63 6f6d6d3a 5f6b2c32   -aligncomm:_k,2
Index: gas/testsuite/gas/pe/aligncomm-b.s
===================================================================
RCS file: gas/testsuite/gas/pe/aligncomm-b.s
diff -N gas/testsuite/gas/pe/aligncomm-b.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/pe/aligncomm-b.s	16 May 2009 16:38:13 -0000
@@ -0,0 +1,11 @@
+	.file	"a.c"
+	.comm	_h, 16, 8
+	.comm	_i, 16, 4
+	.comm	_j, 16, 2
+	.comm	_k, 16, 1
+	.section .drectve
+	.ascii " -aligncomm:_h,5"
+	.ascii " -aligncomm:_i,4"
+	.ascii " -aligncomm:_j,3"
+	.ascii " -aligncomm:_k,2"
+
Index: gas/testsuite/gas/pe/aligncomm-c.d
===================================================================
RCS file: gas/testsuite/gas/pe/aligncomm-c.d
diff -N gas/testsuite/gas/pe/aligncomm-c.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/pe/aligncomm-c.d	16 May 2009 16:38:13 -0000
@@ -0,0 +1,8 @@
+#objdump: -s -j .drectve
+#name: aligned common C
+
+# Test the alignment pseudo-op.
+
+.*: .*
+
+# No .drectve section emitted.
\ No newline at end of file
Index: gas/testsuite/gas/pe/aligncomm-c.s
===================================================================
RCS file: gas/testsuite/gas/pe/aligncomm-c.s
diff -N gas/testsuite/gas/pe/aligncomm-c.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/pe/aligncomm-c.s	16 May 2009 16:38:13 -0000
@@ -0,0 +1,5 @@
+	.file	"a.c"
+	.comm	_h, 16	 # 8
+	.comm	_i, 16	 # 4
+	.comm	_j, 16	 # 2
+	.comm	_k, 16	 # 1
Index: gas/testsuite/gas/pe/aligncomm-d.d
===================================================================
RCS file: gas/testsuite/gas/pe/aligncomm-d.d
diff -N gas/testsuite/gas/pe/aligncomm-d.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/pe/aligncomm-d.d	16 May 2009 16:38:13 -0000
@@ -0,0 +1,12 @@
+#objdump: -s -j .drectve
+#name: aligned common D
+
+# Test the alignment pseudo-op.
+
+.*: .*
+
+Contents of section .drectve:
+ 0000 202d616c 69676e63 6f6d6d3a 5f682c38   -aligncomm:_h,8
+ 0010 202d616c 69676e63 6f6d6d3a 5f692c34   -aligncomm:_i,4
+ 0020 202d616c 69676e63 6f6d6d3a 5f6a2c32   -aligncomm:_j,2
+ 0030 202d616c 69676e63 6f6d6d3a 5f6b2c31   -aligncomm:_k,1
Index: gas/testsuite/gas/pe/aligncomm-d.s
===================================================================
RCS file: gas/testsuite/gas/pe/aligncomm-d.s
diff -N gas/testsuite/gas/pe/aligncomm-d.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/pe/aligncomm-d.s	16 May 2009 16:38:13 -0000
@@ -0,0 +1,5 @@
+	.file	"a.c"
+	.comm	_h, 16, 8
+	.comm	_i, 16, 4
+	.comm	_j, 16, 2
+	.comm	_k, 16, 1
Index: gas/testsuite/gas/pe/pe.exp
===================================================================
RCS file: gas/testsuite/gas/pe/pe.exp
diff -N gas/testsuite/gas/pe/pe.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/pe/pe.exp	16 May 2009 16:38:13 -0000
@@ -0,0 +1,34 @@
+# Expect control script for GAS testsuite PE object-format-specific tests.
+
+# Copyright (C) 2009
+# Free Software Foundation, Inc.
+
+# 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 3 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.
+# 
+# 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# binutils@gnu.org
+
+load_lib gas-dg.exp
+load_lib gas-defs.exp
+
+# These tests can only be run on PE/COFF platforms.
+if {![is_pecoff_format]} {
+    return
+}
+
+run_dump_test "aligncomm-a"
+run_dump_test "aligncomm-b"
+run_dump_test "aligncomm-c"
+run_dump_test "aligncomm-d"
Index: gas/testsuite/lib/gas-defs.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/lib/gas-defs.exp,v
retrieving revision 1.32
diff -p -u -r1.32 gas-defs.exp
--- gas/testsuite/lib/gas-defs.exp	27 Jan 2009 13:48:14 -0000	1.32
+++ gas/testsuite/lib/gas-defs.exp	16 May 2009 16:38:13 -0000
@@ -310,6 +310,18 @@ proc is_elf_format {} {
     return 1
 }
 
+# True if the object format is known to be PE COFF.
+#
+proc is_pecoff_format {} {
+    if { ![istarget *-*-mingw*] \
+	 && ![istarget *-*-cygwin*] \
+	 && ![istarget *-*-pe*] } {
+	return 0
+    }
+
+    return 1
+}
+
 # run_dump_tests TESTCASES EXTRA_OPTIONS
 # Wrapper for run_dump_test, which is suitable for invoking as
 #   run_dump_tests [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
Index: ld/NEWS
===================================================================
RCS file: /cvs/src/src/ld/NEWS,v
retrieving revision 1.104
diff -p -u -r1.104 NEWS
--- ld/NEWS	4 May 2009 12:09:30 -0000	1.104
+++ ld/NEWS	16 May 2009 16:38:13 -0000
@@ -1,5 +1,9 @@
 -*- text -*-
 
+* PE targets now support a GNU extension to allow the alignment of common
+  common symbols to be specified.  This support uses custom options in
+  the .drectve section, which will be disregarded by the native tools.
+
 * PE targets now add primitive support for ELF version scripts; symbols
   are not versioned, but the local and global symbol visibility directives
   are respected when filtering symbols in auto-export mode.
Index: ld/deffile.h
===================================================================
RCS file: /cvs/src/src/ld/deffile.h,v
retrieving revision 1.11
diff -p -u -r1.11 deffile.h
--- ld/deffile.h	6 Jul 2007 14:09:41 -0000	1.11
+++ ld/deffile.h	16 May 2009 16:38:13 -0000
@@ -53,6 +53,12 @@ typedef struct def_file_import {
   int data;			/* = 1 if data */
 } def_file_import;
 
+typedef struct def_file_aligncomm {
+  struct def_file_aligncomm *next;	/* Chain pointer.  */
+  char *symbol_name;		/* Name of common symbol.  */
+  unsigned int alignment;	/* log-2 alignment.        */
+} def_file_aligncomm;
+
 typedef struct def_file {
   /* From the NAME or LIBRARY command.  */
   char *name;
@@ -83,6 +89,10 @@ typedef struct def_file {
 
   /* From the VERSION command, -1 if not specified.  */
   int version_major, version_minor;
+
+  /* Only expected from .drectve sections, not .DEF files.  */
+  def_file_aligncomm *aligncomms;
+
 } def_file;
 
 extern def_file *def_file_empty (void);
Index: ld/deffilep.y
===================================================================
RCS file: /cvs/src/src/ld/deffilep.y,v
retrieving revision 1.25
diff -p -u -r1.25 deffilep.y
--- ld/deffilep.y	29 Apr 2009 01:17:54 -0000	1.25
+++ ld/deffilep.y	16 May 2009 16:38:13 -0000
@@ -89,6 +89,7 @@ static void def_section_alt (const char 
 static void def_stacksize (int, int);
 static void def_version (int, int);
 static void def_directive (char *);
+static void def_aligncomm (char *str, int align);
 static int def_parse (void);
 static int def_error (const char *);
 static int def_lex (void);
@@ -106,7 +107,7 @@ static const char *lex_parse_string_end 
 
 %token NAME LIBRARY DESCRIPTION STACKSIZE_K HEAPSIZE CODE DATAU DATAL
 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL
-%token PRIVATEU PRIVATEL
+%token PRIVATEU PRIVATEL ALIGNCOMM
 %token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE
 %token <id> ID
 %token <number> NUMBER
@@ -134,6 +135,7 @@ command: 
 	|	VERSIONK NUMBER { def_version ($2, 0);}
 	|	VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
 	|	DIRECTIVE ID { def_directive ($2);}
+	|	ALIGNCOMM ID ',' NUMBER { def_aligncomm ($2, $4);}
 	;
 
 
@@ -379,6 +381,14 @@ def_file_free (def_file *def)
       free (m);
     }
 
+  while (def->aligncomms)
+    {
+      def_file_aligncomm *c = def->aligncomms;
+      def->aligncomms = def->aligncomms->next;
+      free (c->symbol_name);
+      free (c);
+    }
+
   free (def);
 }
 
@@ -573,6 +583,7 @@ diropts[] =
   { "-stack", STACKSIZE_K },
   { "-attr", SECTIONS },
   { "-export", EXPORTS },
+  { "-aligncomm", ALIGNCOMM },
   { 0, 0 }
 };
 
@@ -831,6 +842,18 @@ def_directive (char *str)
   d->len = strlen (str);
 }
 
+static void
+def_aligncomm (char *str, int align)
+{
+  def_file_aligncomm *c = xmalloc (sizeof (def_file_aligncomm));
+
+  c->symbol_name = xstrdup (str);
+  c->alignment = (unsigned int) align;
+
+  c->next = def->aligncomms;
+  def->aligncomms = c;
+}
+
 static int
 def_error (const char *err)
 {
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.243
diff -p -u -r1.243 ld.texinfo
--- ld/ld.texinfo	4 May 2009 12:09:30 -0000	1.243
+++ ld/ld.texinfo	16 May 2009 16:38:16 -0000
@@ -6994,6 +6994,17 @@ implemented.
 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.
+
+@cindex aligned common symbols
+@item aligned common symbols
+As a GNU extension to the PE file format, it is possible to specify the
+desired alignment for a common symbol.  This information is conveyed from
+the assembler or compiler to the linker by means of GNU-specific commands
+carried in the object file's @samp{.drectve} section, which are recognized
+by @command{ld} and respected when laying out the common symbols.  Native
+tools will be able to process object files employing this GNU extension,
+but will fail to respect the alignment instructions, and may issue noisy
+warnings about unknown linker directives.
 @end table
 
 @ifclear GENERIC
Index: ld/pe-dll.c
===================================================================
RCS file: /cvs/src/src/ld/pe-dll.c,v
retrieving revision 1.118
diff -p -u -r1.118 pe-dll.c
--- ld/pe-dll.c	4 May 2009 12:09:30 -0000	1.118
+++ ld/pe-dll.c	16 May 2009 16:38:16 -0000
@@ -615,7 +615,7 @@ auto_export (bfd *abfd, def_file *d, con
 }
 
 static void
-process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
+process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
 {
   int i, j;
   struct bfd_link_hash_entry *blhe;
@@ -642,6 +642,28 @@ process_def_file (bfd *abfd ATTRIBUTE_UN
 	}
     }
 
+  /* Process aligned common symbol information from the
+     .drectve sections now; common symbol allocation is
+     done before final link, so it will be too late to
+     process them in process_embedded_commands() called
+     from _bfd_coff_link_input_bfd().  */
+  if (pe_def_file->aligncomms)
+    {
+      def_file_aligncomm *ac = pe_def_file->aligncomms;
+      while (ac)
+	{
+	  struct coff_link_hash_entry *sym_hash;
+	  sym_hash = coff_link_hash_lookup (coff_hash_table (info),
+		ac->symbol_name, FALSE, FALSE, FALSE);
+	  if (sym_hash && sym_hash->root.type == bfd_link_hash_common
+	    && sym_hash->root.u.c.p->alignment_power < (unsigned) ac->alignment)
+	    {
+	      sym_hash->root.u.c.p->alignment_power = (unsigned) ac->alignment;
+	    }
+	  ac = ac->next;
+	}
+    }
+
   /* If we are not building a DLL, when there are no exports
      we do not build an export table at all.  */
   if (!pe_dll_export_everything && pe_def_file->num_exports == 0
@@ -1053,7 +1075,7 @@ generate_edata (bfd *abfd, struct bfd_li
 }
 
 /* Fill the exported symbol offsets. The preliminary work has already
-   been done in process_def_file().  */
+   been done in process_def_file_and_drectve().  */
 
 static void
 fill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
@@ -3062,7 +3084,7 @@ pe_dll_build_sections (bfd *abfd, struct
 {
   pe_dll_id_target (bfd_get_target (abfd));
   pe_output_file_set_long_section_names (abfd);
-  process_def_file (abfd, info);
+  process_def_file_and_drectve (abfd, info);
 
   if (pe_def_file->num_exports == 0 && !info->shared)
     return;
Index: ld/testsuite/ld-pe/aligncomm-1.c
===================================================================
RCS file: ld/testsuite/ld-pe/aligncomm-1.c
diff -N ld/testsuite/ld-pe/aligncomm-1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-pe/aligncomm-1.c	16 May 2009 16:38:17 -0000
@@ -0,0 +1,19 @@
+
+typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
+
+long s1 = 0;
+__m128 r;
+__m128 * volatile raddr = &r;
+
+int main (int argc, const char **argv)
+{
+  return 15 & (int)raddr;
+}
+
+void __main (void)
+{
+  asm (".section .drectve\n"
+	"  .ascii \" -aligncomm:_r,4\"\n"
+	"  .ascii \" -aligncomm:r,4\"\n"
+	"  .text");
+}
Index: ld/testsuite/ld-pe/aligncomm-2.c
===================================================================
RCS file: ld/testsuite/ld-pe/aligncomm-2.c
diff -N ld/testsuite/ld-pe/aligncomm-2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-pe/aligncomm-2.c	16 May 2009 16:38:17 -0000
@@ -0,0 +1,20 @@
+
+typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
+
+long s1 = 0;
+long s2 = 0;
+__m128 r;
+__m128 * volatile raddr = &r;
+
+int main (int argc, const char **argv)
+{
+  return 15 & (int)raddr;
+}
+
+void __main (void)
+{
+  asm (".section .drectve\n"
+	"  .ascii \" -aligncomm:_r,4\"\n"
+	"  .ascii \" -aligncomm:r,4\"\n"
+	"  .text");
+}
Index: ld/testsuite/ld-pe/aligncomm-3.c
===================================================================
RCS file: ld/testsuite/ld-pe/aligncomm-3.c
diff -N ld/testsuite/ld-pe/aligncomm-3.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-pe/aligncomm-3.c	16 May 2009 16:38:17 -0000
@@ -0,0 +1,21 @@
+
+typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
+
+long s1 = 0;
+long s2 = 0;
+long s3 = 0;
+__m128 r;
+__m128 * volatile raddr = &r;
+
+int main (int argc, const char **argv)
+{
+  return 15 & (int)raddr;
+}
+
+void __main (void)
+{
+  asm (".section .drectve\n"
+	"  .ascii \" -aligncomm:_r,4\"\n"
+	"  .ascii \" -aligncomm:r,4\"\n"
+	"  .text");
+}
Index: ld/testsuite/ld-pe/aligncomm-4.c
===================================================================
RCS file: ld/testsuite/ld-pe/aligncomm-4.c
diff -N ld/testsuite/ld-pe/aligncomm-4.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-pe/aligncomm-4.c	16 May 2009 16:38:17 -0000
@@ -0,0 +1,22 @@
+
+typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
+
+long s1 = 0;
+long s2 = 0;
+long s3 = 0;
+long s4 = 0;
+__m128 r;
+__m128 * volatile raddr = &r;
+
+int main (int argc, const char **argv)
+{
+  return 15 & (int)raddr;
+}
+
+void __main (void)
+{
+  asm (".section .drectve\n"
+	"  .ascii \" -aligncomm:_r,4\"\n"
+	"  .ascii \" -aligncomm:r,4\"\n"
+	"  .text");
+}
Index: ld/testsuite/ld-pe/aligncomm.d
===================================================================
RCS file: ld/testsuite/ld-pe/aligncomm.d
diff -N ld/testsuite/ld-pe/aligncomm.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-pe/aligncomm.d	16 May 2009 16:38:17 -0000
@@ -0,0 +1,3 @@
+#...
+[0-9a-fA-F]{7}0 . r
+#...
Index: ld/testsuite/ld-pe/pe.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-pe/pe.exp,v
retrieving revision 1.11
diff -p -u -r1.11 pe.exp
--- ld/testsuite/ld-pe/pe.exp	15 May 2009 14:22:36 -0000	1.11
+++ ld/testsuite/ld-pe/pe.exp	16 May 2009 16:38:17 -0000
@@ -63,3 +63,16 @@ run_dump_test "longsecn-4"
 run_dump_test "longsecn-5"
 
 run_dump_test "orphan"
+
+set align_tests {
+  {"aligned common 1" "" "" {aligncomm-1.c}
+   {{nm -C aligncomm.d}} "aligncomm-1.x"}
+  {"aligned common 2" "" "" {aligncomm-2.c}
+   {{nm -C aligncomm.d}} "aligncomm-2.x"}
+  {"aligned common 3" "" "" {aligncomm-3.c}
+   {{nm -C aligncomm.d}} "aligncomm-3.x"}
+  {"aligned common 4" "" "" {aligncomm-4.c}
+   {{nm -C aligncomm.d}} "aligncomm-4.x"}
+}
+
+run_ld_link_tests $align_tests

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