[project @ 2002-02-04 03:40:31 by chak]
[ghc-hetmet.git] / ghc / rts / Linker.c
index 31a21db..3ed1843 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
 /* -----------------------------------------------------------------------------
- * $Id: Linker.c,v 1.78 2002/01/23 11:29:12 sewardj Exp $
+ * $Id: Linker.c,v 1.81 2002/02/01 02:05:52 sof Exp $
  *
  * (c) The GHC Team, 2000, 2001
  *
  *
  * (c) The GHC Team, 2000, 2001
  *
@@ -870,6 +870,33 @@ static void addSection ( ObjectCode* oc, SectionKind kind,
       and Common Object File Format Specification
       revision 5.1 January 1998
    which SimonM says comes from the MS Developer Network CDs.
       and Common Object File Format Specification
       revision 5.1 January 1998
    which SimonM says comes from the MS Developer Network CDs.
+   
+   It can be found there (on older CDs), but can also be found 
+   online at:
+
+      http://www.microsoft.com/hwdev/hardware/PECOFF.asp
+
+   (this is Rev 6.0 from February 1999).
+
+   Things move, so if that fails, try searching for it via
+
+      http://www.google.com/search?q=PE+COFF+specification     
+
+   The ultimate reference for the PE format is the Winnt.h 
+   header file that comes with the Platform SDKs; as always,
+   implementations will drift wrt their documentation.
+   
+   A good background article on the PE format is Matt Pietrek's
+   March 1994 article in Microsoft System Journal (MSJ)
+   (Vol.9, No. 3): "Peering Inside the PE: A Tour of the
+   Win32 Portable Executable File Format." The info in there
+   has recently been updated in a two part article in 
+   MSDN magazine, issues Feb and March 2002,
+   "Inside Windows: An In-Depth Look into the Win32 Portable
+   Executable File Format"
+
+   John Levine's book "Linkers and Loaders" contains useful
+   info on PE too.
 */
       
 
 */
       
 
@@ -961,6 +988,7 @@ typedef
 /* From PE spec doc, section 4.1 */
 #define MYIMAGE_SCN_CNT_CODE             0x00000020
 #define MYIMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
 /* From PE spec doc, section 4.1 */
 #define MYIMAGE_SCN_CNT_CODE             0x00000020
 #define MYIMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define MYIMAGE_SCN_LNK_NRELOC_OVFL      0x01000000
 
 /* From PE spec doc, section 5.2.1 */
 #define MYIMAGE_REL_I386_DIR32           0x0006
 
 /* From PE spec doc, section 5.2.1 */
 #define MYIMAGE_REL_I386_DIR32           0x0006
@@ -1094,7 +1122,8 @@ zapTrailingAtSign ( UChar* sym )
 static int
 ocVerifyImage_PEi386 ( ObjectCode* oc )
 {
 static int
 ocVerifyImage_PEi386 ( ObjectCode* oc )
 {
-   int i, j;
+   int i;
+   UInt32 j, noRelocs;
    COFF_header*  hdr;
    COFF_section* sectab;
    COFF_symbol*  symtab;
    COFF_header*  hdr;
    COFF_section* sectab;
    COFF_symbol*  symtab;
@@ -1137,13 +1166,15 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
       there are more than 64k relocations, despite claims to the
       contrary.  Hence this test. */
    /* fprintf(stderr, "strtab size %d\n", * (UInt32*)strtab); */
       there are more than 64k relocations, despite claims to the
       contrary.  Hence this test. */
    /* fprintf(stderr, "strtab size %d\n", * (UInt32*)strtab); */
-   if (* (UInt32*)strtab > 600000) {
+#if 0
+   if ( (*(UInt32*)strtab) > 600000 ) {
       /* Note that 600k has no special significance other than being
          big enough to handle the almost-2MB-sized lumps that
          constitute HSwin32*.o. */
       belch("PEi386 object has suspiciously large string table; > 64k relocs?");
       return 0;
    }
       /* Note that 600k has no special significance other than being
          big enough to handle the almost-2MB-sized lumps that
          constitute HSwin32*.o. */
       belch("PEi386 object has suspiciously large string table; > 64k relocs?");
       return 0;
    }
+#endif
 
    /* No further verification after this point; only debug printing. */
    i = 0;
 
    /* No further verification after this point; only debug printing. */
    i = 0;
@@ -1207,8 +1238,23 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
       reltab = (COFF_reloc*) (
                   ((UChar*)(oc->image)) + sectab_i->PointerToRelocations
                );
       reltab = (COFF_reloc*) (
                   ((UChar*)(oc->image)) + sectab_i->PointerToRelocations
                );
+              
+      if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) {
+       /* If the relocation field (a short) has overflowed, the
+        * real count can be found in the first reloc entry.
+        * 
+        * See Section 4.1 (last para) of the PE spec (rev6.0).
+        */
+        COFF_reloc* rel = (COFF_reloc*)
+                           myindex ( sizeof_COFF_reloc, reltab, 0 );
+       noRelocs = rel->VirtualAddress;
+       j = 1;
+      } else {
+       noRelocs = sectab_i->NumberOfRelocations;
+        j = 0;
+      }
 
 
-      for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
+      for (; j < noRelocs; j++) {
          COFF_symbol* sym;
          COFF_reloc* rel = (COFF_reloc*)
                            myindex ( sizeof_COFF_reloc, reltab, j );
          COFF_symbol* sym;
          COFF_reloc* rel = (COFF_reloc*)
                            myindex ( sizeof_COFF_reloc, reltab, j );
@@ -1218,6 +1264,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
                    rel->VirtualAddress );
          sym = (COFF_symbol*)
                myindex ( sizeof_COFF_symbol, symtab, rel->SymbolTableIndex );
                    rel->VirtualAddress );
          sym = (COFF_symbol*)
                myindex ( sizeof_COFF_symbol, symtab, rel->SymbolTableIndex );
