Refactoring to allow for raw binary loading.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
428
src/cpu/sdb.cc
428
src/cpu/sdb.cc
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user