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]

[WIP] Supporting aligned commons in PE.


Dave Korn wrote:
> Danny Smith wrote:
>> Dave Korn wrote
>>
>>
>>> 2)  Add a new type of statement to the .drectve section, with a syntax such as
>>> "-aligncomm:<symbolname>,<alignment>".  This might cause noisy warnings from
>>> the vendors tools, but I think it's a cleaner interface than inventing our own
>>> non-approved aux symbol format, so up til now it's my preferred option.
>>
>> This is my preferred option too, since the vendors own spec
>> documentation says that the .drectve section is meant to handle
>> compiler specific features.

  Here's a first draft, sans docs and tests, but the core of it is I think
complete.  As well as extending the linker to take alignment directives, I
extended the assembler to allow the three-arg form of the .comm pseudo-op and
emit .drectve strings directly, but it'll also work to use the two-operand
form and manually add the directive using the .section and .ascii pseudo-ops.

  It's kind of funny having to go via the DEF-file handling stuff, but I think
it's the most sensible place for it given the existing architecture of BFD and
the PE emulation.  The symbol alignments have to be set early, when we open
the BFDs, not at final link time when adding input BFDs to the output, as the
common symbols have already been assigned by then.  Rather than add a whole
bunch of duplicated .drectve-section iterating and parsing, I thought it was
fair enough to piggy-back onto the existing processing.  This may mean you can
now specify common symbol alignment in .DEF files, should you be strange
enough to want to do so.  I don't see any need to try and prevent this.

  I'll get round to the tests and docs later today after I've caught some
sleep.  If anyone has any input on how I've approached this, I'd love to hear
it, otherwise I'll plough straight on.

  (Kai, this is why I haven't had a lot of time to look at your SEH patch yet
- I'll get to it next, promise!)

    cheers,
      DaveK
? 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	14 May 2009 05:35:36 -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/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	14 May 2009 05:35:38 -0000
@@ -169,6 +169,74 @@ 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;
+    }
+  else
+    {
+      /* Align to nearest power of 2 <= size, max 16.  */
+      while (((unsigned)1 << (align + 1)) <= size && align < 4)
+	align++;
+    }
+
+  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.  */
+  {
+    segT current_seg = now_seg;
+    subsegT current_subseg = now_subseg;
+    flagword oldflags;
+    asection *sec;
+    size_t count;
+    char *frag;
+
+    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. */
+    count = strlen (" -aligncomm:") + strlen (S_GET_NAME (symbolP)) 
+		+ 1 + snprintf (NULL, 0, "%d", (int) align) + 1;
+    frag = frag_more (count);
+    snprintf (frag, count, " -aligncomm:%s,%d", S_GET_NAME (symbolP), (int) align);
+
+    /* 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 +1846,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: 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	14 May 2009 05:35:39 -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	14 May 2009 05:35:39 -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/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	14 May 2009 05:35:40 -0000
@@ -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

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