2003-01-26 06:18:56 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// *
|
|
|
|
// * .,-::::: .,:: .::::::::. .,:: .:
|
|
|
|
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
|
|
|
|
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
|
|
|
|
// * $$$ Y$$$P $$""""Y$$ Y$$$P
|
|
|
|
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
|
|
|
|
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
|
|
|
|
// *
|
|
|
|
// * Cxbx->Win32->Cxbx->EmuExe.cpp
|
|
|
|
// *
|
|
|
|
// * This file is part of the Cxbx project.
|
|
|
|
// *
|
|
|
|
// * Cxbx and Cxbe are free software; you can redistribute them
|
|
|
|
// * and/or modify them under the terms of the GNU General Public
|
|
|
|
// * License as published by the Free Software Foundation; either
|
|
|
|
// * version 2 of the license, or (at your option) any later version.
|
|
|
|
// *
|
|
|
|
// * This program is distributed in the hope that it will be useful,
|
|
|
|
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// * GNU General Public License for more details.
|
|
|
|
// *
|
|
|
|
// * You should have recieved a copy of the GNU General Public License
|
|
|
|
// * along with this program; see the file COPYING.
|
|
|
|
// * If not, write to the Free Software Foundation, Inc.,
|
|
|
|
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
|
|
|
// *
|
|
|
|
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
|
|
|
|
// *
|
|
|
|
// * All rights reserved
|
|
|
|
// *
|
|
|
|
// ******************************************************************
|
|
|
|
#include "EmuExe.h"
|
|
|
|
#include "Prolog.h"
|
2003-03-27 06:23:58 +00:00
|
|
|
#include "Emu.h"
|
2003-01-26 06:56:11 +00:00
|
|
|
|
2003-04-02 02:23:30 +00:00
|
|
|
#include <stdio.h>
|
2003-01-26 06:18:56 +00:00
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * constructor
|
|
|
|
// ******************************************************************
|
2003-04-04 04:35:00 +00:00
|
|
|
EmuExe::EmuExe(Xbe *x_Xbe, DebugMode x_debug_mode, char *x_debug_filename) : Exe()
|
2003-01-26 06:18:56 +00:00
|
|
|
{
|
|
|
|
ConstructorInit();
|
|
|
|
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating Exe file...\n");
|
|
|
|
|
2003-03-31 04:03:54 +00:00
|
|
|
Xbe::TLS OrigTLS;
|
|
|
|
|
|
|
|
void *OrigTLSAddr = (void*)x_Xbe->GetTLSData();
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * backup original TLS structure (it will be modified)
|
|
|
|
// ******************************************************************
|
2003-03-31 23:22:21 +00:00
|
|
|
if(x_Xbe->m_TLS != 0 && OrigTLSAddr != 0)
|
|
|
|
memcpy(&OrigTLS, x_Xbe->m_TLS, sizeof(Xbe::TLS));
|
2003-03-31 04:03:54 +00:00
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * generate pe header
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating PE header...");
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
m_Header.m_magic = *(uint32 *)"PE\0\0"; // magic number : "PE\0\0"
|
|
|
|
m_Header.m_machine = IMAGE_FILE_MACHINE_I386; // machine type : i386
|
|
|
|
m_Header.m_sections = (uint16)(x_Xbe->m_Header.dwSections + 2); // xbe sections + .cxbximp + .cxbxplg
|
|
|
|
m_Header.m_timedate = x_Xbe->m_Header.dwTimeDate; // time/date stamp
|
|
|
|
m_Header.m_symbol_table_addr = 0; // unused
|
|
|
|
m_Header.m_symbols = 0; // unused
|
|
|
|
m_Header.m_sizeof_optional_header = sizeof(OptionalHeader); // size of optional header
|
|
|
|
m_Header.m_characteristics = 0x010F; // should be fine..
|
2003-02-07 20:44:49 +00:00
|
|
|
|
|
|
|
printf("OK\n");
|
2003-01-26 06:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate optional header
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating Optional Header...");
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
m_OptionalHeader.m_magic = 0x010B; // magic number : 0x010B
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * abitrary linker version : 6.0
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_linker_version_major = 0x06;
|
|
|
|
m_OptionalHeader.m_linker_version_minor = 0x00;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * size of headers
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_sizeof_headers = sizeof(bzDOSStub) + sizeof(m_Header);
|
|
|
|
m_OptionalHeader.m_sizeof_headers += sizeof(m_OptionalHeader) + sizeof(*m_SectionHeader)*m_Header.m_sections;
|
|
|
|
m_OptionalHeader.m_sizeof_headers = RoundUp(m_OptionalHeader.m_sizeof_headers, PE_FILE_ALIGN);
|
|
|
|
|
|
|
|
m_OptionalHeader.m_image_base = x_Xbe->m_Header.dwBaseAddr;
|
|
|
|
|
|
|
|
m_OptionalHeader.m_section_alignment = PE_SEGM_ALIGN;
|
|
|
|
m_OptionalHeader.m_file_alignment = PE_FILE_ALIGN;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * OS version : 4.0
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_os_version_major = 0x0004;
|
|
|
|
m_OptionalHeader.m_os_version_minor = 0x0000;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * image version : 0.0
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_image_version_major = 0x0000;
|
|
|
|
m_OptionalHeader.m_image_version_minor = 0x0000;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * subsystem version : 4.0
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_subsystem_version_major = 0x0004;
|
|
|
|
m_OptionalHeader.m_subsystem_version_minor = 0x0000;
|
|
|
|
|
|
|
|
m_OptionalHeader.m_win32_version = 0x00000000;
|
|
|
|
m_OptionalHeader.m_checksum = 0x00000000;
|
|
|
|
m_OptionalHeader.m_subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * no special dll characteristics are necessary
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_dll_characteristics = 0x0000;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * TODO: for each of these, check for bad values and correct them
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_sizeof_stack_reserve = 0x00100000;
|
|
|
|
m_OptionalHeader.m_sizeof_stack_commit = 0x00001000;
|
|
|
|
m_OptionalHeader.m_sizeof_heap_reserve = x_Xbe->m_Header.dwPeHeapReserve;
|
|
|
|
m_OptionalHeader.m_sizeof_heap_commit = x_Xbe->m_Header.dwPeHeapCommit;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * this member is obsolete, so we'll just set it to zero
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_loader_flags = 0x00000000;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * we'll set this to the typical 0x10 (16)
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_data_directories = 0x10;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * clear all data directories (we'll setup some later)
|
|
|
|
// ******************************************************************
|
|
|
|
for(uint32 d=0;d<m_OptionalHeader.m_data_directories;d++)
|
|
|
|
{
|
|
|
|
m_OptionalHeader.m_image_data_directory[d].m_virtual_addr = 0;
|
|
|
|
m_OptionalHeader.m_image_data_directory[d].m_size = 0;
|
|
|
|
}
|
2003-02-07 20:44:49 +00:00
|
|
|
|
|
|
|
printf("OK\n");
|
2003-01-26 06:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate section headers
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating Section Headers...\n");
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
m_SectionHeader = new SectionHeader[m_Header.m_sections];
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * start appending section headers at this point
|
|
|
|
// ******************************************************************
|
|
|
|
uint32 dwSectionCursor = RoundUp(m_OptionalHeader.m_sizeof_headers, 0x1000);
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate xbe section headers
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
for(uint32 v=0;v<x_Xbe->m_Header.dwSections;v++)
|
|
|
|
{
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating Section Header 0x%.04X...", v);
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * generate xbe section name
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
memset(m_SectionHeader[v].m_name, 0, 8);
|
|
|
|
|
|
|
|
for(int c=0;c<8;c++)
|
|
|
|
{
|
|
|
|
m_SectionHeader[v].m_name[c] = x_Xbe->m_szSectionName[v][c];
|
|
|
|
|
|
|
|
if(m_SectionHeader[v].m_name[c] == '\0')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate xbe section virtual size / addr
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 VirtSize = x_Xbe->m_SectionHeader[v].dwVirtualSize;
|
|
|
|
uint32 VirtAddr = x_Xbe->m_SectionHeader[v].dwVirtualAddr - x_Xbe->m_Header.dwBaseAddr;
|
|
|
|
|
|
|
|
m_SectionHeader[v].m_virtual_size = VirtSize;
|
|
|
|
m_SectionHeader[v].m_virtual_addr = VirtAddr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate xbe section raw size / addr
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
// TODO: get this working such that m_sizeof_raw can be the actual raw size, not virtual size
|
|
|
|
uint32 RawSize = RoundUp(x_Xbe->m_SectionHeader[v].dwVirtualSize, PE_FILE_ALIGN);
|
|
|
|
uint32 RawAddr = dwSectionCursor;
|
|
|
|
|
|
|
|
m_SectionHeader[v].m_sizeof_raw = RawSize;
|
|
|
|
m_SectionHeader[v].m_raw_addr = RawAddr;
|
|
|
|
|
|
|
|
dwSectionCursor += RawSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * relocation / line numbers will not exist
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
m_SectionHeader[v].m_relocations_addr = 0;
|
|
|
|
m_SectionHeader[v].m_linenumbers_addr = 0;
|
|
|
|
|
|
|
|
m_SectionHeader[v].m_relocations = 0;
|
|
|
|
m_SectionHeader[v].m_linenumbers = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate flags for this xbe section
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 flags = IMAGE_SCN_MEM_READ;
|
|
|
|
|
|
|
|
if(x_Xbe->m_SectionHeader[v].dwFlags.bExecutable)
|
|
|
|
{
|
|
|
|
flags |= IMAGE_SCN_MEM_EXECUTE;
|
|
|
|
flags |= IMAGE_SCN_CNT_CODE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
flags |= IMAGE_SCN_CNT_INITIALIZED_DATA;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(x_Xbe->m_SectionHeader[v].dwFlags.bWritable)
|
|
|
|
flags |= IMAGE_SCN_MEM_WRITE;
|
|
|
|
|
|
|
|
m_SectionHeader[v].m_characteristics = flags;
|
|
|
|
}
|
2003-02-07 20:44:49 +00:00
|
|
|
|
|
|
|
printf("OK\n");
|
2003-01-26 06:18:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate .cxbximp section header
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 i = m_Header.m_sections - 2;
|
|
|
|
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating Section Header 0x%.04X (.cxbximp)...", i);
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
memcpy(m_SectionHeader[i].m_name, ".cxbximp", 8);
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate .cxbximp section virtual size / addr
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
2003-03-31 23:22:21 +00:00
|
|
|
uint32 size_null = 0;
|
|
|
|
uint32 data_size = 0;
|
|
|
|
|
|
|
|
if(x_Xbe->m_TLS != 0 && OrigTLSAddr != 0)
|
|
|
|
{
|
|
|
|
size_null = 4;
|
|
|
|
data_size = x_Xbe->m_TLS->dwDataEndAddr - x_Xbe->m_TLS->dwDataStartAddr + x_Xbe->m_TLS->dwSizeofZeroFill;
|
|
|
|
}
|
|
|
|
|
2003-03-31 04:03:54 +00:00
|
|
|
uint32 virt_size = RoundUp(0x6E + data_size + size_null, PE_SEGM_ALIGN);
|
2003-01-26 06:18:56 +00:00
|
|
|
uint32 virt_addr = RoundUp(m_SectionHeader[i-1].m_virtual_addr + m_SectionHeader[i-1].m_virtual_size, PE_SEGM_ALIGN);
|
|
|
|
|
|
|
|
m_SectionHeader[i].m_virtual_size = virt_size;
|
|
|
|
m_SectionHeader[i].m_virtual_addr = virt_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate .cxbximp section raw size / addr
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 raw_size = RoundUp(m_SectionHeader[i].m_virtual_size, PE_FILE_ALIGN);
|
|
|
|
|
|
|
|
m_SectionHeader[i].m_sizeof_raw = raw_size;
|
|
|
|
m_SectionHeader[i].m_raw_addr = dwSectionCursor;
|
|
|
|
|
|
|
|
dwSectionCursor += raw_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * relocation / line numbers will not exist
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
m_SectionHeader[i].m_relocations_addr = 0;
|
|
|
|
m_SectionHeader[i].m_linenumbers_addr = 0;
|
|
|
|
|
|
|
|
m_SectionHeader[i].m_relocations = 0;
|
|
|
|
m_SectionHeader[i].m_linenumbers = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * make this section readable initialized data
|
|
|
|
// ******************************************************************
|
|
|
|
m_SectionHeader[i].m_characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * update import table directory entry
|
|
|
|
// ******************************************************************
|
2003-01-31 22:15:41 +00:00
|
|
|
m_OptionalHeader.m_image_data_directory[IMAGE_DIRECTORY_ENTRY_IMPORT].m_virtual_addr = m_SectionHeader[i].m_virtual_addr + 0x08;
|
|
|
|
m_OptionalHeader.m_image_data_directory[IMAGE_DIRECTORY_ENTRY_IMPORT].m_size = 0x28;
|
2003-01-26 06:18:56 +00:00
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * update import address table directory entry
|
|
|
|
// ******************************************************************
|
2003-01-31 22:15:41 +00:00
|
|
|
m_OptionalHeader.m_image_data_directory[IMAGE_DIRECTORY_ENTRY_IAT].m_virtual_addr = m_SectionHeader[i].m_virtual_addr;
|
|
|
|
m_OptionalHeader.m_image_data_directory[IMAGE_DIRECTORY_ENTRY_IAT].m_size = 0x08;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * update TLS entry
|
|
|
|
// ******************************************************************
|
2003-03-31 23:22:21 +00:00
|
|
|
if(x_Xbe->m_Header.dwTLSAddr != 0 && OrigTLSAddr != 0)
|
2003-01-31 22:15:41 +00:00
|
|
|
{
|
2003-03-31 04:03:54 +00:00
|
|
|
m_OptionalHeader.m_image_data_directory[IMAGE_DIRECTORY_ENTRY_TLS].m_virtual_addr = m_SectionHeader[i].m_virtual_addr + 0x56;
|
|
|
|
m_OptionalHeader.m_image_data_directory[IMAGE_DIRECTORY_ENTRY_TLS].m_size = 0x18;
|
2003-01-31 22:15:41 +00:00
|
|
|
}
|
2003-02-07 20:44:49 +00:00
|
|
|
|
|
|
|
printf("OK\n");
|
2003-01-26 06:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate .cxbxplg section header
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 i = m_Header.m_sections - 1;
|
|
|
|
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating Section Header 0x%.04X (.cxbxplg)...", i);
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
memcpy(m_SectionHeader[i].m_name, ".cxbxplg", 8);
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate .cxbxplg section virtual size / addr
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 virt_size = RoundUp(0x1000 + x_Xbe->m_Header.dwSizeofHeaders, 0x1000);
|
|
|
|
uint32 virt_addr = RoundUp(m_SectionHeader[i-1].m_virtual_addr + m_SectionHeader[i-1].m_virtual_size, PE_SEGM_ALIGN);
|
|
|
|
|
|
|
|
m_SectionHeader[i].m_virtual_size = virt_size;
|
|
|
|
m_SectionHeader[i].m_virtual_addr = virt_addr;
|
|
|
|
|
|
|
|
// our entry point should be the first bytes in this section
|
|
|
|
m_OptionalHeader.m_entry = virt_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate .cxbxplg section raw size / addr
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 raw_size = RoundUp(m_SectionHeader[i].m_virtual_size, PE_FILE_ALIGN);
|
|
|
|
|
|
|
|
m_SectionHeader[i].m_sizeof_raw = raw_size;
|
|
|
|
m_SectionHeader[i].m_raw_addr = dwSectionCursor;
|
|
|
|
|
|
|
|
dwSectionCursor += raw_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * relocation / line numbers will not exist
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
m_SectionHeader[i].m_relocations_addr = 0;
|
|
|
|
m_SectionHeader[i].m_linenumbers_addr = 0;
|
|
|
|
|
|
|
|
m_SectionHeader[i].m_relocations = 0;
|
|
|
|
m_SectionHeader[i].m_linenumbers = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * make this section readable and executable
|
|
|
|
// ******************************************************************
|
|
|
|
m_SectionHeader[i].m_characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
|
2003-02-07 20:44:49 +00:00
|
|
|
|
|
|
|
printf("OK\n");
|
2003-01-26 06:18:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate sections
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating Sections...\n");
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
m_bzSection = new uint08*[m_Header.m_sections];
|
|
|
|
|
2003-03-31 04:03:54 +00:00
|
|
|
// ******************************************************************
|
2003-03-31 23:22:21 +00:00
|
|
|
// * patch TLS for correct Exe output
|
2003-03-31 04:03:54 +00:00
|
|
|
// ******************************************************************
|
2003-03-31 23:22:21 +00:00
|
|
|
if(x_Xbe->m_TLS != 0 && OrigTLSAddr != 0)
|
2003-03-31 04:03:54 +00:00
|
|
|
{
|
|
|
|
uint32 i = m_Header.m_sections - 2;
|
|
|
|
uint32 tlsd_size = x_Xbe->m_TLS->dwDataEndAddr - x_Xbe->m_TLS->dwDataStartAddr;
|
|
|
|
|
|
|
|
x_Xbe->m_TLS->dwDataStartAddr = m_SectionHeader[i].m_virtual_addr + m_OptionalHeader.m_image_base + 0x6E;
|
|
|
|
x_Xbe->m_TLS->dwDataEndAddr = m_SectionHeader[i].m_virtual_addr + m_OptionalHeader.m_image_base + 0x6E + tlsd_size + 8;
|
|
|
|
}
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * generate xbe sections
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 kt = x_Xbe->m_Header.dwKernelImageThunkAddr;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * decode kernel thunk address
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
2003-01-28 04:57:33 +00:00
|
|
|
if((kt ^ XOR_KT_DEBUG) > 0x01000000)
|
2003-01-26 06:18:56 +00:00
|
|
|
kt ^= XOR_KT_RETAIL;
|
|
|
|
else
|
|
|
|
kt ^= XOR_KT_DEBUG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate xbe sections
|
|
|
|
// ******************************************************************
|
|
|
|
for(uint32 v=0;v<x_Xbe->m_Header.dwSections;v++)
|
|
|
|
{
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating Section 0x%.04X...", v);
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
uint32 SectionSize = m_SectionHeader[v].m_sizeof_raw;
|
|
|
|
|
|
|
|
m_bzSection[v] = new uint08[SectionSize];
|
|
|
|
|
|
|
|
memset(m_bzSection[v], 0, SectionSize);
|
|
|
|
|
|
|
|
memcpy(m_bzSection[v], x_Xbe->m_bzSection[v], x_Xbe->m_SectionHeader[v].dwSizeofRaw);
|
2003-02-07 20:44:49 +00:00
|
|
|
|
|
|
|
printf("OK\n");
|
2003-01-26 06:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate .cxbximp section
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 i = m_Header.m_sections - 2;
|
|
|
|
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating Section 0x%.04X (.cxbximp)...", i);
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
uint32 dwVirtAddr = m_SectionHeader[i].m_virtual_addr;
|
|
|
|
|
|
|
|
uint32 dwRawSize = m_SectionHeader[i].m_sizeof_raw;
|
|
|
|
|
|
|
|
m_bzSection[i] = new uint08[dwRawSize];
|
|
|
|
|
|
|
|
memset(m_bzSection[i], 0, dwRawSize);
|
|
|
|
|
|
|
|
*(uint32*)&m_bzSection[i][0x00] = dwVirtAddr + 0x38;
|
|
|
|
*(uint32*)&m_bzSection[i][0x04] = 0;
|
|
|
|
*(uint32*)&m_bzSection[i][0x08] = dwVirtAddr + 0x30;
|
|
|
|
*(uint32*)&m_bzSection[i][0x0C] = 0;
|
|
|
|
|
|
|
|
*(uint32*)&m_bzSection[i][0x10] = 0;
|
|
|
|
*(uint32*)&m_bzSection[i][0x14] = dwVirtAddr + 0x48;
|
|
|
|
*(uint32*)&m_bzSection[i][0x18] = dwVirtAddr + 0x00;
|
|
|
|
*(uint32*)&m_bzSection[i][0x1C] = 0;
|
|
|
|
|
|
|
|
*(uint32*)&m_bzSection[i][0x20] = 0;
|
|
|
|
*(uint32*)&m_bzSection[i][0x24] = 0;
|
|
|
|
*(uint32*)&m_bzSection[i][0x28] = 0;
|
|
|
|
*(uint32*)&m_bzSection[i][0x2C] = 0;
|
|
|
|
|
|
|
|
*(uint32*)&m_bzSection[i][0x30] = dwVirtAddr + 0x38;
|
|
|
|
*(uint32*)&m_bzSection[i][0x34] = 0;
|
|
|
|
*(uint16*)&m_bzSection[i][0x38] = 0x0001;
|
2003-02-07 20:44:49 +00:00
|
|
|
|
2003-04-06 20:07:36 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
memcpy(&m_bzSection[i][0x3A], "_EmuNoFunc@0\0\0CxbxKrnl.dll\0\0", 28);
|
|
|
|
#else
|
|
|
|
memcpy(&m_bzSection[i][0x3A], "_EmuNoFunc@0\0\0Cxbx.dll\0\0\0\0\0\0", 28);
|
|
|
|
#endif
|
2003-03-31 04:03:54 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * TLS Data
|
|
|
|
// ******************************************************************
|
2003-03-31 23:22:21 +00:00
|
|
|
if(x_Xbe->m_TLS != 0 && OrigTLSAddr != 0)
|
2003-03-31 04:03:54 +00:00
|
|
|
{
|
|
|
|
uint32 tlsd_size = x_Xbe->m_TLS->dwDataEndAddr - x_Xbe->m_TLS->dwDataStartAddr;
|
|
|
|
uint32 data_size = tlsd_size + x_Xbe->m_TLS->dwSizeofZeroFill;
|
|
|
|
|
|
|
|
memcpy(&m_bzSection[i][0x56], x_Xbe->m_TLS, sizeof(Xbe::TLS));
|
|
|
|
memcpy(&m_bzSection[i][0x6E], OrigTLSAddr, tlsd_size);
|
|
|
|
|
|
|
|
*(uint32*)&m_bzSection[i][0x62] = m_SectionHeader[i].m_virtual_addr + m_OptionalHeader.m_image_base + 0x6E + data_size;
|
|
|
|
*(uint32*)&m_bzSection[i][0x66] = 0;
|
|
|
|
*(uint32*)&m_bzSection[i][0x6E + data_size] = 0;
|
|
|
|
}
|
|
|
|
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("OK\n");
|
2003-01-26 06:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * generate .cxbxplg section
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 ep = x_Xbe->m_Header.dwEntryAddr;
|
|
|
|
uint32 i = m_Header.m_sections - 1;
|
|
|
|
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Generating Section 0x%.04X (.cxbxplg)...", i);
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * decode entry point
|
|
|
|
// ******************************************************************
|
|
|
|
if( (ep ^ XOR_EP_RETAIL) > 0x01000000)
|
|
|
|
ep ^= XOR_EP_DEBUG;
|
|
|
|
else
|
|
|
|
ep ^= XOR_EP_RETAIL;
|
|
|
|
|
|
|
|
m_bzSection[i] = new uint08[m_SectionHeader[i].m_sizeof_raw];
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * append prolog section
|
|
|
|
// ******************************************************************
|
|
|
|
memcpy(m_bzSection[i], Prolog, 0x1000);
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * append xbe header
|
|
|
|
// ******************************************************************
|
|
|
|
memcpy(m_bzSection[i] + 0x100, &x_Xbe->m_Header, sizeof(Xbe::Header));
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * append xbe extra header bytes
|
|
|
|
// ******************************************************************
|
|
|
|
memcpy(m_bzSection[i] + 0x100 + sizeof(Xbe::Header), x_Xbe->m_HeaderEx, x_Xbe->m_Header.dwSizeofHeaders - sizeof(Xbe::Header));
|
|
|
|
|
2003-01-29 23:59:07 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * append x_debug_filename
|
|
|
|
// ******************************************************************
|
|
|
|
memcpy(m_bzSection[i] + 0x100 + x_Xbe->m_Header.dwSizeofHeaders, x_debug_filename, 260);
|
|
|
|
|
2003-02-19 20:53:33 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * append library versions
|
|
|
|
// ******************************************************************
|
2003-04-08 03:34:05 +00:00
|
|
|
if(x_Xbe->m_LibraryVersion != 0)
|
|
|
|
memcpy(m_bzSection[i] + 0x100 + x_Xbe->m_Header.dwSizeofHeaders + 260, x_Xbe->m_LibraryVersion, sizeof(Xbe::LibraryVersion) * x_Xbe->m_Header.dwLibraryVersions);
|
2003-02-19 20:53:33 +00:00
|
|
|
|
2003-04-06 00:25:30 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * calculate TLS adjustment
|
|
|
|
// ******************************************************************
|
|
|
|
uint32 TlsAdjust = 0;
|
|
|
|
|
|
|
|
if(x_Xbe->m_TLS == 0 || OrigTLSAddr == 0)
|
|
|
|
TlsAdjust = -1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// ******************************************************************
|
|
|
|
// * necessary tls adjustment values
|
|
|
|
// ******************************************************************
|
2003-04-26 07:30:21 +00:00
|
|
|
uint32 TlsZF = OrigTLS.dwSizeofZeroFill;
|
|
|
|
uint32 TlsEA = OrigTLS.dwDataEndAddr;
|
|
|
|
uint32 TlsSA = OrigTLS.dwDataStartAddr;
|
|
|
|
|
2003-04-06 00:25:30 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * calculate tls adjustment
|
|
|
|
// ******************************************************************
|
2003-04-26 07:30:21 +00:00
|
|
|
TlsAdjust = (TlsZF - TlsSA) + TlsEA + 0x0F;
|
2003-04-06 00:25:30 +00:00
|
|
|
TlsAdjust &= 0xFFFFFFF0;
|
|
|
|
TlsAdjust += 4;
|
|
|
|
}
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * patch prolog function parameters
|
|
|
|
// ******************************************************************
|
2003-03-27 06:23:58 +00:00
|
|
|
*(uint32 *)((uint32)m_bzSection[i] + 1) = (uint32)EmuInit;
|
2003-01-26 06:18:56 +00:00
|
|
|
*(uint32 *)((uint32)m_bzSection[i] + 6) = (uint32)ep;
|
|
|
|
*(uint32 *)((uint32)m_bzSection[i] + 11) = (uint32)x_Xbe->m_Header.dwSizeofHeaders;
|
|
|
|
*(uint32 *)((uint32)m_bzSection[i] + 16) = m_SectionHeader[i].m_virtual_addr + m_OptionalHeader.m_image_base + 0x100;
|
2003-01-29 23:59:07 +00:00
|
|
|
*(uint32 *)((uint32)m_bzSection[i] + 21) = m_SectionHeader[i].m_virtual_addr + m_OptionalHeader.m_image_base + 0x100 + x_Xbe->m_Header.dwSizeofHeaders;
|
2003-04-04 04:35:00 +00:00
|
|
|
*(uint32 *)((uint32)m_bzSection[i] + 26) = x_debug_mode;
|
2003-04-08 03:34:05 +00:00
|
|
|
if(x_Xbe->m_LibraryVersion != 0)
|
|
|
|
*(uint32 *)((uint32)m_bzSection[i] + 31) = m_SectionHeader[i].m_virtual_addr + m_OptionalHeader.m_image_base + 0x100 + x_Xbe->m_Header.dwSizeofHeaders + 260;
|
|
|
|
else
|
|
|
|
*(uint32 *)((uint32)m_bzSection[i] + 31) = 0;
|
2003-04-06 00:25:30 +00:00
|
|
|
*(uint32 *)((uint32)m_bzSection[i] + 36) = TlsAdjust;
|
2003-02-07 20:44:49 +00:00
|
|
|
|
|
|
|
printf("OK\n");
|
2003-01-26 06:18:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * patch kernel thunk table
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Hijacking Kernel Imports...\n");
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
uint32 kt = x_Xbe->m_Header.dwKernelImageThunkAddr;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * decode kernel thunk address
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
if( (kt ^ XOR_KT_DEBUG) > 0x01000000)
|
|
|
|
kt ^= XOR_KT_RETAIL;
|
|
|
|
else
|
|
|
|
kt ^= XOR_KT_DEBUG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * locate section containing kernel thunk table
|
|
|
|
// ******************************************************************
|
|
|
|
for(uint32 v=0;v<x_Xbe->m_Header.dwSections;v++)
|
|
|
|
{
|
|
|
|
uint32 imag_base = m_OptionalHeader.m_image_base;
|
|
|
|
|
|
|
|
uint32 virt_addr = m_SectionHeader[v].m_virtual_addr;
|
|
|
|
uint32 virt_size = m_SectionHeader[v].m_virtual_size;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * modify kernel thunk table, if found
|
|
|
|
// ******************************************************************
|
|
|
|
if(kt >= virt_addr + imag_base && kt < virt_addr + virt_size + imag_base)
|
|
|
|
{
|
2003-02-09 08:35:33 +00:00
|
|
|
printf("EmuExe::EmuExe: Located Thunk Table in Section 0x%.04X (0x%.08X)...", v, kt);
|
2003-02-07 20:44:49 +00:00
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
uint32 *kt_tbl = (uint32*)&m_bzSection[v][kt - virt_addr - imag_base];
|
|
|
|
|
|
|
|
while(*kt_tbl != 0)
|
|
|
|
*kt_tbl++ = KernelThunkTable[*kt_tbl & 0x7FFFFFFF];
|
|
|
|
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("OK\n");
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * update imcomplete header fields
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
2003-02-07 20:44:49 +00:00
|
|
|
printf("EmuExe::EmuExe: Finalizing Exe file...");
|
|
|
|
|
2003-01-26 06:18:56 +00:00
|
|
|
// ******************************************************************
|
|
|
|
// * calculate size of code / data / image
|
|
|
|
// ******************************************************************
|
|
|
|
{
|
|
|
|
uint32 sizeof_code = 0;
|
|
|
|
uint32 sizeof_data = 0;
|
|
|
|
uint32 sizeof_undata = 0;
|
|
|
|
uint32 sizeof_image = 0;
|
|
|
|
|
|
|
|
for(uint32 v=0;v<m_Header.m_sections;v++)
|
|
|
|
{
|
|
|
|
uint32 characteristics = m_SectionHeader[v].m_characteristics;
|
|
|
|
|
|
|
|
if( (characteristics & IMAGE_SCN_MEM_EXECUTE) || (characteristics & IMAGE_SCN_CNT_CODE) )
|
|
|
|
sizeof_code += m_SectionHeader[v].m_sizeof_raw;
|
|
|
|
|
|
|
|
if( (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) )
|
|
|
|
sizeof_data += m_SectionHeader[v].m_sizeof_raw;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * calculate size of image
|
|
|
|
// ******************************************************************
|
|
|
|
sizeof_image = sizeof_undata + sizeof_data + sizeof_code + m_OptionalHeader.m_sizeof_headers;
|
|
|
|
sizeof_image = RoundUp(sizeof_image, PE_SEGM_ALIGN);
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * update optional header as necessary
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_sizeof_code = sizeof_code;
|
|
|
|
m_OptionalHeader.m_sizeof_initialized_data = sizeof_data;
|
|
|
|
m_OptionalHeader.m_sizeof_uninitialized_data = sizeof_undata;
|
|
|
|
m_OptionalHeader.m_sizeof_image = sizeof_image;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * we'll set code base as the virtual address of the first section
|
|
|
|
// ******************************************************************
|
|
|
|
m_OptionalHeader.m_code_base = m_SectionHeader[0].m_virtual_addr;
|
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * we'll set data base as the virtual address of the first section
|
|
|
|
// * that is not marked as containing code or being executable
|
|
|
|
// ******************************************************************
|
|
|
|
for(uint32 v=0;v<m_Header.m_sections;v++)
|
|
|
|
{
|
|
|
|
uint32 characteristics = m_SectionHeader[v].m_characteristics;
|
|
|
|
|
|
|
|
if( !(characteristics & IMAGE_SCN_MEM_EXECUTE) || !(characteristics & IMAGE_SCN_CNT_CODE) )
|
|
|
|
{
|
|
|
|
m_OptionalHeader.m_data_base = m_SectionHeader[v].m_virtual_addr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-02-07 20:44:49 +00:00
|
|
|
|
|
|
|
printf("OK\n");
|
2003-01-26 06:18:56 +00:00
|
|
|
}
|
2003-03-31 04:03:54 +00:00
|
|
|
|
|
|
|
// ******************************************************************
|
|
|
|
// * repair original TLS structure
|
|
|
|
// ******************************************************************
|
2003-03-31 23:22:21 +00:00
|
|
|
if(x_Xbe->m_TLS != 0 && OrigTLSAddr != 0)
|
2003-03-31 04:03:54 +00:00
|
|
|
memcpy(x_Xbe->m_TLS, &OrigTLS, sizeof(Xbe::TLS));
|
2003-01-26 06:18:56 +00:00
|
|
|
}
|