Blob Blame History Raw
--- nasm-2.14.02/output/outcoff.c.orig	2018-12-26 13:44:06.000000000 +0000
+++ nasm-2.14.02/output/outcoff.c	2019-01-20 13:18:06.240000000 +0000
@@ -701,6 +701,7 @@
     sect->len += len;
 }
 
+#ifndef COFF_MIDIPIX
 typedef struct tagString {
     struct tagString *next;
     int len;
@@ -765,6 +766,98 @@
 
     *rvp = NULL;
 }
+#else
+typedef struct tagGlobalSymbol {
+    struct tagGlobalSymbol *next;
+    struct coff_Symbol *sym;
+} GLOBALSYMBOL;
+typedef struct tagGlobalSymbolList {
+    GLOBALSYMBOL *head, *tail;
+} GLOBALSYMBOLLIST;
+
+#define GOT_SECTION_FLAGS                               \
+    (IMAGE_SCN_CNT_INITIALIZED_DATA             |       \
+     IMAGE_SCN_ALIGN_4BYTES                     |       \
+     IMAGE_SCN_LNK_COMDAT                       |       \
+     IMAGE_SCN_MEM_READ)
+#define GOT_SECTION_PREFIX           ".got$"
+#define GOT_SECTION_PREFIX_LEN       (sizeof(GOT_SECTION_PREFIX) - 1)
+#define GOT_SYMBOL_PREFIX            "__imp_"
+#define GOT_SYMBOL_PREFIX_LEN       (sizeof(GOT_SYMBOL_PREFIX) - 1)
+
+static void BuildGlobalOffsetTable(void)
+{
+    uint64_t global_sym_addr;
+    GLOBALSYMBOL *global_sym, *global_sym_next;
+    char *global_sym_name;
+    GLOBALSYMBOLLIST global_symbols = {NULL, NULL};
+    char *got_sec_name, *got_sym_name;
+    size_t got_sec_name_len, got_sym_name_len;
+    struct coff_Symbol *sym;
+    unsigned long sym_num;
+
+    saa_rewind(coff_syms);
+    for (sym_num = 0; sym_num < coff_nsyms; sym_num++) {
+        sym = saa_rstruct(coff_syms);
+        if (sym->is_global && sym->section > 0) {
+            global_sym = nasm_malloc(sizeof(*global_sym));
+            global_sym->next = NULL;
+            global_sym->sym = sym;
+            if (!global_symbols.head)
+                global_symbols.head = global_sym;
+            if (global_symbols.tail)
+                global_symbols.tail->next = global_sym;
+            global_symbols.tail = global_sym;
+        }
+    }
+
+    for (global_sym = global_symbols.head, global_sym_next = NULL; global_sym; global_sym = global_sym_next) {
+        global_sym_name = nasm_zalloc(global_sym->sym->namlen + 1);
+        if (global_sym->sym->namlen > 8)
+            saa_fread(coff_strs, global_sym->sym->strpos - 4, global_sym_name, global_sym->sym->namlen);
+        else
+            strcpy(global_sym_name, global_sym->sym->name);
+
+        got_sec_name_len = GOT_SECTION_PREFIX_LEN + global_sym->sym->namlen;
+        got_sym_name_len = GOT_SYMBOL_PREFIX_LEN + global_sym->sym->namlen;
+        got_sec_name = nasm_zalloc(got_sec_name_len + 1);
+        got_sym_name = nasm_zalloc(got_sym_name_len + 1);
+        snprintf(got_sec_name, got_sec_name_len + 1, "%s%s", GOT_SECTION_PREFIX, global_sym_name);
+        snprintf(got_sym_name, got_sym_name_len + 1, "%s%s", GOT_SYMBOL_PREFIX, global_sym_name);
+
+        sym_num = coff_nsyms - 1;
+        sym = saa_wstruct(coff_syms);
+        sym->is_global = 1;
+        sym->namlen = got_sym_name_len;
+        sym->section = coff_make_section(got_sec_name, GOT_SECTION_FLAGS) + 1;
+        sym->type = 0; sym->value = 0;
+        coff_nsyms++;
+
+        if (sym->namlen > 8) {
+            sym->strpos = strslen + 4;
+            memset(sym->name, '\0', sizeof(sym->name));
+            saa_wbytes(coff_strs, got_sym_name, sym->namlen + 1);
+            strslen += sym->namlen + 1;
+        } else {
+            sym->strpos = -1;
+            strncpy(sym->name, got_sym_name, sizeof(sym->name));
+        }
+
+        if (win64) {
+            coff_add_reloc(coff_sects[sym->section - 1], coff_sects[global_sym->sym->section - 1]->index, IMAGE_REL_AMD64_ADDR64);
+            global_sym_addr = (uint64_t)global_sym->sym->value;
+            coff_sect_write(coff_sects[sym->section - 1], (const uint8_t *)&global_sym_addr, sizeof(global_sym_addr));
+        } else {
+            coff_add_reloc(coff_sects[sym->section - 1], coff_sects[global_sym->sym->section - 1]->index, IMAGE_REL_I386_DIR32);
+            coff_sect_write(coff_sects[sym->section - 1], (const uint8_t *)&global_sym->sym->value, sizeof(global_sym->sym->value));
+        }
+
+        global_sym_next = global_sym->next;
+        nasm_free(global_sym); nasm_free(global_sym_name);
+        nasm_free(got_sec_name); nasm_free(got_sym_name);
+    }
+}
+#endif
 
 static enum directive_result
 coff_directives(enum directive directive, char *value, int pass)
@@ -793,7 +886,9 @@
             nasm_error(ERR_NONFATAL, "unrecognized export qualifier `%s'", q);
             return DIRR_ERROR;
         }
+#ifndef COFF_MIDIPIX
         AddExport(name);
+#endif
         return DIRR_OK;
     }
     case D_SAFESEH:
@@ -888,8 +983,12 @@
     int32_t pos, sympos, vsize;
     int i;
 
+#ifndef COFF_MIDIPIX
     /* fill in the .drectve section with -export's */
     BuildExportTable(&Exports);
+#else
+    BuildGlobalOffsetTable();
+#endif
 
     if (win32) {
         /* add default value for @feat.00, this allows to 'link /safeseh' */
@@ -1086,7 +1185,10 @@
     memset(filename, 0, 18);    /* useful zeroed buffer */
 
     for (i = 0; i < (uint32_t) coff_nsects; i++) {
-        coff_symbol(coff_sects[i]->name, 0L, 0L, i + 1, 0, 3, 1);
+        if (coff_sects[i]->namepos == -1)
+            coff_symbol(coff_sects[i]->name, 0L, 0L, i + 1, 0, 3, 1);
+        else
+            coff_symbol(NULL, coff_sects[i]->namepos, 0L, i + 1, 0, 3, 1);
         fwriteint32_t(coff_sects[i]->len,    ofile);
         fwriteint16_t(coff_sects[i]->nrelocs,ofile);
         nasm_write(filename, 12, ofile);