Refactoring to allow for raw binary loading.

This commit is contained in:
Ben Vanik 2013-01-27 12:48:10 -08:00
parent 26d5df0d38
commit bba99d4a22
14 changed files with 378 additions and 231 deletions

View File

@ -35,7 +35,8 @@ class ModuleGenerator {
public:
ModuleGenerator(
xe_memory_ref memory, kernel::ExportResolver* export_resolver,
kernel::UserModule* module, sdb::SymbolDatabase* sdb,
const char* module_name, const char* module_path,
sdb::SymbolDatabase* sdb,
llvm::LLVMContext* context, llvm::Module* gen_module);
~ModuleGenerator();
@ -61,7 +62,8 @@ private:
xe_memory_ref memory_;
kernel::ExportResolver* export_resolver_;
kernel::UserModule* module_;
char* module_name_;
char* module_path_;
sdb::SymbolDatabase* sdb_;
llvm::LLVMContext* context_;

View File

@ -41,22 +41,25 @@ class ExecModule {
public:
ExecModule(
xe_memory_ref memory, shared_ptr<kernel::ExportResolver> export_resolver,
kernel::UserModule* user_module,
const char* module_name, const char* module_path,
shared_ptr<llvm::ExecutionEngine>& engine);
~ExecModule();
int Prepare();
int PrepareUserModule(kernel::UserModule* user_module);
int PrepareRawBinary(uint32_t start_address, uint32_t end_address);
void Dump();
private:
int Prepare();
int InjectGlobals();
int Init();
int Uninit();
xe_memory_ref memory_;
shared_ptr<kernel::ExportResolver> export_resolver_;
kernel::UserModule* module_;
char* module_name_;
char* module_path_;
shared_ptr<llvm::ExecutionEngine> engine_;
shared_ptr<sdb::SymbolDatabase> sdb_;
shared_ptr<llvm::LLVMContext> context_;

View File

@ -38,6 +38,9 @@ public:
int Setup();
int PrepareModule(const char* module_name, const char* module_path,
uint32_t start_address, uint32_t end_address,
shared_ptr<kernel::ExportResolver> export_resolver);
int PrepareModule(kernel::UserModule* user_module,
shared_ptr<kernel::ExportResolver> export_resolver);

View File

@ -142,11 +142,10 @@ public:
class SymbolDatabase {
public:
SymbolDatabase(xe_memory_ref memory, kernel::ExportResolver* export_resolver,
kernel::UserModule* module);
~SymbolDatabase();
SymbolDatabase(xe_memory_ref memory, kernel::ExportResolver* export_resolver);
virtual ~SymbolDatabase();
int Analyze();
virtual int Analyze();
ExceptionEntrySymbol* GetOrInsertExceptionEntry(uint32_t address);
FunctionSymbol* GetOrInsertFunction(uint32_t address);
@ -161,24 +160,21 @@ public:
void Dump();
void DumpFunctionBlocks(FunctionSymbol* fn);
private:
protected:
typedef std::map<uint32_t, Symbol*> SymbolMap;
typedef std::list<FunctionSymbol*> FunctionList;
int FindGplr();
int AddImports(const xe_xex2_import_library_t *library);
int AddMethodHints();
int AnalyzeFunction(FunctionSymbol* fn);
int CompleteFunctionGraph(FunctionSymbol* fn);
bool FillHoles();
int FlushQueue();
bool IsValueInTextRange(uint32_t value);
bool IsRestGprLr(uint32_t addr);
virtual uint32_t GetEntryPoint() = 0;
virtual bool IsValueInTextRange(uint32_t value) = 0;
xe_memory_ref memory_;
kernel::ExportResolver* export_resolver_;
kernel::UserModule* module_;
size_t function_count_;
size_t variable_count_;
SymbolMap symbols_;
@ -186,6 +182,43 @@ private:
};
class RawSymbolDatabase : public SymbolDatabase {
public:
RawSymbolDatabase(xe_memory_ref memory,
kernel::ExportResolver* export_resolver,
uint32_t start_address, uint32_t end_address);
virtual ~RawSymbolDatabase();
private:
virtual uint32_t GetEntryPoint();
virtual bool IsValueInTextRange(uint32_t value);
uint32_t start_address_;
uint32_t end_address_;
};
class XexSymbolDatabase : public SymbolDatabase {
public:
XexSymbolDatabase(xe_memory_ref memory,
kernel::ExportResolver* export_resolver,
kernel::UserModule* module);
virtual ~XexSymbolDatabase();
virtual int Analyze();
private:
int FindGplr();
int AddImports(const xe_xex2_import_library_t *library);
int AddMethodHints();
virtual uint32_t GetEntryPoint();
virtual bool IsValueInTextRange(uint32_t value);
kernel::UserModule* module_;
};
} // namespace sdb
} // namespace cpu
} // namespace xe

