--- 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);