outcoff: set the "virtual size field" to zero (BR 1351586)
authorH. Peter Anvin <hpa@zytor.com>
Tue, 25 Sep 2007 00:02:07 +0000 (17:02 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 25 Sep 2007 00:02:41 +0000 (17:02 -0700)
Per SF bug report 1351586:

The COFF spec suggests that the "Virtual Size" field (which
immediately follows the name field inside a section header) be set to
0 for an object file.

By contrast (as documented in comment #4 at the beginning of its
outcoff.c file) NASM sets it to a particular non-0 value.

MASM 6.15 matches NASM for both 16- and 32-bit object files,
i.e. emits non-0 values.

MASM 8 (from VS 2005 Beta) matches the COFF spec for 64-bit object
files, i.e. emits 0.

GAS matches the COFF spec for 32-bit object files (MinGW or Cygwin),
i.e. also emits 0.

Older versions of GNU ld seem to honor said "Virtual Size" field
whereas newer versions do not.  As a result those older versions
generate "bloated" image files.

Since the COFF spec and the real world seem to disagree for this case,
it might make sense to add a method for selecting between the two to
NASM.

Date: 2005-11-28 15:39
Sender: nasm64developer
Logged In: YES
user_id=804543

MASM 8 (from VS 2005 Beta) also matches the COFF spec for 16- and
32-bit object files, i.e. emits 0.

That said, NASM should always emit 0 too. Therefore I am turning this
from a support request into a bug.

output/outcoff.c

index 6669424..8eb8c06 100644 (file)
@@ -53,6 +53,9 @@
  * seem to fit at all. In fact, Win32 even includes non-linked
  * sections such as .drectve in this calculation.
  *
+ * Newer versions of MASM seem to have changed this to be zero, and
+ * that apparently matches the COFF spec, so go with that.
+ *
  * (5) Standard COFF does something very strange to common
  * variables: the relocation point for a common variable is as far
  * _before_ the variable as its size stretches out _after_ it. So
@@ -763,10 +766,12 @@ static void coff_section_header(char *name, int32_t vsize,
 {
     char padname[8];
 
+    (void)vsize;
+
     memset(padname, 0, 8);
     strncpy(padname, name, 8);
     fwrite(padname, 8, 1, coffp);
-    fwriteint32_t(vsize, coffp);
+    fwriteint32_t(0, coffp);   /* Virtual size field - set to 0 or vsize */
     fwriteint32_t(0L, coffp);      /* RVA/offset - we ignore */
     fwriteint32_t(datalen, coffp);
     fwriteint32_t(datapos, coffp);