/******************************************************************* * BuildSpec32File * * Build a Win32 C file from a spec file. */ void BuildSpec32File( DLLSPEC *spec ) { resolve_imports( spec ); output_standard_file_header(); output_module( spec ); output_stubs( spec ); output_exports( spec ); output_imports( spec ); if (is_undefined( "__wine_call_from_regs" )) output_asm_relays(); output_resources( spec ); output_gnu_stack_note(); }
/******************************************************************* * output_spec16_file * * Output the complete data for a spec 16-bit file. */ void output_spec16_file( DLLSPEC *spec16 ) { DLLSPEC *spec32 = alloc_dll_spec(); resolve_imports( spec16 ); add_16bit_exports( spec32, spec16 ); output_standard_file_header(); output_module( spec32 ); output_module16( spec16 ); output_stubs( spec16 ); output_exports( spec32 ); output_imports( spec16 ); if (is_undefined( "__wine_call_from_16" )) output_asm_relays16(); if (spec16->main_module) { output( "\n\t%s\n", get_asm_string_section() ); output( ".L__wine_spec_main_module:\n" ); output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec16->main_module ); } output_gnu_stack_note(); free_dll_spec( spec32 ); output("%s:/*?*/\n", asm_name("_end")); }
/******************************************************************* * output_fake_module * * Build a fake binary module from a spec file. */ void output_fake_module( DLLSPEC *spec ) { static const unsigned char dll_code_section[] = { 0x31, 0xc0, /* xor %eax,%eax */ 0xc2, 0x0c, 0x00 }; /* ret $12 */ static const unsigned char exe_code_section[] = { 0xb8, 0x01, 0x00, 0x00, 0x00, /* movl $1,%eax */ 0xc2, 0x04, 0x00 }; /* ret $4 */ static const char fakedll_signature[] = "Wine placeholder DLL"; const unsigned int page_size = get_page_size(); const unsigned int section_align = page_size; const unsigned int file_align = 0x200; const unsigned int reloc_size = 8; const unsigned int lfanew = (0x40 + sizeof(fakedll_signature) + 15) & ~15; const unsigned int nb_sections = 2 + (spec->nb_resources != 0); const unsigned int text_size = (spec->characteristics & IMAGE_FILE_DLL) ? sizeof(dll_code_section) : sizeof(exe_code_section); unsigned char *resources; unsigned int resources_size; unsigned int image_size = 3 * section_align; resolve_imports( spec ); output_bin_resources( spec, 3 * section_align ); resources = output_buffer; resources_size = output_buffer_pos; if (resources_size) image_size += (resources_size + section_align - 1) & ~(section_align - 1); init_output_buffer(); put_word( 0x5a4d ); /* e_magic */ put_word( 0x40 ); /* e_cblp */ put_word( 0x01 ); /* e_cp */ put_word( 0 ); /* e_crlc */ put_word( lfanew / 16 ); /* e_cparhdr */ put_word( 0x0000 ); /* e_minalloc */ put_word( 0xffff ); /* e_maxalloc */ put_word( 0x0000 ); /* e_ss */ put_word( 0x00b8 ); /* e_sp */ put_word( 0 ); /* e_csum */ put_word( 0 ); /* e_ip */ put_word( 0 ); /* e_cs */ put_word( lfanew ); /* e_lfarlc */ put_word( 0 ); /* e_ovno */ put_dword( 0 ); /* e_res */ put_dword( 0 ); put_word( 0 ); /* e_oemid */ put_word( 0 ); /* e_oeminfo */ put_dword( 0 ); /* e_res2 */ put_dword( 0 ); put_dword( 0 ); put_dword( 0 ); put_dword( 0 ); put_dword( lfanew ); put_data( fakedll_signature, sizeof(fakedll_signature) ); align_output( 16 ); put_dword( 0x4550 ); /* Signature */ switch(target_cpu) { case CPU_x86: put_word( IMAGE_FILE_MACHINE_I386 ); break; case CPU_x86_64: put_word( IMAGE_FILE_MACHINE_AMD64 ); break; case CPU_POWERPC: put_word( IMAGE_FILE_MACHINE_POWERPC ); break; case CPU_SPARC: put_word( IMAGE_FILE_MACHINE_SPARC ); break; case CPU_ARM: put_word( IMAGE_FILE_MACHINE_ARMV7 ); break; } put_word( nb_sections ); /* NumberOfSections */ put_dword( 0 ); /* TimeDateStamp */ put_dword( 0 ); /* PointerToSymbolTable */ put_dword( 0 ); /* NumberOfSymbols */ put_word( get_ptr_size() == 8 ? IMAGE_SIZEOF_NT_OPTIONAL64_HEADER : IMAGE_SIZEOF_NT_OPTIONAL32_HEADER ); /* SizeOfOptionalHeader */ put_word( spec->characteristics ); /* Characteristics */ put_word( get_ptr_size() == 8 ? IMAGE_NT_OPTIONAL_HDR64_MAGIC : IMAGE_NT_OPTIONAL_HDR32_MAGIC ); /* Magic */ put_byte( 0 ); /* MajorLinkerVersion */ put_byte( 0 ); /* MinorLinkerVersion */ put_dword( text_size ); /* SizeOfCode */ put_dword( 0 ); /* SizeOfInitializedData */ put_dword( 0 ); /* SizeOfUninitializedData */ put_dword( section_align ); /* AddressOfEntryPoint */ put_dword( section_align ); /* BaseOfCode */ if (get_ptr_size() == 4) put_dword( 0 ); /* BaseOfData */ put_pword( 0x10000000 ); /* ImageBase */ put_dword( section_align ); /* SectionAlignment */ put_dword( file_align ); /* FileAlignment */ put_word( 1 ); /* MajorOperatingSystemVersion */ put_word( 0 ); /* MinorOperatingSystemVersion */ put_word( 0 ); /* MajorImageVersion */ put_word( 0 ); /* MinorImageVersion */ put_word( spec->subsystem_major ); /* MajorSubsystemVersion */ put_word( spec->subsystem_minor ); /* MinorSubsystemVersion */ put_dword( 0 ); /* Win32VersionValue */ put_dword( image_size ); /* SizeOfImage */ put_dword( file_align ); /* SizeOfHeaders */ put_dword( 0 ); /* CheckSum */ put_word( spec->subsystem ); /* Subsystem */ put_word( spec->dll_characteristics ); /* DllCharacteristics */ put_pword( (spec->stack_size ? spec->stack_size : 1024) * 1024 ); /* SizeOfStackReserve */ put_pword( page_size ); /* SizeOfStackCommit */ put_pword( (spec->heap_size ? spec->heap_size : 1024) * 1024 ); /* SizeOfHeapReserve */ put_pword( page_size ); /* SizeOfHeapCommit */ put_dword( 0 ); /* LoaderFlags */ put_dword( 16 ); /* NumberOfRvaAndSizes */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */ if (resources_size) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */ { put_dword( 3 * section_align ); put_dword( resources_size ); } else { put_dword( 0 ); put_dword( 0 ); } put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] */ put_dword( 2 * section_align ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC] */ put_dword( reloc_size ); put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_COPYRIGHT] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[15] */ /* .text section */ put_data( ".text\0\0", 8 ); /* Name */ put_dword( section_align ); /* VirtualSize */ put_dword( section_align ); /* VirtualAddress */ put_dword( text_size ); /* SizeOfRawData */ put_dword( file_align ); /* PointerToRawData */ put_dword( 0 ); /* PointerToRelocations */ put_dword( 0 ); /* PointerToLinenumbers */ put_word( 0 ); /* NumberOfRelocations */ put_word( 0 ); /* NumberOfLinenumbers */ put_dword( 0x60000020 /* CNT_CODE|MEM_EXECUTE|MEM_READ */ ); /* Characteristics */ /* .reloc section */ put_data( ".reloc\0", 8 ); /* Name */ put_dword( section_align ); /* VirtualSize */ put_dword( 2 * section_align );/* VirtualAddress */ put_dword( reloc_size ); /* SizeOfRawData */ put_dword( 2 * file_align ); /* PointerToRawData */ put_dword( 0 ); /* PointerToRelocations */ put_dword( 0 ); /* PointerToLinenumbers */ put_word( 0 ); /* NumberOfRelocations */ put_word( 0 ); /* NumberOfLinenumbers */ put_dword( 0x42000040 /* CNT_INITIALIZED_DATA|MEM_DISCARDABLE|MEM_READ */ ); /* Characteristics */ /* .rsrc section */ if (resources_size) { put_data( ".rsrc\0\0", 8 ); /* Name */ put_dword( (resources_size + section_align - 1) & ~(section_align - 1) ); /* VirtualSize */ put_dword( 3 * section_align );/* VirtualAddress */ put_dword( resources_size ); /* SizeOfRawData */ put_dword( 3 * file_align ); /* PointerToRawData */ put_dword( 0 ); /* PointerToRelocations */ put_dword( 0 ); /* PointerToLinenumbers */ put_word( 0 ); /* NumberOfRelocations */ put_word( 0 ); /* NumberOfLinenumbers */ put_dword( 0x40000040 /* CNT_INITIALIZED_DATA|MEM_READ */ ); /* Characteristics */ } /* .text contents */ align_output( file_align ); if (spec->characteristics & IMAGE_FILE_DLL) put_data( dll_code_section, sizeof(dll_code_section) ); else put_data( exe_code_section, sizeof(exe_code_section) ); /* .reloc contents */ align_output( file_align ); put_dword( 0 ); /* VirtualAddress */ put_dword( 0 ); /* SizeOfBlock */ /* .rsrc contents */ if (resources_size) { align_output( file_align ); put_data( resources, resources_size ); } flush_output_buffer(); }
// Loads a module to memory SceUID load_module(SceUID fd, const char *path, void *addr, SceOff off) { _sceModuleInfo modinfo; Elf32_Ehdr ehdr; Elf32_Phdr *phdrs; tStubEntry *stubs; SceUID phdrs_block; SceUID modid = mod_loaded_num; size_t phdrs_size, mod_size, stubs_size; int i, ret; dbg_printf("\n\n->Entering load_module...\n"); for (i = 0; path[i]; i++) { if (i >= sizeof(mod_table[modid].path) - 1) return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; mod_table[modid].path[i] = path[i]; } mod_table[modid].path[i] = '\0'; //dbg_printf("mod_table address: 0x%08X\n", mod_table); // Read ELF header sceIoLseek(fd, off, PSP_SEEK_SET); sceIoRead(fd, &ehdr, sizeof(ehdr)); // Check for module encryption if (!strncmp(ehdr.e_ident, "~PSP", 4)) return SCE_KERNEL_ERROR_UNSUPPORTED_PRX_TYPE; dbg_printf("\n->ELF header:\n" "Type: 0x%08X\n" "Code entry: 0x%08X\n" "Program header table offset: 0x%08X\n" "Program header size: 0x%08X\n" "Number of program headers: 0x%08X\n" "Section header table offset: 0x%08X\n" "Section header size: 0x%08X\n" "Number of section headers: 0x%08X\n", ehdr.e_type, (int)ehdr.e_entry, ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum, ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shnum); phdrs_size = ehdr.e_phentsize * ehdr.e_phnum; ret = sceKernelAllocPartitionMemory( 2, "HBL Module Program Headers", PSP_SMEM_High, phdrs_size, NULL); if (ret < 0) goto fail; else phdrs_block = ret; phdrs = sceKernelGetBlockHeadAddr(phdrs_block); if (phdrs == NULL) { ret = SCE_KERNEL_ERROR_ERROR; goto fail; } ret = sceIoLseek(fd, off + ehdr.e_phoff, PSP_SEEK_SET); if (ret < 0) goto fail; ret = sceIoRead(fd, phdrs, phdrs_size); if (ret < 0) goto fail; switch (ehdr.e_type) { case ELF_STATIC: if (modid > 0) { ret = SCE_KERNEL_ERROR_EXCLUSIVE_LOAD; goto fail; } // Load ELF program section into memory ret = elf_load(fd, off, phdrs, ehdr.e_phnum, modmgrMalloc); if (ret < 0) goto fail; else mod_size = ret; // Locate ELF's .lib.stubs section stubs = elf_find_imports(fd, off, &ehdr, &stubs_size); if (stubs == NULL) { ret = SCE_KERNEL_ERROR_ERROR; goto fail; } mod_table[modid].text_entry = (u32 *)ehdr.e_entry; ret = elf_get_gp(fd, off, &ehdr, &mod_table[modid].gp); if (ret < 0) goto fail; break; case ELF_RELOC: if (modid >= MAX_MODULES) { ret = SCE_KERNEL_ERROR_EXCLUSIVE_LOAD; goto fail; } dbg_printf("load_module -> Offset: 0x%08X\n", off); // Load PRX program section ret = prx_load(fd, off, &ehdr, phdrs, &modinfo, &addr, modmgrMalloc); if (ret < 0) goto fail; else mod_size = ret; stubs = (void *)((int)modinfo.stub_top + (int)addr); stubs_size = (int)modinfo.stub_end - (int)modinfo.stub_top; // Relocate ELF entry point and GP register mod_table[modid].text_entry = (u32 *)((u32)ehdr.e_entry + (int)addr); mod_table[modid].gp = (void *)((int)modinfo.gp_value + (int)addr); break; default: dbg_printf("Uknown ELF type: 0x%08X\n", ehdr.e_type); ret = SCE_KERNEL_ERROR_UNSUPPORTED_PRX_TYPE; goto fail; } dbg_printf("resolve stubs\n"); // Resolve ELF's stubs with game's stubs and syscall estimation ret = resolve_imports(stubs, stubs_size); if (ret) dbg_printf("failed to resolve imports: 0x%08X\n", ret); mod_table[modid].state = LOADED; mod_loaded_num++; //dbg_printf("Module table updated\n"); dbg_printf("\n->Actual number of loaded modules: %d\n", mod_loaded_num); dbg_printf("Last loaded module [%d]:\n", modid); #ifdef DEBUG log_mod_entry(mod_table[modid]); #endif synci(addr, addr + mod_size); ret = modid; fail: sceKernelFreePartitionMemory(phdrs_block); return ret; }
/******************************************************************* * BuildSpec32File * * Build a Win32 C file from a spec file. */ void BuildSpec32File( FILE *outfile, DLLSPEC *spec ) { int machine = 0; unsigned int page_size = get_page_size(); resolve_imports( spec ); output_standard_file_header( outfile ); /* Reserve some space for the PE header */ fprintf( outfile, "\t.text\n" ); fprintf( outfile, "\t.align %d\n", get_alignment(page_size) ); fprintf( outfile, "__wine_spec_pe_header:\n" ); if (target_platform == PLATFORM_APPLE) fprintf( outfile, "\t.space 65536\n" ); else fprintf( outfile, "\t.skip 65536\n" ); /* Output the NT header */ fprintf( outfile, "\n\t.data\n" ); fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) ); fprintf( outfile, "%s\n", asm_globl("__wine_spec_nt_header") ); fprintf( outfile, ".L__wine_spec_rva_base:\n" ); fprintf( outfile, "\t.long 0x%04x\n", IMAGE_NT_SIGNATURE ); /* Signature */ switch(target_cpu) { case CPU_x86: machine = IMAGE_FILE_MACHINE_I386; break; case CPU_x86_64: machine = IMAGE_FILE_MACHINE_AMD64; break; case CPU_POWERPC: machine = IMAGE_FILE_MACHINE_POWERPC; break; case CPU_ALPHA: machine = IMAGE_FILE_MACHINE_ALPHA; break; case CPU_SPARC: machine = IMAGE_FILE_MACHINE_UNKNOWN; break; } fprintf( outfile, "\t%s 0x%04x\n", /* Machine */ get_asm_short_keyword(), machine ); fprintf( outfile, "\t%s 0\n", /* NumberOfSections */ get_asm_short_keyword() ); fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */ fprintf( outfile, "\t.long 0\n" ); /* PointerToSymbolTable */ fprintf( outfile, "\t.long 0\n" ); /* NumberOfSymbols */ fprintf( outfile, "\t%s %d\n", /* SizeOfOptionalHeader */ get_asm_short_keyword(), get_ptr_size() == 8 ? IMAGE_SIZEOF_NT_OPTIONAL64_HEADER : IMAGE_SIZEOF_NT_OPTIONAL32_HEADER ); fprintf( outfile, "\t%s 0x%04x\n", /* Characteristics */ get_asm_short_keyword(), spec->characteristics ); fprintf( outfile, "\t%s 0x%04x\n", /* Magic */ get_asm_short_keyword(), get_ptr_size() == 8 ? IMAGE_NT_OPTIONAL_HDR64_MAGIC : IMAGE_NT_OPTIONAL_HDR32_MAGIC ); fprintf( outfile, "\t.byte 0\n" ); /* MajorLinkerVersion */ fprintf( outfile, "\t.byte 0\n" ); /* MinorLinkerVersion */ fprintf( outfile, "\t.long 0\n" ); /* SizeOfCode */ fprintf( outfile, "\t.long 0\n" ); /* SizeOfInitializedData */ fprintf( outfile, "\t.long 0\n" ); /* SizeOfUninitializedData */ /* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */ fprintf( outfile, "\t%s %s\n", /* AddressOfEntryPoint */ get_asm_ptr_keyword(), asm_name(spec->init_func) ); if (get_ptr_size() == 4) { fprintf( outfile, "\t.long 0\n" ); /* BaseOfCode */ fprintf( outfile, "\t.long 0\n" ); /* BaseOfData */ } fprintf( outfile, "\t%s __wine_spec_pe_header\n", /* ImageBase */ get_asm_ptr_keyword() ); fprintf( outfile, "\t.long %u\n", page_size ); /* SectionAlignment */ fprintf( outfile, "\t.long %u\n", page_size ); /* FileAlignment */ fprintf( outfile, "\t%s 1,0\n", /* Major/MinorOperatingSystemVersion */ get_asm_short_keyword() ); fprintf( outfile, "\t%s 0,0\n", /* Major/MinorImageVersion */ get_asm_short_keyword() ); fprintf( outfile, "\t%s %u,%u\n", /* Major/MinorSubsystemVersion */ get_asm_short_keyword(), spec->subsystem_major, spec->subsystem_minor ); fprintf( outfile, "\t.long 0\n" ); /* Win32VersionValue */ fprintf( outfile, "\t.long %s-.L__wine_spec_rva_base\n", /* SizeOfImage */ asm_name("_end") ); fprintf( outfile, "\t.long %u\n", page_size ); /* SizeOfHeaders */ fprintf( outfile, "\t.long 0\n" ); /* CheckSum */ fprintf( outfile, "\t%s 0x%04x\n", /* Subsystem */ get_asm_short_keyword(), spec->subsystem ); fprintf( outfile, "\t%s 0\n", /* DllCharacteristics */ get_asm_short_keyword() ); fprintf( outfile, "\t%s %u,%u\n", /* SizeOfStackReserve/Commit */ get_asm_ptr_keyword(), (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size ); fprintf( outfile, "\t%s %u,%u\n", /* SizeOfHeapReserve/Commit */ get_asm_ptr_keyword(), (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size ); fprintf( outfile, "\t.long 0\n" ); /* LoaderFlags */ fprintf( outfile, "\t.long 16\n" ); /* NumberOfRvaAndSizes */ if (spec->base <= spec->limit) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */ fprintf( outfile, "\t.long .L__wine_spec_exports-.L__wine_spec_rva_base," ".L__wine_spec_exports_end-.L__wine_spec_exports\n" ); else fprintf( outfile, "\t.long 0,0\n" ); if (has_imports()) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */ fprintf( outfile, "\t.long .L__wine_spec_imports-.L__wine_spec_rva_base," ".L__wine_spec_imports_end-.L__wine_spec_imports\n" ); else fprintf( outfile, "\t.long 0,0\n" ); if (spec->nb_resources) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */ fprintf( outfile, "\t.long .L__wine_spec_resources-.L__wine_spec_rva_base," ".L__wine_spec_resources_end-.L__wine_spec_resources\n" ); else fprintf( outfile, "\t.long 0,0\n" ); fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[3] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[4] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[5] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[6] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[7] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[8] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[9] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[10] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[11] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[12] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[13] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[14] */ fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[15] */ fprintf( outfile, "\n\t%s\n", get_asm_string_section() ); fprintf( outfile, "%s\n", asm_globl("__wine_spec_file_name") ); fprintf( outfile, ".L__wine_spec_file_name:\n" ); fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name ); if (target_platform == PLATFORM_APPLE) fprintf( outfile, "\t.lcomm %s,4\n", asm_name("_end") ); output_stubs( outfile, spec ); output_exports( outfile, spec ); output_imports( outfile, spec ); output_resources( outfile, spec ); output_asm_constructor( outfile, "__wine_spec_init_ctor" ); output_gnu_stack_note( outfile ); }