Converting everything to C++ cause I'm a masochist.

This commit is contained in:
Ben Vanik
2013-01-20 01:13:59 -08:00
parent 8a5dcbc1dd
commit ca2908db32
47 changed files with 3966 additions and 3760 deletions

View File

@@ -10,87 +10,62 @@
#include <xenia/kernel/export.h>
bool xe_kernel_export_is_implemented(const xe_kernel_export_t *kernel_export) {
if (kernel_export->flags & kXEKernelExportFlagFunction) {
if (kernel_export->function_data.impl) {
using namespace xe;
using namespace xe::kernel;
bool KernelExport::IsImplemented() {
switch (type) {
case Function:
if (function_data.impl) {
return true;
}
} else if (kernel_export->flags & kXEKernelExportFlagVariable) {
if (kernel_export->variable_data) {
break;
case Variable:
if (variable_data) {
return true;
}
break;
}
return false;
}
typedef struct {
char name[32];
xe_kernel_export_t *exports;
size_t count;
} xe_kernel_export_table_t;
#define kXEKernelExportResolverTableMaxCount 8
struct xe_kernel_export_resolver {
xe_ref_t ref;
xe_kernel_export_table_t tables[kXEKernelExportResolverTableMaxCount];
size_t table_count;
};
xe_kernel_export_resolver_ref xe_kernel_export_resolver_create() {
xe_kernel_export_resolver_ref resolver = (xe_kernel_export_resolver_ref)
xe_calloc(sizeof(xe_kernel_export_resolver));
xe_ref_init((xe_ref)resolver);
return resolver;
ExportResolver::ExportResolver() {
}
void xe_kernel_export_resolver_dealloc(xe_kernel_export_resolver_ref resolver) {
ExportResolver::~ExportResolver() {
}
xe_kernel_export_resolver_ref xe_kernel_export_resolver_retain(
xe_kernel_export_resolver_ref resolver) {
xe_ref_retain((xe_ref)resolver);
return resolver;
void ExportResolver::RegisterTable(
const char* library_name, KernelExport* exports, const size_t count) {
ExportTable table;
XEIGNORE(xestrcpya(table.name, XECOUNT(table.name), library_name));
table.exports = exports;
table.count = count;
tables_.push_back(table);
}
void xe_kernel_export_resolver_release(xe_kernel_export_resolver_ref resolver) {
xe_ref_release((xe_ref)resolver,
(xe_ref_dealloc_t)xe_kernel_export_resolver_dealloc);
}
void xe_kernel_export_resolver_register_table(
xe_kernel_export_resolver_ref resolver, const char *library_name,
xe_kernel_export_t *exports, const size_t count) {
XEASSERT(resolver->table_count + 1 < kXEKernelExportResolverTableMaxCount);
xe_kernel_export_table_t *table = &resolver->tables[resolver->table_count++];
XEIGNORE(xestrcpya(table->name, XECOUNT(table->name), library_name));
table->exports = exports;
table->count = count;
}
xe_kernel_export_t *xe_kernel_export_resolver_get_by_ordinal(
xe_kernel_export_resolver_ref resolver, const char *library_name,
const uint32_t ordinal) {
// TODO(benvanik): binary search everything.
for (size_t n = 0; n < resolver->table_count; n++) {
const xe_kernel_export_table_t *table = &resolver->tables[n];
if (!xestrcmpa(library_name, table->name)) {
// TODO(benvanik): binary search table.
for (size_t m = 0; m < table->count; m++) {
if (table->exports[m].ordinal == ordinal) {
return &table->exports[m];
KernelExport* ExportResolver::GetExportByOrdinal(const char* library_name,
const uint32_t ordinal) {
for (std::vector<ExportTable>::iterator it = tables_.begin();
it != tables_.end(); ++it) {
if (!xestrcmp(library_name, it->name)) {
// TODO(benvanik): binary search?
for (size_t n = 0; n < it->count; n++) {
if (it->exports[n].ordinal == ordinal) {
return &it->exports[n];
}
}
return NULL;
}
}
return NULL;
}
xe_kernel_export_t *xe_kernel_export_resolver_get_by_name(
xe_kernel_export_resolver_ref resolver, const char *library_name,
const char *name) {
KernelExport* ExportResolver::GetExportByName(const char* library_name,
const char* name) {
// TODO(benvanik): lookup by name.
XEASSERTALWAYS();
return NULL;
}

View File

@@ -1,164 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <xenia/kernel.h>
#include "kernel/modules/modules.h"
typedef struct xe_kernel {
xe_ref_t ref;
xe_kernel_options_t options;
xe_pal_ref pal;
xe_memory_ref memory;
xe_cpu_ref cpu;
xe_kernel_export_resolver_ref export_resolver;
struct {
xe_xam_ref xam;
xe_xbdm_ref xbdm;
xe_xboxkrnl_ref xboxkrnl;
} modules;
} xe_kernel_t;
xe_kernel_ref xe_kernel_create(xe_pal_ref pal, xe_cpu_ref cpu,
xe_kernel_options_t options) {
xe_kernel_ref kernel = (xe_kernel_ref)xe_calloc(sizeof(xe_kernel));
xe_ref_init((xe_ref)kernel);
xe_copy_struct(&kernel->options, &options, sizeof(xe_kernel_options_t));
kernel->pal = xe_pal_retain(pal);
kernel->memory = xe_cpu_get_memory(cpu);
kernel->cpu = xe_cpu_retain(cpu);
kernel->export_resolver = xe_kernel_export_resolver_create();
kernel->modules.xam =
xe_xam_create(kernel->pal, kernel->memory, kernel->export_resolver);
kernel->modules.xbdm =
xe_xbdm_create(kernel->pal, kernel->memory, kernel->export_resolver);
kernel->modules.xboxkrnl =
xe_xboxkrnl_create(kernel->pal, kernel->memory, kernel->export_resolver);
return kernel;
}
void xe_kernel_dealloc(xe_kernel_ref kernel) {
xe_xboxkrnl_release(kernel->modules.xboxkrnl);
xe_xbdm_release(kernel->modules.xbdm);
xe_xam_release(kernel->modules.xam);
xe_kernel_export_resolver_release(kernel->export_resolver);
xe_cpu_release(kernel->cpu);
xe_memory_release(kernel->memory);
xe_pal_release(kernel->pal);
}
xe_kernel_ref xe_kernel_retain(xe_kernel_ref kernel) {
xe_ref_retain((xe_ref)kernel);
return kernel;
}
void xe_kernel_release(xe_kernel_ref kernel) {
xe_ref_release((xe_ref)kernel, (xe_ref_dealloc_t)xe_kernel_dealloc);
}
xe_pal_ref xe_kernel_get_pal(xe_kernel_ref kernel) {
return xe_pal_retain(kernel->pal);
}
xe_memory_ref xe_kernel_get_memory(xe_kernel_ref kernel) {
return xe_memory_retain(kernel->memory);
}
xe_cpu_ref xe_kernel_get_cpu(xe_kernel_ref kernel) {
return xe_cpu_retain(kernel->cpu);
}
const xechar_t *xe_kernel_get_command_line(xe_kernel_ref kernel) {
return kernel->options.command_line;
}
xe_kernel_export_resolver_ref xe_kernel_get_export_resolver(
xe_kernel_ref kernel) {
return xe_kernel_export_resolver_retain(kernel->export_resolver);
}
xe_module_ref xe_kernel_load_module(xe_kernel_ref kernel,
const xechar_t *path) {
xe_module_ref module = xe_kernel_get_module(kernel, path);
if (module) {
return module;
}
// TODO(benvanik): map file from filesystem
xe_mmap_ref mmap = xe_mmap_open(kernel->pal, kXEFileModeRead, path, 0, 0);
if (!mmap) {
return NULL;
}
void *addr = xe_mmap_get_addr(mmap);
size_t length = xe_mmap_get_length(mmap);
xe_module_options_t options;
xe_zero_struct(&options, sizeof(xe_module_options_t));
XEIGNORE(xestrcpy(options.path, XECOUNT(options.path), path));
module = xe_module_load(kernel->memory, kernel->export_resolver,
addr, length, options);
// TODO(benvanik): retain memory somehow? is it needed?
xe_mmap_release(mmap);
if (!module) {
return NULL;
}
// Prepare the module.
XEEXPECTZERO(xe_cpu_prepare_module(kernel->cpu, module,
kernel->export_resolver));
// Stash in modules list (takes reference).
// TODO(benvanik): stash in list.
return xe_module_retain(module);
XECLEANUP:
xe_module_release(module);
return NULL;
}
void xe_kernel_launch_module(xe_kernel_ref kernel, xe_module_ref module) {
//const xe_xex2_header_t *xex_header = xe_module_get_xex_header(module);
// TODO(benvanik): set as main module/etc
// xekXexExecutableModuleHandle = xe_module_get_handle(module);
// XEEXPECTTRUE(XECPUPrepareModule(XEGetCPU(), module->xex, module->pe, module->address_space, module->address_space_size));
// Setup the heap (and TLS?).
// xex_header->exe_heap_size;
// Launch thread.
// XHANDLE thread_handle;
// XDWORD thread_id;
// XBOOL result = xekExCreateThread(&thread_handle, xex_header->exe_stack_size, &thread_id, NULL, (void*)xex_header->exe_entry_point, NULL, 0);
// Wait until thread completes.
// XLARGE_INTEGER timeout = XINFINITE;
// xekNtWaitForSingleObjectEx(thread_handle, TRUE, &timeout);
}
xe_module_ref xe_kernel_get_module(xe_kernel_ref kernel, const xechar_t *path) {
return NULL;
}
void xe_kernel_unload_module(xe_kernel_ref kernel, xe_module_ref module) {
//
}

View File

@@ -10,8 +10,8 @@
#ifndef XENIA_KERNEL_MODULES_H_
#define XENIA_KERNEL_MODULES_H_
#include "kernel/modules/xam/xam.h"
#include "kernel/modules/xbdm/xbdm.h"
#include "kernel/modules/xboxkrnl/xboxkrnl.h"
#include "kernel/modules/xam/xam_module.h"
#include "kernel/modules/xbdm/xbdm_module.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_module.h"
#endif // XENIA_KERNEL_MODULES_H_

View File

@@ -1,6 +1,6 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'xam.cc',
'xam_module.cc',
],
}

View File

@@ -1,42 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "kernel/modules/xam/xam.h"
#include "kernel/modules/xam/xam_table.h"
struct xe_xam {
xe_ref_t ref;
};
xe_xam_ref xe_xam_create(
xe_pal_ref pal, xe_memory_ref memory,
xe_kernel_export_resolver_ref export_resolver) {
xe_xam_ref module = (xe_xam_ref)xe_calloc(sizeof(xe_xam));
xe_ref_init((xe_ref)module);
xe_kernel_export_resolver_register_table(export_resolver, "xam.xex",
xe_xam_export_table, XECOUNT(xe_xam_export_table));
return module;
}
void xe_xam_dealloc(xe_xam_ref module) {
}
xe_xam_ref xe_xam_retain(xe_xam_ref module) {
xe_ref_retain((xe_ref)module);
return module;
}
void xe_xam_release(xe_xam_ref module) {
xe_ref_release((xe_ref)module, (xe_ref_dealloc_t)xe_xam_dealloc);
}

View File

@@ -0,0 +1,28 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "kernel/modules/xam/xam_module.h"
#include "kernel/modules/xam/xam_table.h"
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::xam;
XamModule::XamModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver) :
KernelModule(pal, memory, resolver) {
resolver->RegisterTable(
"xam.xex", xam_export_table, XECOUNT(xam_export_table));
}
XamModule::~XamModule() {
}

View File

@@ -14,18 +14,25 @@
#include <xenia/core.h>
#include <xenia/kernel/export.h>
#include <xenia/kernel/kernel_module.h>
struct xe_xam;
typedef struct xe_xam* xe_xam_ref;
namespace xe {
namespace kernel {
namespace xam {
xe_xam_ref xe_xam_create(
xe_pal_ref pal, xe_memory_ref memory,
xe_kernel_export_resolver_ref export_resolver);
class XamModule : public KernelModule {
public:
XamModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver);
virtual ~XamModule();
};
xe_xam_ref xe_xam_retain(xe_xam_ref module);
void xe_xam_release(xe_xam_ref module);
} // namespace xam
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_MODULES_XAM_H_

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'xbdm.cc',
'xbdm_module.cc',
],
}

View File

@@ -1,42 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "kernel/modules/xbdm/xbdm.h"
#include "kernel/modules/xbdm/xbdm_table.h"
struct xe_xbdm {
xe_ref_t ref;
};
xe_xbdm_ref xe_xbdm_create(
xe_pal_ref pal, xe_memory_ref memory,
xe_kernel_export_resolver_ref export_resolver) {
xe_xbdm_ref module = (xe_xbdm_ref)xe_calloc(sizeof(xe_xbdm));
xe_ref_init((xe_ref)module);
xe_kernel_export_resolver_register_table(export_resolver, "xbdm.exe",
xe_xbdm_export_table, XECOUNT(xe_xbdm_export_table));
return module;
}
void xe_xbdm_dealloc(xe_xbdm_ref module) {
}
xe_xbdm_ref xe_xbdm_retain(xe_xbdm_ref module) {
xe_ref_retain((xe_ref)module);
return module;
}
void xe_xbdm_release(xe_xbdm_ref module) {
xe_ref_release((xe_ref)module, (xe_ref_dealloc_t)xe_xbdm_dealloc);
}

View File

@@ -0,0 +1,28 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "kernel/modules/xbdm/xbdm_module.h"
#include "kernel/modules/xbdm/xbdm_table.h"
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::xbdm;
XbdmModule::XbdmModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver) :
KernelModule(pal, memory, resolver) {
resolver->RegisterTable(
"xbdm.exe", xbdm_export_table, XECOUNT(xbdm_export_table));
}
XbdmModule::~XbdmModule() {
}

View File

@@ -7,25 +7,32 @@
******************************************************************************
*/
#ifndef XENIA_KERNEL_MODULES_XBOXKRNL_H_
#define XENIA_KERNEL_MODULES_XBOXKRNL_H_
#ifndef XENIA_KERNEL_MODULES_XBDM_MODULE_H_
#define XENIA_KERNEL_MODULES_XBDM_MODULE_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/export.h>
#include <xenia/kernel/kernel_module.h>
struct xe_xboxkrnl;
typedef struct xe_xboxkrnl* xe_xboxkrnl_ref;
namespace xe {
namespace kernel {
namespace xbdm {
xe_xboxkrnl_ref xe_xboxkrnl_create(
xe_pal_ref pal, xe_memory_ref memory,
xe_kernel_export_resolver_ref export_resolver);
xe_xboxkrnl_ref xe_xboxkrnl_retain(xe_xboxkrnl_ref module);
void xe_xboxkrnl_release(xe_xboxkrnl_ref module);
class XbdmModule : public KernelModule {
public:
XbdmModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver);
virtual ~XbdmModule();
};
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_H_
} // namespace xbdm
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_MODULES_XBDM_MODULE_H_

View File

@@ -13,14 +13,24 @@
#include <xenia/kernel/export.h>
namespace xe {
namespace kernel {
namespace xbdm {
#define FLAG(t) kXEKernelExportFlag##t
static xe_kernel_export_t xe_xbdm_export_table[] = {
static KernelExport xbdm_export_table[] = {
};
#undef FLAG
} // namespace xbdm
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_MODULES_XBDM_TABLE_H_

View File

@@ -1,6 +1,6 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'xboxkrnl.cc',
'xboxkrnl_module.cc',
],
}

View File

@@ -1,42 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "kernel/modules/xboxkrnl/xboxkrnl.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_table.h"
struct xe_xboxkrnl {
xe_ref_t ref;
};
xe_xboxkrnl_ref xe_xboxkrnl_create(
xe_pal_ref pal, xe_memory_ref memory,
xe_kernel_export_resolver_ref export_resolver) {
xe_xboxkrnl_ref module = (xe_xboxkrnl_ref)xe_calloc(sizeof(xe_xboxkrnl));
xe_ref_init((xe_ref)module);
xe_kernel_export_resolver_register_table(export_resolver, "xboxkrnl.exe",
xe_xboxkrnl_export_table, XECOUNT(xe_xboxkrnl_export_table));
return module;
}
void xe_xboxkrnl_dealloc(xe_xboxkrnl_ref module) {
}
xe_xboxkrnl_ref xe_xboxkrnl_retain(xe_xboxkrnl_ref module) {
xe_ref_retain((xe_ref)module);
return module;
}
void xe_xboxkrnl_release(xe_xboxkrnl_ref module) {
xe_ref_release((xe_ref)module, (xe_ref_dealloc_t)xe_xboxkrnl_dealloc);
}

View File

@@ -0,0 +1,28 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "kernel/modules/xboxkrnl/xboxkrnl_module.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_table.h"
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::xboxkrnl;
XboxkrnlModule::XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver) :
KernelModule(pal, memory, resolver) {
resolver->RegisterTable(
"xboxkrnl.exe", xboxkrnl_export_table, XECOUNT(xboxkrnl_export_table));
}
XboxkrnlModule::~XboxkrnlModule() {
}

View File

@@ -7,25 +7,32 @@
******************************************************************************
*/
#ifndef XENIA_KERNEL_MODULES_XBDM_H_
#define XENIA_KERNEL_MODULES_XBDM_H_
#ifndef XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
#define XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/export.h>
#include <xenia/kernel/kernel_module.h>
struct xe_xbdm;
typedef struct xe_xbdm* xe_xbdm_ref;
namespace xe {
namespace kernel {
namespace xboxkrnl {
xe_xbdm_ref xe_xbdm_create(
xe_pal_ref pal, xe_memory_ref memory,
xe_kernel_export_resolver_ref export_resolver);
xe_xbdm_ref xe_xbdm_retain(xe_xbdm_ref module);
void xe_xbdm_release(xe_xbdm_ref module);
class XboxkrnlModule : public KernelModule {
public:
XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver);
virtual ~XboxkrnlModule();
};
#endif // XENIA_KERNEL_MODULES_XBDM_H_
} // namespace xboxkrnl
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_

File diff suppressed because it is too large Load Diff

139
src/kernel/runtime.cc Normal file
View File

@@ -0,0 +1,139 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <xenia/kernel/runtime.h>
#include "kernel/modules/modules.h"
using namespace xe;
using namespace xe::kernel;
Runtime::Runtime(xe_pal_ref pal, shared_ptr<cpu::Processor> processor,
const xechar_t* command_line) {
pal_ = xe_pal_retain(pal);
memory_ = processor->memory();
processor_ = processor;
XEIGNORE(xestrcpy(command_line_, XECOUNT(command_line_), command_line));
export_resolver_ = shared_ptr<ExportResolver>(new ExportResolver());
kernel_modules_.push_back(
new xboxkrnl::XboxkrnlModule(pal_, memory_, export_resolver_));
kernel_modules_.push_back(
new xbdm::XbdmModule(pal_, memory_, export_resolver_));
kernel_modules_.push_back(
new xam::XamModule(pal_, memory_, export_resolver_));
}
Runtime::~Runtime() {
for (std::map<const xechar_t*, UserModule*>::iterator it =
user_modules_.begin(); it != user_modules_.end(); ++it) {
delete it->second;
}
for (std::vector<KernelModule*>::iterator it = kernel_modules_.begin();
it != kernel_modules_.end(); ++it) {
delete *it;
}
xe_memory_release(memory_);
xe_pal_release(pal_);
}
xe_pal_ref Runtime::pal() {
return xe_pal_retain(pal_);
}
xe_memory_ref Runtime::memory() {
return xe_memory_retain(memory_);
}
shared_ptr<cpu::Processor> Runtime::processor() {
return processor_;
}
shared_ptr<ExportResolver> Runtime::export_resolver() {
return export_resolver_;
}
const xechar_t* Runtime::command_line() {
return command_line_;
}
int Runtime::LoadModule(const xechar_t* path) {
if (GetModule(path)) {
return 0;
}
// TODO(benvanik): map file from filesystem
xe_mmap_ref mmap = xe_mmap_open(pal_, kXEFileModeRead, path, 0, 0);
if (!mmap) {
return NULL;
}
void* addr = xe_mmap_get_addr(mmap);
size_t length = xe_mmap_get_length(mmap);
UserModule* module = new UserModule(memory_);
int result_code = module->Load(addr, length, path);
// TODO(benvanik): retain memory somehow? is it needed?
xe_mmap_release(mmap);
if (result_code) {
delete module;
return 1;
}
// Prepare the module.
XEEXPECTZERO(processor_->PrepareModule(module, export_resolver_));
// Stash in modules list (takes reference).
user_modules_.insert(std::pair<const xechar_t*, UserModule*>(path, module));
return 0;
XECLEANUP:
delete module;
return 1;
}
void Runtime::LaunchModule(UserModule* user_module) {
//const xe_xex2_header_t *xex_header = xe_module_get_xex_header(module);
// TODO(benvanik): set as main module/etc
// xekXexExecutableModuleHandle = xe_module_get_handle(module);
// XEEXPECTTRUE(XECPUPrepareModule(XEGetCPU(), module->xex, module->pe, module->address_space, module->address_space_size));
// Setup the heap (and TLS?).
// xex_header->exe_heap_size;
// Launch thread.
// XHANDLE thread_handle;
// XDWORD thread_id;
// XBOOL result = xekExCreateThread(&thread_handle, xex_header->exe_stack_size, &thread_id, NULL, (void*)xex_header->exe_entry_point, NULL, 0);
// Wait until thread completes.
// XLARGE_INTEGER timeout = XINFINITE;
// xekNtWaitForSingleObjectEx(thread_handle, TRUE, &timeout);
}
UserModule* Runtime::GetModule(const xechar_t* path) {
std::map<const xechar_t*, UserModule*>::iterator it =
user_modules_.find(path);
if (it != user_modules_.end()) {
return it->second;
}
return NULL;
}
void Runtime::UnloadModule(UserModule* user_module) {
// TODO(benvanik): unload module
XEASSERTALWAYS();
}

View File

@@ -2,8 +2,8 @@
{
'sources': [
'export.cc',
'kernel.cc',
'module.cc',
'runtime.cc',
'user_module.cc',
'xex2.cc',
],

View File

@@ -7,97 +7,72 @@
******************************************************************************
*/
#include <xenia/kernel/module.h>
#include <xenia/kernel/user_module.h>
#include <third_party/pe/pe_image.h>
#define kXEModuleMaxSectionCount 32
typedef struct xe_module {
xe_ref_t ref;
xe_module_options_t options;
xechar_t name[256];
xe_memory_ref memory;
xe_kernel_export_resolver_ref export_resolver;
uint32_t handle;
xe_xex2_ref xex;
size_t section_count;
xe_module_pe_section_t sections[kXEModuleMaxSectionCount];
} xe_module_t;
using namespace xe;
using namespace kernel;
int xe_module_load_pe(xe_module_ref module);
UserModule::UserModule(xe_memory_ref memory) {
memory_ = xe_memory_retain(memory);
xex_ = NULL;
}
xe_module_ref xe_module_load(xe_memory_ref memory,
xe_kernel_export_resolver_ref export_resolver,
const void *addr, const size_t length,
xe_module_options_t options) {
xe_module_ref module = (xe_module_ref)xe_calloc(sizeof(xe_module));
xe_ref_init((xe_ref)module);
xe_copy_struct(&module->options, &options, sizeof(xe_module_options_t));
xechar_t *slash = xestrrchr(options.path, '/');
if (slash) {
xestrcpy(module->name, XECOUNT(module->name), slash + 1);
UserModule::~UserModule() {
for (std::vector<PESection*>::iterator it = sections_.begin();
it != sections_.end(); ++it) {
delete *it;
}
module->memory = xe_memory_retain(memory);
module->export_resolver = xe_kernel_export_resolver_retain(export_resolver);
xe_xex2_release(xex_);
xe_memory_release(memory_);
}
int UserModule::Load(const void* addr, const size_t length,
const xechar_t* path) {
XEIGNORE(xestrcpy(path_, XECOUNT(path_), path));
const xechar_t *slash = xestrrchr(path, '/');
if (slash) {
XEIGNORE(xestrcpy(name_, XECOUNT(name_), slash + 1));
}
xe_xex2_options_t xex_options;
module->xex = xe_xex2_load(memory, addr, length, xex_options);
XEEXPECTNOTNULL(module->xex);
xex_ = xe_xex2_load(memory_, addr, length, xex_options);
XEEXPECTNOTNULL(xex_);
XEEXPECTZERO(xe_module_load_pe(module));
XEEXPECTZERO(LoadPE());
return module;
return 0;
XECLEANUP:
xe_module_release(module);
return NULL;
return 1;
}
void xe_module_dealloc(xe_module_ref module) {
xe_kernel_export_resolver_release(module->export_resolver);
xe_memory_release(module->memory);
const xechar_t* UserModule::path() {
return path_;
}
xe_module_ref xe_module_retain(xe_module_ref module) {
xe_ref_retain((xe_ref)module);
return module;
const xechar_t* UserModule::name() {
return name_;
}
void xe_module_release(xe_module_ref module) {
xe_ref_release((xe_ref)module, (xe_ref_dealloc_t)xe_module_dealloc);
uint32_t UserModule::handle() {
return handle_;
}
const xechar_t *xe_module_get_path(xe_module_ref module) {
return module->options.path;
xe_xex2_ref UserModule::xex() {
return xe_xex2_retain(xex_);
}
const xechar_t *xe_module_get_name(xe_module_ref module) {
return module->name;
const xe_xex2_header_t* UserModule::xex_header() {
return xe_xex2_get_header(xex_);
}
uint32_t xe_module_get_handle(xe_module_ref module) {
return module->handle;
}
xe_xex2_ref xe_module_get_xex(xe_module_ref module) {
return xe_xex2_retain(module->xex);
}
const xe_xex2_header_t *xe_module_get_xex_header(xe_module_ref module) {
return xe_xex2_get_header(module->xex);
}
void *xe_module_get_proc_address(xe_module_ref module, const uint32_t ordinal) {
void* UserModule::GetProcAddress(const uint32_t ordinal) {
XEASSERTALWAYS();
return NULL;
}
@@ -116,10 +91,10 @@ typedef struct IMAGE_XBOX_RUNTIME_FUNCTION_ENTRY_t {
};
} IMAGE_XBOX_RUNTIME_FUNCTION_ENTRY;
int xe_module_load_pe(xe_module_ref module) {
const xe_xex2_header_t *xex_header = xe_xex2_get_header(module->xex);
uint8_t *mem = (uint8_t*)xe_memory_addr(module->memory, 0);
const uint8_t *p = mem + xex_header->exe_address;
int UserModule::LoadPE() {
const xe_xex2_header_t* xex_header = xe_xex2_get_header(xex_);
uint8_t* mem = xe_memory_addr(memory_, 0);
const uint8_t* p = mem + xex_header->exe_address;
// Verify DOS signature (MZ).
const IMAGE_DOS_HEADER* doshdr = (const IMAGE_DOS_HEADER*)p;
@@ -172,14 +147,6 @@ int xe_module_load_pe(xe_module_ref module) {
// IAT Import Address Table ptr
//opthdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_X].VirtualAddress / .Size
// Verify section count not overrun.
// NOTE: if this ever asserts, change to a dynamic section list.
XEASSERT(filehdr->NumberOfSections <= kXEModuleMaxSectionCount);
if (filehdr->NumberOfSections > kXEModuleMaxSectionCount) {
return 1;
}
module->section_count = filehdr->NumberOfSections;
// Quick scan to determine bounds of sections.
size_t upper_address = 0;
const IMAGE_SECTION_HEADER* sechdr = IMAGE_FIRST_SECTION(nthdr);
@@ -192,7 +159,7 @@ int xe_module_load_pe(xe_module_ref module) {
// Setup/load sections.
sechdr = IMAGE_FIRST_SECTION(nthdr);
for (size_t n = 0; n < filehdr->NumberOfSections; n++, sechdr++) {
xe_module_pe_section_t *section = &module->sections[n];
PESection* section = (PESection*)xe_calloc(sizeof(PESection));
xe_copy_memory(section->name, sizeof(section->name),
sechdr->Name, sizeof(sechdr->Name));
section->name[8] = 0;
@@ -201,6 +168,7 @@ int xe_module_load_pe(xe_module_ref module) {
section->address = xex_header->exe_address + sechdr->VirtualAddress;
section->size = sechdr->Misc.VirtualSize;
section->flags = sechdr->Characteristics;
sections_.push_back(section);
}
//DumpTLSDirectory(pImageBase, pNTHeader, (PIMAGE_TLS_DIRECTORY32)0);
@@ -208,48 +176,45 @@ int xe_module_load_pe(xe_module_ref module) {
return 0;
}
xe_module_pe_section_t *xe_module_get_section(xe_module_ref module,
const char *name) {
for (size_t n = 0; n < module->section_count; n++) {
if (xestrcmpa(module->sections[n].name, name) == 0) {
return &module->sections[n];
PESection* UserModule::GetSection(const char *name) {
for (std::vector<PESection*>::iterator it = sections_.begin();
it != sections_.end(); ++it) {
if (!xestrcmpa((*it)->name, name)) {
return *it;
}
}
return NULL;
}
int xe_module_get_method_hints(xe_module_ref module,
xe_module_pe_method_info_t **out_method_infos,
size_t *out_method_info_count) {
uint8_t *mem = (uint8_t*)xe_memory_addr(module->memory, 0);
int UserModule::GetMethodHints(PEMethodInfo** out_method_infos,
size_t* out_method_info_count) {
uint8_t* mem = xe_memory_addr(memory_, 0);
*out_method_infos = NULL;
*out_method_info_count = 0;
const IMAGE_XBOX_RUNTIME_FUNCTION_ENTRY *entry = NULL;
const IMAGE_XBOX_RUNTIME_FUNCTION_ENTRY* entry = NULL;
// Find pdata, which contains the exception handling entries.
xe_module_pe_section_t *pdata = xe_module_get_section(module, ".pdata");
PESection* pdata = GetSection(".pdata");
if (!pdata) {
// No exception data to go on.
return 0;
}
// Resolve.
const uint8_t *p = mem + pdata->address;
const uint8_t* p = mem + pdata->address;
// Entry count = pdata size / sizeof(entry).
const size_t entry_count =
pdata->size / sizeof(IMAGE_XBOX_RUNTIME_FUNCTION_ENTRY);
if (entry_count == 0) {
size_t entry_count = pdata->size / sizeof(IMAGE_XBOX_RUNTIME_FUNCTION_ENTRY);
if (!entry_count) {
// Empty?
return 0;
}
// Allocate output.
xe_module_pe_method_info_t *method_infos =
(xe_module_pe_method_info_t*)xe_calloc(
entry_count * sizeof(xe_module_pe_method_info_t));
PEMethodInfo* method_infos = (PEMethodInfo*)xe_calloc(
entry_count * sizeof(PEMethodInfo));
XEEXPECTNOTNULL(method_infos);
// Parse entries.
@@ -258,7 +223,7 @@ int xe_module_get_method_hints(xe_module_ref module,
entry = (const IMAGE_XBOX_RUNTIME_FUNCTION_ENTRY*)p;
IMAGE_XBOX_RUNTIME_FUNCTION_ENTRY temp_entry;
for (size_t n = 0; n < entry_count; n++, entry++) {
xe_module_pe_method_info_t *method_info = &method_infos[n];
PEMethodInfo* method_info = &method_infos[n];
method_info->address = XESWAP32BE(entry->FuncStart);
// The bitfield needs to be swapped by hand.
@@ -278,12 +243,12 @@ XECLEANUP:
return 1;
}
void xe_module_dump(xe_module_ref module) {
//const uint8_t *mem = (const uint8_t*)xe_memory_addr(module->memory, 0);
const xe_xex2_header_t *header = xe_xex2_get_header(module->xex);
void UserModule::Dump(ExportResolver* export_resolver) {
//const uint8_t *mem = (const uint8_t*)xe_memory_addr(memory_, 0);
const xe_xex2_header_t* header = xe_xex2_get_header(xex_);
// XEX info.
printf("Module %s:\n\n", module->options.path);
printf("Module %s:\n\n", path_);
printf(" Module Flags: %.8X\n", header->module_flags);
printf(" System Flags: %.8X\n", header->system_flags);
printf("\n");
@@ -320,11 +285,11 @@ void xe_module_dump(xe_module_ref module) {
printf(" Slot Count: %d\n", header->tls_info.slot_count);
printf(" Data Size: %db\n", header->tls_info.data_size);
printf(" Address: %.8X, %db\n", header->tls_info.raw_data_address,
header->tls_info.raw_data_size);
header->tls_info.raw_data_size);
printf("\n");
printf(" Headers:\n");
for (size_t n = 0; n < header->header_count; n++) {
const xe_xex2_opt_header_t *opt_header = &header->headers[n];
const xe_xex2_opt_header_t* opt_header = &header->headers[n];
printf(" %.8X (%.8X, %4db) %.8X = %11d\n",
opt_header->key, opt_header->offset, opt_header->length,
opt_header->value, opt_header->value);
@@ -334,14 +299,14 @@ void xe_module_dump(xe_module_ref module) {
// Resources.
printf("Resources:\n");
printf(" %.8X, %db\n", header->resource_info.address,
header->resource_info.size);
header->resource_info.size);
printf(" TODO\n");
printf("\n");
// Section info.
printf("Sections:\n");
for (size_t n = 0, i = 0; n < header->section_count; n++) {
const xe_xex2_section_t *section = &header->sections[n];
const xe_xex2_section_t* section = &header->sections[n];
const char* type = "UNKNOWN";
switch (section->info.type) {
case XEX_SECTION_CODE:
@@ -354,10 +319,10 @@ void xe_module_dump(xe_module_ref module) {
type = "RODATA ";
break;
}
const size_t start_address = header->exe_address +
(i * xe_xex2_section_length);
const size_t end_address = start_address + (section->info.page_count *
xe_xex2_section_length);
const size_t start_address =
header->exe_address + (i * xe_xex2_section_length);
const size_t end_address =
start_address + (section->info.page_count * xe_xex2_section_length);
printf(" %3d %s %3d pages %.8X - %.8X (%d bytes)\n",
(int)n, type, section->info.page_count, (int)start_address,
(int)end_address, section->info.page_count * xe_xex2_section_length);
@@ -369,7 +334,8 @@ void xe_module_dump(xe_module_ref module) {
printf("Static Libraries:\n");
for (size_t n = 0; n < header->static_library_count; n++) {
const xe_xex2_static_library_t *library = &header->static_libraries[n];
printf(" %-8s : %d.%d.%d.%d\n", library->name, library->major,
printf(" %-8s : %d.%d.%d.%d\n",
library->name, library->major,
library->minor, library->build, library->qfe);
}
printf("\n");
@@ -377,11 +343,11 @@ void xe_module_dump(xe_module_ref module) {
// Imports.
printf("Imports:\n");
for (size_t n = 0; n < header->import_library_count; n++) {
const xe_xex2_import_library_t *library = &header->import_libraries[n];
const xe_xex2_import_library_t* library = &header->import_libraries[n];
xe_xex2_import_info_t* import_infos;
size_t import_info_count;
if (!xe_xex2_get_import_infos(module->xex, library,
if (!xe_xex2_get_import_infos(xex_, library,
&import_infos, &import_info_count)) {
printf(" %s - %d imports\n", library->name, (int)import_info_count);
printf(" Version: %d.%d.%d.%d\n",
@@ -398,13 +364,12 @@ void xe_module_dump(xe_module_ref module) {
int impl_count = 0;
int unimpl_count = 0;
for (size_t m = 0; m < import_info_count; m++) {
const xe_xex2_import_info_t *info = &import_infos[m];
const xe_kernel_export_t *kernel_export =
xe_kernel_export_resolver_get_by_ordinal(
module->export_resolver, library->name, info->ordinal);
const xe_xex2_import_info_t* info = &import_infos[m];
KernelExport* kernel_export =
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
if (kernel_export) {
known_count++;
if (xe_kernel_export_is_implemented(kernel_export)) {
if (kernel_export->IsImplemented()) {
impl_count++;
}
} else {
@@ -423,15 +388,14 @@ void xe_module_dump(xe_module_ref module) {
// Listing.
for (size_t m = 0; m < import_info_count; m++) {
const xe_xex2_import_info_t *info = &import_infos[m];
const xe_kernel_export_t *kernel_export =
xe_kernel_export_resolver_get_by_ordinal(
module->export_resolver, library->name, info->ordinal);
const xe_xex2_import_info_t* info = &import_infos[m];
KernelExport* kernel_export = export_resolver->GetExportByOrdinal(
library->name, info->ordinal);
const char *name = "UNKNOWN";
bool implemented = false;
if (kernel_export) {
name = kernel_export->name;
implemented = xe_kernel_export_is_implemented(kernel_export);
implemented = kernel_export->IsImplemented();
}
if (info->thunk_address) {
printf(" F %.8X %.8X %.3X (%3d) %s %s\n",