int main(int argc, char **argv) { int ret = 0; if(process_args(argc, argv)) { if(load_mapfile(g_mapfile) && load_elf(g_infile)) { if(fixup_imports() && fixup_nidmap()) { FILE *fp; fp = fopen(g_outfile, "wb"); if(fp != NULL) { (void) fwrite(g_elfdata, 1, g_elfsize, fp); fclose(fp); } else { fprintf(stderr, "Error, couldn't open %s for writing\n", g_outfile); return 0; } } else { ret = 1; } free_data(); } else { ret = 1; } } else { print_help(); ret = 1; } return ret; }
/********************************************************************** * PE_CreateModule * * Create WINE_MODREF structure for loaded HMODULE32, link it into * process modref_list, and fixup all imports. * * Note: hModule must point to a correctly allocated PE image, * with base relocations applied; the 16-bit dummy module * associated to hModule must already exist. * * Note: This routine must always be called in the context of the * process that is to own the module to be created. */ WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename, DWORD flags, WIN_BOOL builtin ) { DWORD load_addr = (DWORD)hModule; IMAGE_NT_HEADERS *nt = PE_HEADER(hModule); IMAGE_DATA_DIRECTORY *dir; IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL; IMAGE_EXPORT_DIRECTORY *pe_export = NULL; IMAGE_RESOURCE_DIRECTORY *pe_resource = NULL; WINE_MODREF *wm; dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT; if (dir->Size) pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(dir->VirtualAddress); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT; if (dir->Size) pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(dir->VirtualAddress); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE; if (dir->Size) pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(dir->VirtualAddress); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXCEPTION; if (dir->Size) FIXME("Exception directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_SECURITY; if (dir->Size) FIXME("Security directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DEBUG; if (dir->Size) TRACE("Debug directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COPYRIGHT; if (dir->Size) FIXME("Copyright string ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_GLOBALPTR; if (dir->Size) FIXME("Global Pointer (MIPS) ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG; if (dir->Size) FIXME("Load Configuration directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT; if (dir->Size) TRACE("Bound Import directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IAT; if (dir->Size) TRACE("Import Address Table directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT; if (dir->Size) { TRACE("Delayed import, stub calls LoadLibrary\n" ); /* * Nothing to do here. */ #ifdef ImgDelayDescr /* * This code is useful to observe what the heck is going on. */ { ImgDelayDescr *pe_delay = NULL; pe_delay = (PImgDelayDescr)RVA(dir->VirtualAddress); TRACE_(delayhlp)("pe_delay->grAttrs = %08x\n", pe_delay->grAttrs); TRACE_(delayhlp)("pe_delay->szName = %s\n", pe_delay->szName); TRACE_(delayhlp)("pe_delay->phmod = %08x\n", pe_delay->phmod); TRACE_(delayhlp)("pe_delay->pIAT = %08x\n", pe_delay->pIAT); TRACE_(delayhlp)("pe_delay->pINT = %08x\n", pe_delay->pINT); TRACE_(delayhlp)("pe_delay->pBoundIAT = %08x\n", pe_delay->pBoundIAT); TRACE_(delayhlp)("pe_delay->pUnloadIAT = %08x\n", pe_delay->pUnloadIAT); TRACE_(delayhlp)("pe_delay->dwTimeStamp = %08x\n", pe_delay->dwTimeStamp); } #endif } dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR; if (dir->Size) FIXME("Unknown directory 14 ignored\n" ); dir = nt->OptionalHeader.DataDirectory+15; if (dir->Size) FIXME("Unknown directory 15 ignored\n" ); wm = (WINE_MODREF *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wm) ); wm->module = hModule; if ( builtin ) wm->flags |= WINE_MODREF_INTERNAL; if ( flags & DONT_RESOLVE_DLL_REFERENCES ) wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS; if ( flags & LOAD_LIBRARY_AS_DATAFILE ) wm->flags |= WINE_MODREF_LOAD_AS_DATAFILE; wm->type = MODULE32_PE; wm->binfmt.pe.pe_export = pe_export; wm->binfmt.pe.pe_import = pe_import; wm->binfmt.pe.pe_resource = pe_resource; wm->binfmt.pe.tlsindex = -1; wm->filename = malloc(strlen(filename)+1); strcpy(wm->filename, filename ); wm->modname = strrchr( wm->filename, '\\' ); if (!wm->modname) wm->modname = wm->filename; else wm->modname++; if ( pe_export ) dump_exports( hModule ); /* Fixup Imports */ if ( pe_import && !( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) && !( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS ) && fixup_imports( wm ) ) { /* remove entry from modref chain */ return NULL; } return wm; }
/* map a builtin dll in memory and fixup RVAs */ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr ) { #ifdef HAVE_MMAP IMAGE_DATA_DIRECTORY *dir; IMAGE_DOS_HEADER *dos; IMAGE_NT_HEADERS *nt; IMAGE_SECTION_HEADER *sec; BYTE *addr; DWORD code_start, data_start, data_end; const size_t page_size = getpagesize(); const size_t page_mask = page_size - 1; int delta, nb_sections = 2; /* code + data */ unsigned int i; size_t size = (sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + nb_sections * sizeof(IMAGE_SECTION_HEADER)); assert( size <= page_size ); /* module address must be aligned on 64K boundary */ addr = (BYTE *)((nt_descr->OptionalHeader.ImageBase + 0xffff) & ~0xffff); if (wine_anon_mmap( addr, page_size, PROT_READ|PROT_WRITE, MAP_FIXED ) != addr) return NULL; dos = (IMAGE_DOS_HEADER *)addr; nt = (IMAGE_NT_HEADERS *)(dos + 1); sec = (IMAGE_SECTION_HEADER *)(nt + 1); /* Build the DOS and NT headers */ dos->e_magic = IMAGE_DOS_SIGNATURE; dos->e_cblp = 0x90; dos->e_cp = 3; dos->e_cparhdr = (sizeof(*dos)+0xf)/0x10; dos->e_minalloc = 0; dos->e_maxalloc = 0xffff; dos->e_ss = 0x0000; dos->e_sp = 0x00b8; dos->e_lfarlc = sizeof(*dos); dos->e_lfanew = sizeof(*dos); *nt = *nt_descr; delta = (const BYTE *)nt_descr - addr; code_start = page_size; data_start = delta & ~page_mask; data_end = (nt->OptionalHeader.SizeOfImage + delta + page_mask) & ~page_mask; fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 ); nt->FileHeader.NumberOfSections = nb_sections; nt->OptionalHeader.BaseOfCode = code_start; #ifndef _WIN64 nt->OptionalHeader.BaseOfData = data_start; #endif nt->OptionalHeader.SizeOfCode = data_start - code_start; nt->OptionalHeader.SizeOfInitializedData = data_end - data_start; nt->OptionalHeader.SizeOfUninitializedData = 0; nt->OptionalHeader.SizeOfImage = data_end; nt->OptionalHeader.ImageBase = (ULONG_PTR)addr; /* Build the code section */ memcpy( sec->Name, ".text", sizeof(".text") ); sec->SizeOfRawData = data_start - code_start; sec->Misc.VirtualSize = sec->SizeOfRawData; sec->VirtualAddress = code_start; sec->PointerToRawData = code_start; sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ); sec++; /* Build the data section */ memcpy( sec->Name, ".data", sizeof(".data") ); sec->SizeOfRawData = data_end - data_start; sec->Misc.VirtualSize = sec->SizeOfRawData; sec->VirtualAddress = data_start; sec->PointerToRawData = data_start; sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ); sec++; for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++) fixup_rva_dwords( &nt->OptionalHeader.DataDirectory[i].VirtualAddress, delta, 1 ); /* Build the import directory */ dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY]; if (dir->Size) { IMAGE_IMPORT_DESCRIPTOR *imports = (void *)(addr + dir->VirtualAddress); fixup_imports( imports, addr, delta ); } /* Build the resource directory */ dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY]; if (dir->Size) { void *ptr = (void *)(addr + dir->VirtualAddress); fixup_resources( ptr, ptr, delta ); } /* Build the export directory */ dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY]; if (dir->Size) { IMAGE_EXPORT_DIRECTORY *exports = (void *)(addr + dir->VirtualAddress); fixup_exports( exports, addr, delta ); } return addr; #else /* HAVE_MMAP */ return NULL; #endif /* HAVE_MMAP */ }
int load_pe_images(struct pe_image *pe_image, int n) { struct nt_header *nt_hdr; unsigned int nt_hdr_offset; int i = 0; void *image; int size; struct optional_header *opt_hdr; for (i = 0; i < n; i++) { image = pe_image[i].image; size = pe_image[i].size; /* The PE header is found at the RVA specified at offset 3c. */ if (size < 0x3c + 4) return -EINVAL; nt_hdr_offset = *(unsigned int *)(image+0x3c); nt_hdr = (struct nt_header *)((char *)image + nt_hdr_offset); pe_image[i].type = check_nt_hdr(nt_hdr); if (pe_image[i].type <= 0) return -EINVAL; if (read_exports(image, nt_hdr, pe_image[i].name)) return -EINVAL; } for (i = 0; i < n; i++) { image = pe_image[i].image; size = pe_image[i].size; nt_hdr_offset = *(unsigned int *)(image+0x3c); nt_hdr = (struct nt_header *)((char *)image + nt_hdr_offset); opt_hdr = &nt_hdr->opt_hdr; if (fixup_reloc(image, nt_hdr)) return -EINVAL; if (fixup_imports(image, nt_hdr)) return -EINVAL; flush_icache_range(image, pe_image[i].size); pe_image[i].entry = RVA2VA(image, opt_hdr->opt_std_hdr.entry_rva, void *); DBGTRACE1("entry is at %p, rva at %08X", pe_image[i].entry, (unsigned int)opt_hdr->opt_std_hdr.entry_rva); } for (i = 0; i < n; i++) { image = pe_image[i].image; size = pe_image[i].size; nt_hdr_offset = *(unsigned int *)(image+0x3c); nt_hdr = (struct nt_header *)((char *)image + nt_hdr_offset); opt_hdr = &nt_hdr->opt_hdr; if (pe_image[i].type == COFF_CHAR_DLL) { struct ustring ustring; char *buf = "0\0t0m0p00"; int (*dll_entry)(struct ustring *ustring) STDCALL; memset(&ustring, 0, sizeof(ustring)); ustring.buf = buf; dll_entry = (void *)get_dll_init(pe_image[i].name); DBGTRACE1("calling dll_init at %p", dll_entry); if (!dll_entry || dll_entry(&ustring)) ERROR("DLL initialize failed for %s", pe_image[i].name); } else if (pe_image[i].type == COFF_CHAR_IMAGE) ; else ERROR("illegal image type: %d", pe_image[i].type); }
int load_pe_images(struct pe_image *pe_image, int n) { int i; struct pe_image *pe; #ifdef DEBUG /* Sanity checkings */ CHECK_SZ(IMAGE_SECTION_HEADER, IMAGE_SIZEOF_SECTION_HEADER); CHECK_SZ(IMAGE_FILE_HEADER, IMAGE_SIZEOF_FILE_HEADER); CHECK_SZ(IMAGE_OPTIONAL_HEADER, IMAGE_SIZEOF_NT_OPTIONAL_HEADER); CHECK_SZ(IMAGE_NT_HEADERS, 4 + IMAGE_SIZEOF_FILE_HEADER + IMAGE_SIZEOF_NT_OPTIONAL_HEADER); CHECK_SZ(IMAGE_DOS_HEADER, 0x40); CHECK_SZ(IMAGE_EXPORT_DIRECTORY, 40); CHECK_SZ(IMAGE_BASE_RELOCATION, 8); CHECK_SZ(IMAGE_IMPORT_DESCRIPTOR, 20); #endif for (i = 0; i < n; i++) { IMAGE_DOS_HEADER *dos_hdr; pe = &pe_image[i]; dos_hdr = pe->image; if (pe->size < sizeof(IMAGE_DOS_HEADER)) { DBGTRACE1("image too small: %d", pe->size); return -EINVAL; } pe->nt_hdr = (IMAGE_NT_HEADERS *)(pe->image + dos_hdr->e_lfanew); pe->opt_hdr = &pe->nt_hdr->OptionalHeader; pe->type = check_nt_hdr(pe->nt_hdr); if (pe->type <= 0) { DBGTRACE1("type <= 0"); return -EINVAL; } if (fix_pe_image(pe)) { DBGTRACE1("bad PE image"); return -EINVAL; } if (read_exports(pe)) { DBGTRACE1("read exports failed"); return -EINVAL; } } for (i = 0; i < n; i++) { pe = &pe_image[i]; if (fixup_reloc(pe->image, pe->nt_hdr)) { DBGTRACE1("fixup reloc failed"); return -EINVAL; } if (fixup_imports(pe->image, pe->nt_hdr)) { DBGTRACE1("fixup imports failed"); return -EINVAL; } #if defined(CONFIG_X86_64) INFO("fixing KI_USER_SHARED_DATA address in the driver"); fix_user_shared_data_addr(pe_image[i].image, pe_image[i].size); #endif flush_icache_range(pe->image, pe->size); pe->entry = RVA2VA(pe->image, pe->opt_hdr->AddressOfEntryPoint, void *); DBGTRACE1("entry is at %p, rva at %08X", pe->entry, pe->opt_hdr->AddressOfEntryPoint); } for (i = 0; i < n; i++) { pe = &pe_image[i]; if (pe->type == IMAGE_FILE_DLL) { struct unicode_string ustring; char *buf = "0/0t0m0p00"; int (*dll_entry)(struct unicode_string *ustring) wstdcall; memset(&ustring, 0, sizeof(ustring)); ustring.buf = (wchar_t *)buf; dll_entry = (void *)get_dll_init(pe->name); DBGTRACE1("calling dll_init at %p", dll_entry); if (!dll_entry || dll_entry(&ustring)) ERROR("DLL initialize failed for %s", pe->name); } else if (pe->type != IMAGE_FILE_EXECUTABLE_IMAGE) ERROR("illegal image type: %d", pe->type); }