]> granicus.if.org Git - yasm/commitdiff
* coff-objfmt.c: Support >=64K relocs on Win32/64 objects.
authorPeter Johnson <peter@tortall.net>
Thu, 11 May 2006 05:43:22 +0000 (05:43 -0000)
committerPeter Johnson <peter@tortall.net>
Thu, 11 May 2006 05:43:22 +0000 (05:43 -0000)
svn path=/trunk/yasm/; revision=1535

modules/objfmts/coff/coff-objfmt.c

index f9a3982d2a51d97e41cb334825c1371106c32d49..39b7f34cd4164f1c7e39c576c2ce02b29a63e7ab 100644 (file)
@@ -92,6 +92,7 @@ typedef struct coff_reloc {
 #define COFF_STYP_STD_MASK     0x000003FFUL
 #define COFF_STYP_ALIGN_MASK   0x00F00000UL
 #define COFF_STYP_ALIGN_SHIFT  20
+#define COFF_STYP_NRELOC_OVFL  0x01000000UL
 #define COFF_STYP_DISCARD      0x02000000UL
 #define COFF_STYP_NOCACHE      0x04000000UL
 #define COFF_STYP_NOPAGE       0x08000000UL
@@ -99,7 +100,7 @@ typedef struct coff_reloc {
 #define COFF_STYP_EXECUTE      0x20000000UL
 #define COFF_STYP_READ         0x40000000UL
 #define COFF_STYP_WRITE                0x80000000UL
-#define COFF_STYP_WIN32_MASK   0xFE000000UL
+#define COFF_STYP_WIN32_MASK   0xFF000000UL
 
 #define COFF_FLAG_NOBASE       (1UL<<0)    /* Use no-base (NB) relocs */
 
@@ -742,6 +743,7 @@ coff_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
     /*@dependent@*/ /*@null@*/ coff_section_data *csd;
     long pos;
     coff_reloc *reloc;
+    unsigned char *localbuf;
 
     /* Don't output absolute sections into the section table */
     if (yasm_section_is_absolute(sect))
@@ -812,10 +814,21 @@ coff_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
     }
     csd->relptr = (unsigned long)pos;
 
+    /* If >=64K relocs (for Win32/64), we set a flag in the section header
+     * (NRELOC_OVFL) and the first relocation contains the number of relocs.
+     */
+    if (csd->nreloc >= 64*1024 && info->objfmt_coff->win32) {
+       localbuf = info->buf;
+       YASM_WRITE_32_L(localbuf, csd->nreloc+1);   /* address of relocation */
+       YASM_WRITE_32_L(localbuf, 0);           /* relocated symbol */
+       YASM_WRITE_16_L(localbuf, 0);           /* type of relocation */
+       fwrite(info->buf, 10, 1, info->f);
+    }
+
     reloc = (coff_reloc *)yasm_section_relocs_first(sect);
     while (reloc) {
-       unsigned char *localbuf = info->buf;
        /*@null@*/ coff_symrec_data *csymd;
+       localbuf = info->buf;
 
        csymd = yasm_symrec_get_data(reloc->reloc.sym, &coff_symrec_data_cb);
        if (!csymd)
@@ -909,10 +922,15 @@ coff_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
     YASM_WRITE_32_L(localbuf, csd->relptr);    /* file ptr to relocs */
     YASM_WRITE_32_L(localbuf, 0);              /* file ptr to line nums */
     if (csd->nreloc >= 64*1024) {
-       yasm_warn_set(YASM_WARN_GENERAL,
-                     N_("too many relocations in section `%s'"),
-                     yasm_section_get_name(sect));
-       yasm_errwarn_propagate(info->errwarns, 0);
+       /* Win32/64 has special handling for this case. */
+       if (objfmt_coff->win32)
+           csd->flags |= COFF_STYP_NRELOC_OVFL;
+       else {
+           yasm_warn_set(YASM_WARN_GENERAL,
+                         N_("too many relocations in section `%s'"),
+                         yasm_section_get_name(sect));
+           yasm_errwarn_propagate(info->errwarns, 0);
+       }
        YASM_WRITE_16_L(localbuf, 0xFFFF);      /* max out */
     } else
        YASM_WRITE_16_L(localbuf, csd->nreloc); /* num of relocation entries */