View File

@ -44,6 +44,8 @@ public:
shared_ptr<ExportResolver> export_resolver();
const xechar_t* command_line();
int LoadBinaryModule(const xechar_t* path, uint32_t start_address);
int LoadModule(const xechar_t* path);
void LaunchModule(UserModule* user_module);
UserModule* GetModule(const xechar_t* path);

View File

@ -39,11 +39,12 @@ using namespace xe::kernel;
ModuleGenerator::ModuleGenerator(
xe_memory_ref memory, ExportResolver* export_resolver,
UserModule* module, SymbolDatabase* sdb,
const char* module_name, const char* module_path, SymbolDatabase* sdb,
LLVMContext* context, Module* gen_module) {
memory_ = xe_memory_retain(memory);
export_resolver_ = export_resolver;
module_ = module;
module_name_ = xestrdupa(module_name);
module_path_ = xestrdupa(module_path);
sdb_ = sdb;
context_ = context;
gen_module_ = gen_module;
@ -57,6 +58,8 @@ ModuleGenerator::~ModuleGenerator() {
}
delete di_builder_;
xe_free(module_path_);
xe_free(module_name_);
xe_memory_release(memory_);
}
@ -67,7 +70,7 @@ int ModuleGenerator::Generate() {
// This is used when creating any debug info. We may want to go more
// fine grained than this, but for now it's something.
xechar_t dir[2048];
XEIGNORE(xestrcpy(dir, XECOUNT(dir), module_->path()));
XEIGNORE(xestrcpy(dir, XECOUNT(dir), module_path_));
xechar_t* slash = xestrrchr(dir, '/');
if (slash) {
*(slash + 1) = 0;
@ -75,7 +78,7 @@ int ModuleGenerator::Generate() {
di_builder_ = new DIBuilder(*gen_module_);
di_builder_->createCompileUnit(
0,
StringRef(module_->name()),
StringRef(module_name_),
StringRef(dir),
StringRef("xenia"),
true,

View File

@ -46,13 +46,13 @@ using namespace xe::kernel;
ExecModule::ExecModule(
xe_memory_ref memory, shared_ptr<ExportResolver> export_resolver,
UserModule* user_module, shared_ptr<llvm::ExecutionEngine>& engine) {
const char* module_name, const char* module_path,
shared_ptr<llvm::ExecutionEngine>& engine) {
memory_ = xe_memory_retain(memory);
export_resolver_ = export_resolver;
module_ = user_module;
module_name_ = xestrdupa(module_name);
module_path_ = xestrdupa(module_path);
engine_ = engine;
sdb_ = shared_ptr<sdb::SymbolDatabase>(
new sdb::SymbolDatabase(memory_, export_resolver_.get(), module_));
context_ = shared_ptr<LLVMContext>(new LLVMContext());
}
@ -63,9 +63,26 @@ ExecModule::~ExecModule() {
engine_->removeModule(gen_module_.get());
}
xe_free(module_path_);
xe_free(module_name_);
xe_memory_release(memory_);
}
int ExecModule::PrepareUserModule(kernel::UserModule* user_module) {
sdb_ = shared_ptr<sdb::SymbolDatabase>(
new sdb::XexSymbolDatabase(memory_, export_resolver_.get(), user_module));
return Prepare();
}
int ExecModule::PrepareRawBinary(uint32_t start_address, uint32_t end_address) {
sdb_ = shared_ptr<sdb::SymbolDatabase>(
new sdb::RawSymbolDatabase(memory_, export_resolver_.get(),
start_address, end_address));
return Prepare();
}
int ExecModule::Prepare() {
int result_code = 1;
std::string error_message;
@ -112,13 +129,13 @@ int ExecModule::Prepare() {
// Dump the symbol database.
if (FLAGS_dump_module_map) {
xesnprintf(file_name, XECOUNT(file_name),
"%s%s.map", FLAGS_dump_path.c_str(), module_->name());
"%s%s.map", FLAGS_dump_path.c_str(), module_name_);
sdb_->Write(file_name);
}
// Initialize the module.
gen_module_ = shared_ptr<Module>(
new Module(module_->name(), *context_.get()));
new Module(module_name_, *context_.get()));
// TODO(benavnik): addModuleFlag?
// Inject globals.
@ -134,8 +151,8 @@ int ExecModule::Prepare() {
// Build the module from the source code.
codegen_ = auto_ptr<ModuleGenerator>(new ModuleGenerator(
memory_, export_resolver_.get(), module_, sdb_.get(),
context_.get(), gen_module_.get()));
memory_, export_resolver_.get(), module_name_, module_path_,
sdb_.get(), context_.get(), gen_module_.get()));
XEEXPECTZERO(codegen_->Generate());
// Write to cache.
@ -144,7 +161,7 @@ int ExecModule::Prepare() {
// Dump pre-optimized module to disk.
if (FLAGS_dump_module_bitcode) {
xesnprintf(file_name, XECOUNT(file_name),
"%s%s-preopt.bc", FLAGS_dump_path.c_str(), module_->name());
"%s%s-preopt.bc", FLAGS_dump_path.c_str(), module_name_);
outs = auto_ptr<raw_ostream>(new raw_fd_ostream(
file_name, error_message, raw_fd_ostream::F_Binary));
XEEXPECTTRUE(error_message.empty());
@ -176,7 +193,7 @@ int ExecModule::Prepare() {
// Dump post-optimized module to disk.
if (FLAGS_optimize_ir_modules && FLAGS_dump_module_bitcode) {
xesnprintf(file_name, XECOUNT(file_name),
"%s%s.bc", FLAGS_dump_path.c_str(), module_->name());
"%s%s.bc", FLAGS_dump_path.c_str(), module_name_);
outs = auto_ptr<raw_ostream>(new raw_fd_ostream(
file_name, error_message, raw_fd_ostream::F_Binary));
XEEXPECTTRUE(error_message.empty());

View File

@ -85,12 +85,32 @@ int Processor::Setup() {
return 0;
}
int Processor::PrepareModule(
const char* module_name, const char* module_path,
uint32_t start_address, uint32_t end_address,
shared_ptr<ExportResolver> export_resolver) {
ExecModule* exec_module = new ExecModule(
memory_, export_resolver, module_name, module_path, engine_);
if (exec_module->PrepareRawBinary(start_address, end_address)) {
delete exec_module;
return 1;
}
modules_.push_back(exec_module);
exec_module->Dump();
return 0;
}
int Processor::PrepareModule(UserModule* user_module,
shared_ptr<ExportResolver> export_resolver) {
ExecModule* exec_module = new ExecModule(
memory_, export_resolver, user_module, engine_);
memory_, export_resolver, user_module->name(), user_module->path(),
engine_);
if (exec_module->Prepare()) {
if (exec_module->PrepareUserModule(user_module)) {
delete exec_module;
return 1;
}

View File

@ -95,11 +95,10 @@ ExceptionEntrySymbol::ExceptionEntrySymbol() :
address(0), function(0) {
}
SymbolDatabase::SymbolDatabase(
xe_memory_ref memory, ExportResolver* export_resolver, UserModule* module) {
SymbolDatabase::SymbolDatabase(xe_memory_ref memory,
ExportResolver* export_resolver) {
memory_ = xe_memory_retain(memory);
export_resolver_ = export_resolver;
module_ = module;
}
SymbolDatabase::~SymbolDatabase() {
@ -115,27 +114,8 @@ int SymbolDatabase::Analyze() {
// This uses a queue to do a breadth-first search of all accessible
// functions. Callbacks and such likely won't be hit.
const xe_xex2_header_t *header = module_->xex_header();
// Find __savegprlr_* and __restgprlr_*.
FindGplr();
// Add each import thunk.
for (size_t n = 0; n < header->import_library_count; n++) {
AddImports(&header->import_libraries[n]);
}
// Add each export root.
// TODO(benvanik): exports.
// - insert fn or variable
// - queue fn
// Add method hints, if available.
// Not all XEXs have these.
AddMethodHints();
// Queue entry point of the application.
FunctionSymbol* fn = GetOrInsertFunction(header->exe_entry_point);
FunctionSymbol* fn = GetOrInsertFunction(GetEntryPoint());
fn->name = xestrdupa("start");
// Keep pumping the queue until there's nothing left to do.
@ -316,173 +296,6 @@ void SymbolDatabase::DumpFunctionBlocks(FunctionSymbol* fn) {
}
}
int SymbolDatabase::FindGplr() {
// Special stack save/restore functions.
// __savegprlr_14 to __savegprlr_31
// __restgprlr_14 to __restgprlr_31
// http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/ppc/xxx.s.htm
// It'd be nice to stash these away and mark them as such to allow for
// special codegen.
static const uint32_t code_values[] = {
0x68FFC1F9, // __savegprlr_14
0x70FFE1F9, // __savegprlr_15
0x78FF01FA, // __savegprlr_16
0x80FF21FA, // __savegprlr_17
0x88FF41FA, // __savegprlr_18
0x90FF61FA, // __savegprlr_19
0x98FF81FA, // __savegprlr_20
0xA0FFA1FA, // __savegprlr_21
0xA8FFC1FA, // __savegprlr_22
0xB0FFE1FA, // __savegprlr_23
0xB8FF01FB, // __savegprlr_24
0xC0FF21FB, // __savegprlr_25
0xC8FF41FB, // __savegprlr_26
0xD0FF61FB, // __savegprlr_27
0xD8FF81FB, // __savegprlr_28
0xE0FFA1FB, // __savegprlr_29
0xE8FFC1FB, // __savegprlr_30
0xF0FFE1FB, // __savegprlr_31
0xF8FF8191,
0x2000804E,
0x68FFC1E9, // __restgprlr_14
0x70FFE1E9, // __restgprlr_15
0x78FF01EA, // __restgprlr_16
0x80FF21EA, // __restgprlr_17
0x88FF41EA, // __restgprlr_18
0x90FF61EA, // __restgprlr_19
0x98FF81EA, // __restgprlr_20
0xA0FFA1EA, // __restgprlr_21
0xA8FFC1EA, // __restgprlr_22
0xB0FFE1EA, // __restgprlr_23
0xB8FF01EB, // __restgprlr_24
0xC0FF21EB, // __restgprlr_25
0xC8FF41EB, // __restgprlr_26
0xD0FF61EB, // __restgprlr_27
0xD8FF81EB, // __restgprlr_28
0xE0FFA1EB, // __restgprlr_29
0xE8FFC1EB, // __restgprlr_30
0xF0FFE1EB, // __restgprlr_31
0xF8FF8181,
0xA603887D,
0x2000804E,
};
uint32_t gplr_start = 0;
const xe_xex2_header_t* header = module_->xex_header();
for (size_t n = 0, i = 0; n < header->section_count; n++) {
const xe_xex2_section_t* section = &header->sections[n];
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);
if (section->info.type == XEX_SECTION_CODE) {
gplr_start = xe_memory_search_aligned(
memory_, start_address, end_address,
code_values, XECOUNT(code_values));
if (gplr_start) {
break;
}
}
i += section->info.page_count;
}
if (!gplr_start) {
return 0;
}
// Add function stubs.
char name[32];
uint32_t address = gplr_start;
for (int n = 14; n <= 31; n++) {
xesnprintf(name, XECOUNT(name), "__savegprlr_%d", n);
FunctionSymbol* fn = GetOrInsertFunction(address);
fn->end_address = fn->start_address + (31 - n) * 4 + 2 * 4;
fn->name = xestrdupa(name);
fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagSaveGprLr;
address += 4;
}
address = gplr_start + 20 * 4;
for (int n = 14; n <= 31; n++) {
xesnprintf(name, XECOUNT(name), "__restgprlr_%d", n);
FunctionSymbol* fn = GetOrInsertFunction(address);
fn->end_address = fn->start_address + (31 - n) * 4 + 3 * 4;
fn->name = xestrdupa(name);
fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagRestGprLr;
address += 4;
}
return 0;
}
int SymbolDatabase::AddImports(const xe_xex2_import_library_t* library) {
xe_xex2_ref xex = module_->xex();
xe_xex2_import_info_t* import_infos;
size_t import_info_count;
if (xe_xex2_get_import_infos(xex, library, &import_infos,
&import_info_count)) {
xe_xex2_release(xex);
return 1;
}
char name[128];
for (size_t n = 0; n < import_info_count; n++) {
const xe_xex2_import_info_t* info = &import_infos[n];
KernelExport* kernel_export = export_resolver_->GetExportByOrdinal(
library->name, info->ordinal);
VariableSymbol* var = GetOrInsertVariable(info->value_address);
if (kernel_export) {
if (info->thunk_address) {
xesnprintfa(name, XECOUNT(name), "__imp__%s", kernel_export->name);
} else {
xesnprintfa(name, XECOUNT(name), "%s", kernel_export->name);
}
} else {
xesnprintfa(name, XECOUNT(name), "__imp__%s_%.3X", library->name,
info->ordinal);
}
var->name = xestrdupa(name);
if (info->thunk_address) {
FunctionSymbol* fn = GetOrInsertFunction(info->thunk_address);
fn->end_address = fn->start_address + 16 - 4;
fn->type = FunctionSymbol::Kernel;
fn->kernel_export = kernel_export;
if (kernel_export) {
xesnprintfa(name, XECOUNT(name), "%s", kernel_export->name);
} else {
xesnprintfa(name, XECOUNT(name), "__kernel_%s_%.3X", library->name,
info->ordinal);
}
fn->name = xestrdupa(name);
}
}
xe_free(import_infos);
xe_xex2_release(xex);
return 0;
}
int SymbolDatabase::AddMethodHints() {
PEMethodInfo* method_infos;
size_t method_info_count;
if (module_->GetMethodHints(&method_infos, &method_info_count)) {
return 1;
}
for (size_t n = 0; n < method_info_count; n++) {
PEMethodInfo* method_info = &method_infos[n];
FunctionSymbol* fn = GetOrInsertFunction(method_info->address);
fn->end_address = method_info->address + method_info->total_length - 4;
fn->type = FunctionSymbol::User;
// TODO(benvanik): something with prolog_length?
}
xe_free(method_infos);
return 0;
}
int SymbolDatabase::AnalyzeFunction(FunctionSymbol* fn) {
// Ignore functions already analyzed.
if (fn->blocks.size()) {
@ -849,7 +662,235 @@ int SymbolDatabase::FlushQueue() {
return 0;
}
bool SymbolDatabase::IsValueInTextRange(uint32_t value) {
bool SymbolDatabase::IsRestGprLr(uint32_t addr) {
FunctionSymbol* fn = GetFunction(addr);
return fn && (fn->flags & FunctionSymbol::kFlagRestGprLr);
}
RawSymbolDatabase::RawSymbolDatabase(
xe_memory_ref memory, ExportResolver* export_resolver,
uint32_t start_address, uint32_t end_address) :
SymbolDatabase(memory, export_resolver) {
start_address_ = start_address;
end_address_ = end_address;
}
RawSymbolDatabase::~RawSymbolDatabase() {
}
uint32_t RawSymbolDatabase::GetEntryPoint() {
return start_address_;
}
bool RawSymbolDatabase::IsValueInTextRange(uint32_t value) {
return value >= start_address_ && value < end_address_;
}
XexSymbolDatabase::XexSymbolDatabase(
xe_memory_ref memory, ExportResolver* export_resolver, UserModule* module) :
SymbolDatabase(memory, export_resolver) {
module_ = module;
}
XexSymbolDatabase::~XexSymbolDatabase() {
}
int XexSymbolDatabase::Analyze() {
const xe_xex2_header_t *header = module_->xex_header();
// Find __savegprlr_* and __restgprlr_*.
FindGplr();
// Add each import thunk.
for (size_t n = 0; n < header->import_library_count; n++) {
AddImports(&header->import_libraries[n]);
}
// Add each export root.
// TODO(benvanik): exports.
// - insert fn or variable
// - queue fn
// Add method hints, if available.
// Not all XEXs have these.
AddMethodHints();
return SymbolDatabase::Analyze();
}
int XexSymbolDatabase::FindGplr() {
// Special stack save/restore functions.
// __savegprlr_14 to __savegprlr_31
// __restgprlr_14 to __restgprlr_31
// http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/ppc/xxx.s.htm
// It'd be nice to stash these away and mark them as such to allow for
// special codegen.
static const uint32_t code_values[] = {
0x68FFC1F9, // __savegprlr_14
0x70FFE1F9, // __savegprlr_15
0x78FF01FA, // __savegprlr_16
0x80FF21FA, // __savegprlr_17
0x88FF41FA, // __savegprlr_18
0x90FF61FA, // __savegprlr_19
0x98FF81FA, // __savegprlr_20
0xA0FFA1FA, // __savegprlr_21
0xA8FFC1FA, // __savegprlr_22
0xB0FFE1FA, // __savegprlr_23
0xB8FF01FB, // __savegprlr_24
0xC0FF21FB, // __savegprlr_25
0xC8FF41FB, // __savegprlr_26
0xD0FF61FB, // __savegprlr_27
0xD8FF81FB, // __savegprlr_28
0xE0FFA1FB, // __savegprlr_29
0xE8FFC1FB, // __savegprlr_30
0xF0FFE1FB, // __savegprlr_31
0xF8FF8191,
0x2000804E,
0x68FFC1E9, // __restgprlr_14
0x70FFE1E9, // __restgprlr_15
0x78FF01EA, // __restgprlr_16
0x80FF21EA, // __restgprlr_17
0x88FF41EA, // __restgprlr_18
0x90FF61EA, // __restgprlr_19
0x98FF81EA, // __restgprlr_20
0xA0FFA1EA, // __restgprlr_21
0xA8FFC1EA, // __restgprlr_22
0xB0FFE1EA, // __restgprlr_23
0xB8FF01EB, // __restgprlr_24
0xC0FF21EB, // __restgprlr_25
0xC8FF41EB, // __restgprlr_26
0xD0FF61EB, // __restgprlr_27
0xD8FF81EB, // __restgprlr_28
0xE0FFA1EB, // __restgprlr_29
0xE8FFC1EB, // __restgprlr_30
0xF0FFE1EB, // __restgprlr_31
0xF8FF8181,
0xA603887D,
0x2000804E,
};
uint32_t gplr_start = 0;
const xe_xex2_header_t* header = module_->xex_header();
for (size_t n = 0, i = 0; n < header->section_count; n++) {
const xe_xex2_section_t* section = &header->sections[n];
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);
if (section->info.type == XEX_SECTION_CODE) {
gplr_start = xe_memory_search_aligned(
memory_, start_address, end_address,
code_values, XECOUNT(code_values));
if (gplr_start) {
break;
}
}
i += section->info.page_count;
}
if (!gplr_start) {
return 0;
}
// Add function stubs.
char name[32];
uint32_t address = gplr_start;
for (int n = 14; n <= 31; n++) {
xesnprintf(name, XECOUNT(name), "__savegprlr_%d", n);
FunctionSymbol* fn = GetOrInsertFunction(address);
fn->end_address = fn->start_address + (31 - n) * 4 + 2 * 4;
fn->name = xestrdupa(name);
fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagSaveGprLr;
address += 4;
}
address = gplr_start + 20 * 4;
for (int n = 14; n <= 31; n++) {
xesnprintf(name, XECOUNT(name), "__restgprlr_%d", n);
FunctionSymbol* fn = GetOrInsertFunction(address);
fn->end_address = fn->start_address + (31 - n) * 4 + 3 * 4;
fn->name = xestrdupa(name);
fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagRestGprLr;
address += 4;
}
return 0;
}
int XexSymbolDatabase::AddImports(const xe_xex2_import_library_t* library) {
xe_xex2_ref xex = module_->xex();
xe_xex2_import_info_t* import_infos;
size_t import_info_count;
if (xe_xex2_get_import_infos(xex, library, &import_infos,
&import_info_count)) {
xe_xex2_release(xex);
return 1;
}
char name[128];
for (size_t n = 0; n < import_info_count; n++) {
const xe_xex2_import_info_t* info = &import_infos[n];
KernelExport* kernel_export = export_resolver_->GetExportByOrdinal(
library->name, info->ordinal);
VariableSymbol* var = GetOrInsertVariable(info->value_address);
if (kernel_export) {
if (info->thunk_address) {
xesnprintfa(name, XECOUNT(name), "__imp__%s", kernel_export->name);
} else {
xesnprintfa(name, XECOUNT(name), "%s", kernel_export->name);
}
} else {
xesnprintfa(name, XECOUNT(name), "__imp__%s_%.3X", library->name,
info->ordinal);
}
var->name = xestrdupa(name);
if (info->thunk_address) {
FunctionSymbol* fn = GetOrInsertFunction(info->thunk_address);
fn->end_address = fn->start_address + 16 - 4;
fn->type = FunctionSymbol::Kernel;
fn->kernel_export = kernel_export;
if (kernel_export) {
xesnprintfa(name, XECOUNT(name), "%s", kernel_export->name);
} else {
xesnprintfa(name, XECOUNT(name), "__kernel_%s_%.3X", library->name,
info->ordinal);
}
fn->name = xestrdupa(name);
}
}
xe_free(import_infos);
xe_xex2_release(xex);
return 0;
}
int XexSymbolDatabase::AddMethodHints() {
PEMethodInfo* method_infos;
size_t method_info_count;
if (module_->GetMethodHints(&method_infos, &method_info_count)) {
return 1;
}
for (size_t n = 0; n < method_info_count; n++) {
PEMethodInfo* method_info = &method_infos[n];
FunctionSymbol* fn = GetOrInsertFunction(method_info->address);
fn->end_address = method_info->address + method_info->total_length - 4;
fn->type = FunctionSymbol::User;
// TODO(benvanik): something with prolog_length?
}
xe_free(method_infos);
return 0;
}
uint32_t XexSymbolDatabase::GetEntryPoint() {
const xe_xex2_header_t* header = module_->xex_header();
return header->exe_entry_point;
};
bool XexSymbolDatabase::IsValueInTextRange(uint32_t value) {
const xe_xex2_header_t* header = module_->xex_header();
for (size_t n = 0, i = 0; n < header->section_count; n++) {
const xe_xex2_section_t* section = &header->sections[n];
@ -864,8 +905,3 @@ bool SymbolDatabase::IsValueInTextRange(uint32_t value) {
}
return false;
}
bool SymbolDatabase::IsRestGprLr(uint32_t addr) {
FunctionSymbol* fn = GetFunction(addr);
return fn && (fn->flags & FunctionSymbol::kFlagRestGprLr);
}

View File

@ -66,6 +66,33 @@ const xechar_t* Runtime::command_line() {
return command_line_;
}
int Runtime::LoadBinaryModule(const xechar_t* path, uint32_t start_address) {
const xechar_t* name = xestrrchr(path, '/') + 1;
// 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);
int result_code = 1;
XEEXPECTZERO(xe_copy_memory(xe_memory_addr(memory_, start_address),
xe_memory_get_length(memory_),
addr, length));
// Prepare the module.
XEEXPECTZERO(processor_->PrepareModule(
name, path, start_address, start_address + length, export_resolver_));
result_code = 0;
XECLEANUP:
xe_mmap_release(mmap);
return result_code;
}
int Runtime::LoadModule(const xechar_t* path) {
if (GetModule(path)) {
return 0;

Binary file not shown.

View File

@ -6,3 +6,4 @@ Disassembly of section .text:
0000000082010000 <.text>:
82010000: 60 83 ff ff ori r3,r4,65535
82010004: 4e 80 00 20 blr

View File

@ -2,4 +2,5 @@
ori r3, r4, 0xFFFF
blr
# REGISTER_OUT r3 0xBABE

View File

@ -102,15 +102,14 @@ int run_test(xe_pal_ref pal, string& src_file_path) {
runtime = shared_ptr<Runtime>(new Runtime(pal, processor, XT("")));
// TODO(benvanik): load test binary file into memory
// bin_file_path
// XEEXPECTZERO(runtime->LoadModule(path));
// Load the binary module.
XEEXPECTZERO(runtime->LoadBinaryModule(bin_file_path.c_str(), 0x82010000));
// Setup test state from annotations.
XEEXPECTZERO(setup_test_state(memory, processor.get(), annotations));
// Execute test.
// TODO(benvanik): execute test
XEEXPECTZERO(processor->Execute(0x82010000));
// Assert test state expectations.
XEEXPECTZERO(check_test_results(memory, processor.get(), annotations));