+        /* Hmm..mysterious looking offset - what's it for? SOF */
          printName ( sym->Name, strtab -10 );
          fprintf ( stderr, "'\n" );
       }
          printName ( sym->Name, strtab -10 );
          fprintf ( stderr, "'\n" );
       }
@@ -1414,9 +1461,9 @@ ocGetNames_PEi386 ( ObjectCode* oc )
          /* fprintf(stderr, "BSS      section at 0x%x\n", addr); */
       }
 
          /* fprintf(stderr, "BSS      section at 0x%x\n", addr); */
       }
 
-      if (addr != NULL) {
+      if (addr != NULL ) {
          sname = cstring_from_COFF_symbol_name ( symtab_i->Name, strtab );
          sname = cstring_from_COFF_symbol_name ( symtab_i->Name, strtab );
-         /* fprintf(stderr,"addSymbol %p `%s'\n", addr,sname); */
+         /* fprintf(stderr,"addSymbol %p `%s \n", addr,sname);  */
          IF_DEBUG(linker, belch("addSymbol %p `%s'\n", addr,sname);)
          ASSERT(i >= 0 && i < oc->n_symbols);
          /* cstring_from_COFF_symbol_name always succeeds. */
          IF_DEBUG(linker, belch("addSymbol %p `%s'\n", addr,sname);)
          ASSERT(i >= 0 && i < oc->n_symbols);
          /* cstring_from_COFF_symbol_name always succeeds. */
@@ -1466,7 +1513,8 @@ ocResolve_PEi386 ( ObjectCode* oc )
    UInt32        S;
    UInt32*       pP;
 
    UInt32        S;
    UInt32*       pP;
 
-   int i, j;
+   int i;
+   UInt32 j, noRelocs;
 
    /* ToDo: should be variable-sized?  But is at least safe in the
       sense of buffer-overrun-proof. */
 
    /* ToDo: should be variable-sized?  But is at least safe in the
       sense of buffer-overrun-proof. */
@@ -1501,7 +1549,24 @@ ocResolve_PEi386 ( ObjectCode* oc )
           || 0 == strcmp(".stabstr", sectab_i->Name))
          continue;
 
           || 0 == strcmp(".stabstr", sectab_i->Name))
          continue;
 
-      for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
+      if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) {
+       /* If the relocation field (a short) has overflowed, the
+        * real count can be found in the first reloc entry.
+         *
+        * See Section 4.1 (last para) of the PE spec (rev6.0).
+        */
+        COFF_reloc* rel = (COFF_reloc*)
+                           myindex ( sizeof_COFF_reloc, reltab, 0 );
+       noRelocs = rel->VirtualAddress;
+       fprintf(stderr, "Overflown relocs: %u\n", noRelocs);
+       j = 1;
+      } else {
+       noRelocs = sectab_i->NumberOfRelocations;
+        j = 0;
+      }
+
+
+      for (; j < noRelocs; j++) {
          COFF_symbol* sym;
          COFF_reloc* reltab_j 
             = (COFF_reloc*)
          COFF_symbol* sym;
          COFF_reloc* reltab_j 
             = (COFF_reloc*)