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