Converting addresses in xe::cpu to 32bit.
This commit is contained in:
parent
3279776a80
commit
281abea955
|
@ -229,7 +229,7 @@ int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||||
|
|
||||||
void X64Emitter::MarkSourceOffset(const Instr* i) {
|
void X64Emitter::MarkSourceOffset(const Instr* i) {
|
||||||
auto entry = source_map_arena_.Alloc<SourceMapEntry>();
|
auto entry = source_map_arena_.Alloc<SourceMapEntry>();
|
||||||
entry->source_offset = i->src1.offset;
|
entry->source_offset = static_cast<uint32_t>(i->src1.offset);
|
||||||
entry->hir_offset = uint32_t(i->block->ordinal << 16) | i->ordinal;
|
entry->hir_offset = uint32_t(i->block->ordinal << 16) | i->ordinal;
|
||||||
entry->code_offset = getSize();
|
entry->code_offset = getSize();
|
||||||
source_map_count_++;
|
source_map_count_++;
|
||||||
|
@ -477,12 +477,11 @@ const int kICSlotCount = 4;
|
||||||
const int kICSlotSize = 23;
|
const int kICSlotSize = 23;
|
||||||
const uint64_t kICSlotInvalidTargetAddress = 0x0F0F0F0F0F0F0F0F;
|
const uint64_t kICSlotInvalidTargetAddress = 0x0F0F0F0F0F0F0F0F;
|
||||||
|
|
||||||
uint64_t ResolveFunctionAddress(void* raw_context, uint64_t target_address) {
|
uint64_t ResolveFunctionAddress(void* raw_context, uint32_t target_address) {
|
||||||
// TODO(benvanik): generate this thunk at runtime? or a shim?
|
// TODO(benvanik): generate this thunk at runtime? or a shim?
|
||||||
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||||
|
|
||||||
// TODO(benvanik): required?
|
// TODO(benvanik): required?
|
||||||
target_address &= 0xFFFFFFFF;
|
|
||||||
assert_not_zero(target_address);
|
assert_not_zero(target_address);
|
||||||
|
|
||||||
Function* fn = NULL;
|
Function* fn = NULL;
|
||||||
|
|
|
@ -34,10 +34,11 @@ int X64Function::AddBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
||||||
|
|
||||||
int X64Function::RemoveBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
int X64Function::RemoveBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
||||||
|
|
||||||
int X64Function::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
int X64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) {
|
||||||
auto backend = (X64Backend*)thread_state->runtime()->backend();
|
auto backend = (X64Backend*)thread_state->runtime()->backend();
|
||||||
auto thunk = backend->host_to_guest_thunk();
|
auto thunk = backend->host_to_guest_thunk();
|
||||||
thunk(machine_code_, thread_state->raw_context(), (void*)return_address);
|
thunk(machine_code_, thread_state->raw_context(),
|
||||||
|
reinterpret_cast<void*>(uintptr_t(return_address)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ class X64Function : public Function {
|
||||||
protected:
|
protected:
|
||||||
virtual int AddBreakpointImpl(Breakpoint* breakpoint);
|
virtual int AddBreakpointImpl(Breakpoint* breakpoint);
|
||||||
virtual int RemoveBreakpointImpl(Breakpoint* breakpoint);
|
virtual int RemoveBreakpointImpl(Breakpoint* breakpoint);
|
||||||
virtual int CallImpl(ThreadState* thread_state, uint64_t return_address);
|
virtual int CallImpl(ThreadState* thread_state, uint32_t return_address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void* machine_code_;
|
void* machine_code_;
|
||||||
|
|
|
@ -38,7 +38,7 @@ void DebugInfo::InitializeSourceMap(size_t source_map_count,
|
||||||
// TODO(benvanik): ensure sorted in some way? MC offset?
|
// TODO(benvanik): ensure sorted in some way? MC offset?
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceMapEntry* DebugInfo::LookupSourceOffset(uint64_t offset) {
|
SourceMapEntry* DebugInfo::LookupSourceOffset(uint32_t offset) {
|
||||||
// TODO(benvanik): binary search? We know the list is sorted by code order.
|
// TODO(benvanik): binary search? We know the list is sorted by code order.
|
||||||
for (size_t n = 0; n < source_map_count_; n++) {
|
for (size_t n = 0; n < source_map_count_; n++) {
|
||||||
auto entry = &source_map_[n];
|
auto entry = &source_map_[n];
|
||||||
|
|
|
@ -37,7 +37,7 @@ enum TraceFlags {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct SourceMapEntry_s {
|
typedef struct SourceMapEntry_s {
|
||||||
uint64_t source_offset; // Original source address/offset.
|
uint32_t source_offset; // Original source address/offset.
|
||||||
uint64_t hir_offset; // Block ordinal (16b) | Instr ordinal (16b)
|
uint64_t hir_offset; // Block ordinal (16b) | Instr ordinal (16b)
|
||||||
uint64_t code_offset; // Offset from emitted code start.
|
uint64_t code_offset; // Offset from emitted code start.
|
||||||
} SourceMapEntry;
|
} SourceMapEntry;
|
||||||
|
@ -57,7 +57,7 @@ class DebugInfo {
|
||||||
void set_machine_code_disasm(char* value) { machine_code_disasm_ = value; }
|
void set_machine_code_disasm(char* value) { machine_code_disasm_ = value; }
|
||||||
|
|
||||||
void InitializeSourceMap(size_t source_map_count, SourceMapEntry* source_map);
|
void InitializeSourceMap(size_t source_map_count, SourceMapEntry* source_map);
|
||||||
SourceMapEntry* LookupSourceOffset(uint64_t offset);
|
SourceMapEntry* LookupSourceOffset(uint32_t offset);
|
||||||
SourceMapEntry* LookupHIROffset(uint64_t offset);
|
SourceMapEntry* LookupHIROffset(uint64_t offset);
|
||||||
SourceMapEntry* LookupCodeOffset(uint64_t offset);
|
SourceMapEntry* LookupCodeOffset(uint64_t offset);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
|
|
||||||
Breakpoint::Breakpoint(Type type, uint64_t address)
|
Breakpoint::Breakpoint(Type type, uint32_t address)
|
||||||
: type_(type), address_(address) {}
|
: type_(type), address_(address) {}
|
||||||
|
|
||||||
Breakpoint::~Breakpoint() = default;
|
Breakpoint::~Breakpoint() = default;
|
||||||
|
@ -78,7 +78,7 @@ int Debugger::AddBreakpoint(Breakpoint* breakpoint) {
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(breakpoints_lock_);
|
std::lock_guard<std::mutex> guard(breakpoints_lock_);
|
||||||
breakpoints_.insert(
|
breakpoints_.insert(
|
||||||
std::pair<uint64_t, Breakpoint*>(breakpoint->address(), breakpoint));
|
std::pair<uint32_t, Breakpoint*>(breakpoint->address(), breakpoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all functions that contain the breakpoint address.
|
// Find all functions that contain the breakpoint address.
|
||||||
|
@ -126,7 +126,7 @@ int Debugger::RemoveBreakpoint(Breakpoint* breakpoint) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::FindBreakpoints(uint64_t address,
|
void Debugger::FindBreakpoints(uint32_t address,
|
||||||
std::vector<Breakpoint*>& out_breakpoints) {
|
std::vector<Breakpoint*>& out_breakpoints) {
|
||||||
std::lock_guard<std::mutex> guard(breakpoints_lock_);
|
std::lock_guard<std::mutex> guard(breakpoints_lock_);
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ void Debugger::OnFunctionDefined(FunctionInfo* symbol_info,
|
||||||
std::vector<Breakpoint*> breakpoints;
|
std::vector<Breakpoint*> breakpoints;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(breakpoints_lock_);
|
std::lock_guard<std::mutex> guard(breakpoints_lock_);
|
||||||
for (uint64_t address = symbol_info->address();
|
for (uint32_t address = symbol_info->address();
|
||||||
address <= symbol_info->end_address(); address += 4) {
|
address <= symbol_info->end_address(); address += 4) {
|
||||||
auto range = breakpoints_.equal_range(address);
|
auto range = breakpoints_.equal_range(address);
|
||||||
if (range.first == range.second) {
|
if (range.first == range.second) {
|
||||||
|
|
|
@ -34,18 +34,18 @@ class Breakpoint {
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Breakpoint(Type type, uint64_t address);
|
Breakpoint(Type type, uint32_t address);
|
||||||
~Breakpoint();
|
~Breakpoint();
|
||||||
|
|
||||||
Type type() const { return type_; }
|
Type type() const { return type_; }
|
||||||
uint64_t address() const { return address_; }
|
uint32_t address() const { return address_; }
|
||||||
|
|
||||||
const char* id() const { return id_.c_str(); }
|
const char* id() const { return id_.c_str(); }
|
||||||
void set_id(const char* id) { id_ = std::string(id); }
|
void set_id(const char* id) { id_ = std::string(id); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type_;
|
Type type_;
|
||||||
uint64_t address_;
|
uint32_t address_;
|
||||||
|
|
||||||
std::string id_;
|
std::string id_;
|
||||||
};
|
};
|
||||||
|
@ -91,7 +91,7 @@ class Debugger {
|
||||||
|
|
||||||
int AddBreakpoint(Breakpoint* breakpoint);
|
int AddBreakpoint(Breakpoint* breakpoint);
|
||||||
int RemoveBreakpoint(Breakpoint* breakpoint);
|
int RemoveBreakpoint(Breakpoint* breakpoint);
|
||||||
void FindBreakpoints(uint64_t address,
|
void FindBreakpoints(uint32_t address,
|
||||||
std::vector<Breakpoint*>& out_breakpoints);
|
std::vector<Breakpoint*>& out_breakpoints);
|
||||||
|
|
||||||
// TODO(benvanik): utility functions for modification (make function ignored,
|
// TODO(benvanik): utility functions for modification (make function ignored,
|
||||||
|
@ -113,7 +113,7 @@ class Debugger {
|
||||||
std::unordered_map<uint32_t, ThreadState*> threads_;
|
std::unordered_map<uint32_t, ThreadState*> threads_;
|
||||||
|
|
||||||
std::mutex breakpoints_lock_;
|
std::mutex breakpoints_lock_;
|
||||||
std::multimap<uint64_t, Breakpoint*> breakpoints_;
|
std::multimap<uint32_t, Breakpoint*> breakpoints_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
|
|
|
@ -25,7 +25,7 @@ EntryTable::~EntryTable() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* EntryTable::Get(uint64_t address) {
|
Entry* EntryTable::Get(uint32_t address) {
|
||||||
std::lock_guard<std::mutex> guard(lock_);
|
std::lock_guard<std::mutex> guard(lock_);
|
||||||
const auto& it = map_.find(address);
|
const auto& it = map_.find(address);
|
||||||
Entry* entry = it != map_.end() ? it->second : nullptr;
|
Entry* entry = it != map_.end() ? it->second : nullptr;
|
||||||
|
@ -38,7 +38,7 @@ Entry* EntryTable::Get(uint64_t address) {
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry::Status EntryTable::GetOrCreate(uint64_t address, Entry** out_entry) {
|
Entry::Status EntryTable::GetOrCreate(uint32_t address, Entry** out_entry) {
|
||||||
// TODO(benvanik): replace with a map with wait-free for find.
|
// TODO(benvanik): replace with a map with wait-free for find.
|
||||||
// https://github.com/facebook/folly/blob/master/folly/AtomicHashMap.h
|
// https://github.com/facebook/folly/blob/master/folly/AtomicHashMap.h
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ Entry::Status EntryTable::GetOrCreate(uint64_t address, Entry** out_entry) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Function*> EntryTable::FindWithAddress(uint64_t address) {
|
std::vector<Function*> EntryTable::FindWithAddress(uint32_t address) {
|
||||||
std::lock_guard<std::mutex> guard(lock_);
|
std::lock_guard<std::mutex> guard(lock_);
|
||||||
std::vector<Function*> fns;
|
std::vector<Function*> fns;
|
||||||
for (auto& it : map_) {
|
for (auto& it : map_) {
|
||||||
|
|
|
@ -27,8 +27,8 @@ typedef struct Entry_t {
|
||||||
STATUS_FAILED,
|
STATUS_FAILED,
|
||||||
} Status;
|
} Status;
|
||||||
|
|
||||||
uint64_t address;
|
uint32_t address;
|
||||||
uint64_t end_address;
|
uint32_t end_address;
|
||||||
Status status;
|
Status status;
|
||||||
Function* function;
|
Function* function;
|
||||||
} Entry;
|
} Entry;
|
||||||
|
@ -38,15 +38,15 @@ class EntryTable {
|
||||||
EntryTable();
|
EntryTable();
|
||||||
~EntryTable();
|
~EntryTable();
|
||||||
|
|
||||||
Entry* Get(uint64_t address);
|
Entry* Get(uint32_t address);
|
||||||
Entry::Status GetOrCreate(uint64_t address, Entry** out_entry);
|
Entry::Status GetOrCreate(uint32_t address, Entry** out_entry);
|
||||||
|
|
||||||
std::vector<Function*> FindWithAddress(uint64_t address);
|
std::vector<Function*> FindWithAddress(uint32_t address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TODO(benvanik): replace with a better data structure.
|
// TODO(benvanik): replace with a better data structure.
|
||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
std::unordered_map<uint64_t, Entry*> map_;
|
std::unordered_map<uint32_t, Entry*> map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
|
|
|
@ -50,7 +50,7 @@ int InstrEmit_branch(PPCHIRBuilder& f, const char* src, uint64_t cia,
|
||||||
// If it's a block inside of ourself, setup a fast jump.
|
// If it's a block inside of ourself, setup a fast jump.
|
||||||
// Unless it's to ourselves directly, in which case it's
|
// Unless it's to ourselves directly, in which case it's
|
||||||
// recursion.
|
// recursion.
|
||||||
uint64_t nia_value = nia->AsUint64() & 0xFFFFFFFF;
|
uint32_t nia_value = nia->AsUint64() & 0xFFFFFFFF;
|
||||||
bool is_recursion = false;
|
bool is_recursion = false;
|
||||||
if (nia_value == f.symbol_info()->address() && lk) {
|
if (nia_value == f.symbol_info()->address() && lk) {
|
||||||
is_recursion = true;
|
is_recursion = true;
|
||||||
|
|
|
@ -74,10 +74,10 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
|
||||||
// Always mark entry with label.
|
// Always mark entry with label.
|
||||||
label_list_[0] = NewLabel();
|
label_list_[0] = NewLabel();
|
||||||
|
|
||||||
uint64_t start_address = symbol_info->address();
|
uint32_t start_address = symbol_info->address();
|
||||||
uint64_t end_address = symbol_info->end_address();
|
uint32_t end_address = symbol_info->end_address();
|
||||||
InstrData i;
|
InstrData i;
|
||||||
for (uint64_t address = start_address, offset = 0; address <= end_address;
|
for (uint32_t address = start_address, offset = 0; address <= end_address;
|
||||||
address += 4, offset++) {
|
address += 4, offset++) {
|
||||||
i.address = address;
|
i.address = address;
|
||||||
i.code = poly::load_and_swap<uint32_t>(p + address);
|
i.code = poly::load_and_swap<uint32_t>(p + address);
|
||||||
|
@ -166,15 +166,14 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
|
||||||
return Finalize();
|
return Finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCHIRBuilder::AnnotateLabel(uint64_t address, Label* label) {
|
void PPCHIRBuilder::AnnotateLabel(uint32_t address, Label* label) {
|
||||||
char name_buffer[13];
|
char name_buffer[13];
|
||||||
snprintf(name_buffer, poly::countof(name_buffer), "loc_%.8X",
|
snprintf(name_buffer, poly::countof(name_buffer), "loc_%.8X", address);
|
||||||
(uint32_t)address);
|
|
||||||
label->name = (char*)arena_->Alloc(sizeof(name_buffer));
|
label->name = (char*)arena_->Alloc(sizeof(name_buffer));
|
||||||
memcpy(label->name, name_buffer, sizeof(name_buffer));
|
memcpy(label->name, name_buffer, sizeof(name_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionInfo* PPCHIRBuilder::LookupFunction(uint64_t address) {
|
FunctionInfo* PPCHIRBuilder::LookupFunction(uint32_t address) {
|
||||||
Runtime* runtime = frontend_->runtime();
|
Runtime* runtime = frontend_->runtime();
|
||||||
FunctionInfo* symbol_info;
|
FunctionInfo* symbol_info;
|
||||||
if (runtime->LookupFunctionInfo(address, &symbol_info)) {
|
if (runtime->LookupFunctionInfo(address, &symbol_info)) {
|
||||||
|
@ -183,7 +182,7 @@ FunctionInfo* PPCHIRBuilder::LookupFunction(uint64_t address) {
|
||||||
return symbol_info;
|
return symbol_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
Label* PPCHIRBuilder::LookupLabel(uint64_t address) {
|
Label* PPCHIRBuilder::LookupLabel(uint32_t address) {
|
||||||
if (address < start_address_) {
|
if (address < start_address_) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,8 @@ class PPCHIRBuilder : public hir::HIRBuilder {
|
||||||
int Emit(FunctionInfo* symbol_info, uint32_t flags);
|
int Emit(FunctionInfo* symbol_info, uint32_t flags);
|
||||||
|
|
||||||
FunctionInfo* symbol_info() const { return symbol_info_; }
|
FunctionInfo* symbol_info() const { return symbol_info_; }
|
||||||
FunctionInfo* LookupFunction(uint64_t address);
|
FunctionInfo* LookupFunction(uint32_t address);
|
||||||
Label* LookupLabel(uint64_t address);
|
Label* LookupLabel(uint32_t address);
|
||||||
|
|
||||||
Value* LoadLR();
|
Value* LoadLR();
|
||||||
void StoreLR(Value* value);
|
void StoreLR(Value* value);
|
||||||
|
@ -85,7 +85,7 @@ class PPCHIRBuilder : public hir::HIRBuilder {
|
||||||
Value* StoreRelease(Value* address, Value* value, uint32_t store_flags = 0);
|
Value* StoreRelease(Value* address, Value* value, uint32_t store_flags = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AnnotateLabel(uint64_t address, Label* label);
|
void AnnotateLabel(uint32_t address, Label* label);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PPCFrontend* frontend_;
|
PPCFrontend* frontend_;
|
||||||
|
|
|
@ -33,7 +33,7 @@ PPCScanner::PPCScanner(PPCFrontend* frontend) : frontend_(frontend) {}
|
||||||
|
|
||||||
PPCScanner::~PPCScanner() {}
|
PPCScanner::~PPCScanner() {}
|
||||||
|
|
||||||
bool PPCScanner::IsRestGprLr(uint64_t address) {
|
bool PPCScanner::IsRestGprLr(uint32_t address) {
|
||||||
FunctionInfo* symbol_info;
|
FunctionInfo* symbol_info;
|
||||||
if (frontend_->runtime()->LookupFunctionInfo(address, &symbol_info)) {
|
if (frontend_->runtime()->LookupFunctionInfo(address, &symbol_info)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -283,14 +283,14 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
|
||||||
Memory* memory = frontend_->memory();
|
Memory* memory = frontend_->memory();
|
||||||
const uint8_t* p = memory->membase();
|
const uint8_t* p = memory->membase();
|
||||||
|
|
||||||
std::map<uint64_t, BlockInfo> block_map;
|
std::map<uint32_t, BlockInfo> block_map;
|
||||||
|
|
||||||
uint64_t start_address = symbol_info->address();
|
uint32_t start_address = symbol_info->address();
|
||||||
uint64_t end_address = symbol_info->end_address();
|
uint32_t end_address = symbol_info->end_address();
|
||||||
bool in_block = false;
|
bool in_block = false;
|
||||||
uint64_t block_start = 0;
|
uint32_t block_start = 0;
|
||||||
InstrData i;
|
InstrData i;
|
||||||
for (uint64_t address = start_address; address <= end_address; address += 4) {
|
for (uint32_t address = start_address; address <= end_address; address += 4) {
|
||||||
i.address = address;
|
i.address = address;
|
||||||
i.code = poly::load_and_swap<uint32_t>(p + address);
|
i.code = poly::load_and_swap<uint32_t>(p + address);
|
||||||
if (!i.code) {
|
if (!i.code) {
|
||||||
|
|
|
@ -21,8 +21,8 @@ namespace frontend {
|
||||||
class PPCFrontend;
|
class PPCFrontend;
|
||||||
|
|
||||||
typedef struct BlockInfo_t {
|
typedef struct BlockInfo_t {
|
||||||
uint64_t start_address;
|
uint32_t start_address;
|
||||||
uint64_t end_address;
|
uint32_t end_address;
|
||||||
} BlockInfo;
|
} BlockInfo;
|
||||||
|
|
||||||
class PPCScanner {
|
class PPCScanner {
|
||||||
|
@ -35,7 +35,7 @@ class PPCScanner {
|
||||||
std::vector<BlockInfo> FindBlocks(FunctionInfo* symbol_info);
|
std::vector<BlockInfo> FindBlocks(FunctionInfo* symbol_info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsRestGprLr(uint64_t address);
|
bool IsRestGprLr(uint32_t address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PPCFrontend* frontend_;
|
PPCFrontend* frontend_;
|
||||||
|
|
|
@ -37,9 +37,9 @@ typedef std::vector<std::pair<std::string, std::string>> AnnotationList;
|
||||||
const uint32_t START_ADDRESS = 0x100000;
|
const uint32_t START_ADDRESS = 0x100000;
|
||||||
|
|
||||||
struct TestCase {
|
struct TestCase {
|
||||||
TestCase(uint64_t address, std::string& name)
|
TestCase(uint32_t address, std::string& name)
|
||||||
: address(address), name(name) {}
|
: address(address), name(name) {}
|
||||||
uint64_t address;
|
uint32_t address;
|
||||||
std::string name;
|
std::string name;
|
||||||
AnnotationList annotations;
|
AnnotationList annotations;
|
||||||
};
|
};
|
||||||
|
@ -111,8 +111,7 @@ class TestSuite {
|
||||||
}
|
}
|
||||||
std::string address(line_buffer, t_test_ - line_buffer);
|
std::string address(line_buffer, t_test_ - line_buffer);
|
||||||
std::string name(t_test_ + strlen(" t test_"));
|
std::string name(t_test_ + strlen(" t test_"));
|
||||||
test_cases.emplace_back(START_ADDRESS + std::stoull(address, 0, 16),
|
test_cases.emplace_back(START_ADDRESS + std::stoul(address, 0, 16), name);
|
||||||
name);
|
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return true;
|
return true;
|
||||||
|
@ -195,9 +194,9 @@ class TestRunner {
|
||||||
runtime->AddModule(std::move(module));
|
runtime->AddModule(std::move(module));
|
||||||
|
|
||||||
// Simulate a thread.
|
// Simulate a thread.
|
||||||
uint64_t stack_size = 64 * 1024;
|
uint32_t stack_size = 64 * 1024;
|
||||||
uint64_t stack_address = START_ADDRESS - stack_size;
|
uint32_t stack_address = START_ADDRESS - stack_size;
|
||||||
uint64_t thread_state_address = stack_address - 0x1000;
|
uint32_t thread_state_address = stack_address - 0x1000;
|
||||||
thread_state.reset(new ThreadState(runtime.get(), 0x100, stack_address,
|
thread_state.reset(new ThreadState(runtime.get(), 0x100, stack_address,
|
||||||
stack_size, thread_state_address));
|
stack_size, thread_state_address));
|
||||||
|
|
||||||
|
@ -221,7 +220,7 @@ class TestRunner {
|
||||||
|
|
||||||
auto ctx = thread_state->context();
|
auto ctx = thread_state->context();
|
||||||
ctx->lr = 0xBEBEBEBE;
|
ctx->lr = 0xBEBEBEBE;
|
||||||
fn->Call(thread_state.get(), ctx->lr);
|
fn->Call(thread_state.get(), uint32_t(ctx->lr));
|
||||||
|
|
||||||
// Assert test state expectations.
|
// Assert test state expectations.
|
||||||
bool result = CheckTestResults(test_case);
|
bool result = CheckTestResults(test_case);
|
||||||
|
|
|
@ -53,7 +53,7 @@ int Function::RemoveBreakpoint(Breakpoint* breakpoint) {
|
||||||
return found ? 0 : 1;
|
return found ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Breakpoint* Function::FindBreakpoint(uint64_t address) {
|
Breakpoint* Function::FindBreakpoint(uint32_t address) {
|
||||||
std::lock_guard<std::mutex> guard(lock_);
|
std::lock_guard<std::mutex> guard(lock_);
|
||||||
Breakpoint* result = nullptr;
|
Breakpoint* result = nullptr;
|
||||||
for (auto breakpoint : breakpoints_) {
|
for (auto breakpoint : breakpoints_) {
|
||||||
|
@ -65,7 +65,7 @@ Breakpoint* Function::FindBreakpoint(uint64_t address) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Function::Call(ThreadState* thread_state, uint64_t return_address) {
|
int Function::Call(ThreadState* thread_state, uint32_t return_address) {
|
||||||
// SCOPE_profile_cpu_f("cpu");
|
// SCOPE_profile_cpu_f("cpu");
|
||||||
|
|
||||||
ThreadState* original_thread_state = ThreadState::Get();
|
ThreadState* original_thread_state = ThreadState::Get();
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Function {
|
||||||
Function(FunctionInfo* symbol_info);
|
Function(FunctionInfo* symbol_info);
|
||||||
virtual ~Function();
|
virtual ~Function();
|
||||||
|
|
||||||
uint64_t address() const { return address_; }
|
uint32_t address() const { return address_; }
|
||||||
FunctionInfo* symbol_info() const { return symbol_info_; }
|
FunctionInfo* symbol_info() const { return symbol_info_; }
|
||||||
|
|
||||||
DebugInfo* debug_info() const { return debug_info_.get(); }
|
DebugInfo* debug_info() const { return debug_info_.get(); }
|
||||||
|
@ -39,16 +39,16 @@ class Function {
|
||||||
int AddBreakpoint(Breakpoint* breakpoint);
|
int AddBreakpoint(Breakpoint* breakpoint);
|
||||||
int RemoveBreakpoint(Breakpoint* breakpoint);
|
int RemoveBreakpoint(Breakpoint* breakpoint);
|
||||||
|
|
||||||
int Call(ThreadState* thread_state, uint64_t return_address);
|
int Call(ThreadState* thread_state, uint32_t return_address);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Breakpoint* FindBreakpoint(uint64_t address);
|
Breakpoint* FindBreakpoint(uint32_t address);
|
||||||
virtual int AddBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
virtual int AddBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
||||||
virtual int RemoveBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
virtual int RemoveBreakpointImpl(Breakpoint* breakpoint) { return 0; }
|
||||||
virtual int CallImpl(ThreadState* thread_state, uint64_t return_address) = 0;
|
virtual int CallImpl(ThreadState* thread_state, uint32_t return_address) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint64_t address_;
|
uint32_t address_;
|
||||||
FunctionInfo* symbol_info_;
|
FunctionInfo* symbol_info_;
|
||||||
std::unique_ptr<DebugInfo> debug_info_;
|
std::unique_ptr<DebugInfo> debug_info_;
|
||||||
|
|
||||||
|
|
|
@ -78,8 +78,8 @@ void FunctionInstrument::Exit(ThreadState* thread_state) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryInstrument::MemoryInstrument(Runtime* runtime, uint64_t address,
|
MemoryInstrument::MemoryInstrument(Runtime* runtime, uint32_t address,
|
||||||
uint64_t end_address)
|
uint32_t end_address)
|
||||||
: Instrument(runtime), address_(address), end_address_(end_address) {}
|
: Instrument(runtime), address_(address), end_address_(end_address) {}
|
||||||
|
|
||||||
bool MemoryInstrument::Attach() {
|
bool MemoryInstrument::Attach() {
|
||||||
|
@ -103,7 +103,7 @@ bool MemoryInstrument::Detach() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryInstrument::Access(ThreadState* thread_state, uint64_t address,
|
void MemoryInstrument::Access(ThreadState* thread_state, uint32_t address,
|
||||||
AccessType type) {
|
AccessType type) {
|
||||||
// TODO(benvanik): get thread local instance
|
// TODO(benvanik): get thread local instance
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ class FunctionInstrument : public Instrument {
|
||||||
|
|
||||||
class MemoryInstrument : public Instrument {
|
class MemoryInstrument : public Instrument {
|
||||||
public:
|
public:
|
||||||
MemoryInstrument(Runtime* runtime, uint64_t address, uint64_t end_address);
|
MemoryInstrument(Runtime* runtime, uint32_t address, uint32_t end_address);
|
||||||
virtual ~MemoryInstrument() {}
|
virtual ~MemoryInstrument() {}
|
||||||
|
|
||||||
uint64_t address() const { return address_; }
|
uint64_t address() const { return address_; }
|
||||||
|
@ -100,7 +100,7 @@ class MemoryInstrument : public Instrument {
|
||||||
ACCESS_READ = (1 << 1),
|
ACCESS_READ = (1 << 1),
|
||||||
ACCESS_WRITE = (1 << 2),
|
ACCESS_WRITE = (1 << 2),
|
||||||
};
|
};
|
||||||
void Access(ThreadState* thread_state, uint64_t address, AccessType type);
|
void Access(ThreadState* thread_state, uint32_t address, AccessType type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class Instance {
|
class Instance {
|
||||||
|
@ -110,7 +110,7 @@ class MemoryInstrument : public Instrument {
|
||||||
|
|
||||||
MemoryInstrument* instrument() const { return instrument_; }
|
MemoryInstrument* instrument() const { return instrument_; }
|
||||||
|
|
||||||
virtual void OnAccess(ThreadState* thread_state, uint64_t address,
|
virtual void OnAccess(ThreadState* thread_state, uint32_t address,
|
||||||
AccessType type) = 0;
|
AccessType type) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -118,8 +118,8 @@ class MemoryInstrument : public Instrument {
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t address_;
|
uint32_t address_;
|
||||||
uint64_t end_address_;
|
uint32_t end_address_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ThreadInstrument
|
// ThreadInstrument
|
||||||
|
|
|
@ -24,9 +24,9 @@ Module::Module(Runtime* runtime)
|
||||||
|
|
||||||
Module::~Module() = default;
|
Module::~Module() = default;
|
||||||
|
|
||||||
bool Module::ContainsAddress(uint64_t address) { return true; }
|
bool Module::ContainsAddress(uint32_t address) { return true; }
|
||||||
|
|
||||||
SymbolInfo* Module::LookupSymbol(uint64_t address, bool wait) {
|
SymbolInfo* Module::LookupSymbol(uint32_t address, bool wait) {
|
||||||
lock_.lock();
|
lock_.lock();
|
||||||
const auto it = map_.find(address);
|
const auto it = map_.find(address);
|
||||||
SymbolInfo* symbol_info = it != map_.end() ? it->second : nullptr;
|
SymbolInfo* symbol_info = it != map_.end() ? it->second : nullptr;
|
||||||
|
@ -51,7 +51,7 @@ SymbolInfo* Module::LookupSymbol(uint64_t address, bool wait) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolInfo::Status Module::DeclareSymbol(SymbolInfo::Type type,
|
SymbolInfo::Status Module::DeclareSymbol(SymbolInfo::Type type,
|
||||||
uint64_t address,
|
uint32_t address,
|
||||||
SymbolInfo** out_symbol_info) {
|
SymbolInfo** out_symbol_info) {
|
||||||
*out_symbol_info = nullptr;
|
*out_symbol_info = nullptr;
|
||||||
lock_.lock();
|
lock_.lock();
|
||||||
|
@ -100,7 +100,7 @@ SymbolInfo::Status Module::DeclareSymbol(SymbolInfo::Type type,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolInfo::Status Module::DeclareFunction(uint64_t address,
|
SymbolInfo::Status Module::DeclareFunction(uint32_t address,
|
||||||
FunctionInfo** out_symbol_info) {
|
FunctionInfo** out_symbol_info) {
|
||||||
SymbolInfo* symbol_info;
|
SymbolInfo* symbol_info;
|
||||||
SymbolInfo::Status status =
|
SymbolInfo::Status status =
|
||||||
|
@ -109,7 +109,7 @@ SymbolInfo::Status Module::DeclareFunction(uint64_t address,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolInfo::Status Module::DeclareVariable(uint64_t address,
|
SymbolInfo::Status Module::DeclareVariable(uint32_t address,
|
||||||
VariableInfo** out_symbol_info) {
|
VariableInfo** out_symbol_info) {
|
||||||
SymbolInfo* symbol_info;
|
SymbolInfo* symbol_info;
|
||||||
SymbolInfo::Status status =
|
SymbolInfo::Status status =
|
||||||
|
|
|
@ -34,12 +34,12 @@ class Module {
|
||||||
|
|
||||||
virtual const std::string& name() const = 0;
|
virtual const std::string& name() const = 0;
|
||||||
|
|
||||||
virtual bool ContainsAddress(uint64_t address);
|
virtual bool ContainsAddress(uint32_t address);
|
||||||
|
|
||||||
SymbolInfo* LookupSymbol(uint64_t address, bool wait = true);
|
SymbolInfo* LookupSymbol(uint32_t address, bool wait = true);
|
||||||
virtual SymbolInfo::Status DeclareFunction(uint64_t address,
|
virtual SymbolInfo::Status DeclareFunction(uint32_t address,
|
||||||
FunctionInfo** out_symbol_info);
|
FunctionInfo** out_symbol_info);
|
||||||
virtual SymbolInfo::Status DeclareVariable(uint64_t address,
|
virtual SymbolInfo::Status DeclareVariable(uint32_t address,
|
||||||
VariableInfo** out_symbol_info);
|
VariableInfo** out_symbol_info);
|
||||||
|
|
||||||
SymbolInfo::Status DefineFunction(FunctionInfo* symbol_info);
|
SymbolInfo::Status DefineFunction(FunctionInfo* symbol_info);
|
||||||
|
@ -52,7 +52,7 @@ class Module {
|
||||||
int ReadMap(const char* file_name);
|
int ReadMap(const char* file_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SymbolInfo::Status DeclareSymbol(SymbolInfo::Type type, uint64_t address,
|
SymbolInfo::Status DeclareSymbol(SymbolInfo::Type type, uint32_t address,
|
||||||
SymbolInfo** out_symbol_info);
|
SymbolInfo** out_symbol_info);
|
||||||
SymbolInfo::Status DefineSymbol(SymbolInfo* symbol_info);
|
SymbolInfo::Status DefineSymbol(SymbolInfo* symbol_info);
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ class Module {
|
||||||
private:
|
private:
|
||||||
// TODO(benvanik): replace with a better data structure.
|
// TODO(benvanik): replace with a better data structure.
|
||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
std::unordered_map<uint64_t, SymbolInfo*> map_;
|
std::unordered_map<uint32_t, SymbolInfo*> map_;
|
||||||
std::vector<std::unique_ptr<SymbolInfo>> list_;
|
std::vector<std::unique_ptr<SymbolInfo>> list_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ int Processor::Setup() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Processor::Execute(ThreadState* thread_state, uint64_t address) {
|
int Processor::Execute(ThreadState* thread_state, uint32_t address) {
|
||||||
SCOPE_profile_cpu_f("cpu");
|
SCOPE_profile_cpu_f("cpu");
|
||||||
|
|
||||||
// Attempt to get the function.
|
// Attempt to get the function.
|
||||||
|
@ -129,7 +129,7 @@ int Processor::Execute(ThreadState* thread_state, uint64_t address) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Processor::Execute(ThreadState* thread_state, uint64_t address,
|
uint64_t Processor::Execute(ThreadState* thread_state, uint32_t address,
|
||||||
uint64_t args[], size_t arg_count) {
|
uint64_t args[], size_t arg_count) {
|
||||||
SCOPE_profile_cpu_f("cpu");
|
SCOPE_profile_cpu_f("cpu");
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ void Processor::LowerIrql(Irql old_value) {
|
||||||
reinterpret_cast<volatile uint32_t*>(&irql_));
|
reinterpret_cast<volatile uint32_t*>(&irql_));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Processor::ExecuteInterrupt(uint32_t cpu, uint64_t address,
|
uint64_t Processor::ExecuteInterrupt(uint32_t cpu, uint32_t address,
|
||||||
uint64_t args[], size_t arg_count) {
|
uint64_t args[], size_t arg_count) {
|
||||||
SCOPE_profile_cpu_f("cpu");
|
SCOPE_profile_cpu_f("cpu");
|
||||||
|
|
||||||
|
|
|
@ -42,14 +42,14 @@ class Processor {
|
||||||
|
|
||||||
int Setup();
|
int Setup();
|
||||||
|
|
||||||
int Execute(ThreadState* thread_state, uint64_t address);
|
int Execute(ThreadState* thread_state, uint32_t address);
|
||||||
uint64_t Execute(ThreadState* thread_state, uint64_t address, uint64_t args[],
|
uint64_t Execute(ThreadState* thread_state, uint32_t address, uint64_t args[],
|
||||||
size_t arg_count);
|
size_t arg_count);
|
||||||
|
|
||||||
Irql RaiseIrql(Irql new_value);
|
Irql RaiseIrql(Irql new_value);
|
||||||
void LowerIrql(Irql old_value);
|
void LowerIrql(Irql old_value);
|
||||||
|
|
||||||
uint64_t ExecuteInterrupt(uint32_t cpu, uint64_t address, uint64_t args[],
|
uint64_t ExecuteInterrupt(uint32_t cpu, uint32_t address, uint64_t args[],
|
||||||
size_t arg_count);
|
size_t arg_count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -61,7 +61,7 @@ class Processor {
|
||||||
Irql irql_;
|
Irql irql_;
|
||||||
std::mutex interrupt_thread_lock_;
|
std::mutex interrupt_thread_lock_;
|
||||||
ThreadState* interrupt_thread_state_;
|
ThreadState* interrupt_thread_state_;
|
||||||
uint64_t interrupt_thread_block_;
|
uint32_t interrupt_thread_block_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
|
|
|
@ -20,11 +20,11 @@ RawModule::RawModule(Runtime* runtime)
|
||||||
|
|
||||||
RawModule::~RawModule() {}
|
RawModule::~RawModule() {}
|
||||||
|
|
||||||
int RawModule::LoadFile(uint64_t base_address, const std::wstring& path) {
|
int RawModule::LoadFile(uint32_t base_address, const std::wstring& path) {
|
||||||
auto fixed_path = poly::to_string(poly::fix_path_separators(path));
|
auto fixed_path = poly::to_string(poly::fix_path_separators(path));
|
||||||
FILE* file = fopen(fixed_path.c_str(), "rb");
|
FILE* file = fopen(fixed_path.c_str(), "rb");
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
size_t file_length = ftell(file);
|
uint32_t file_length = static_cast<uint32_t>(ftell(file));
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
|
@ -52,7 +52,7 @@ int RawModule::LoadFile(uint64_t base_address, const std::wstring& path) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RawModule::ContainsAddress(uint64_t address) {
|
bool RawModule::ContainsAddress(uint32_t address) {
|
||||||
return address >= low_address_ && address < high_address_;
|
return address >= low_address_ && address < high_address_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,17 +22,17 @@ class RawModule : public Module {
|
||||||
RawModule(Runtime* runtime);
|
RawModule(Runtime* runtime);
|
||||||
~RawModule() override;
|
~RawModule() override;
|
||||||
|
|
||||||
int LoadFile(uint64_t base_address, const std::wstring& path);
|
int LoadFile(uint32_t base_address, const std::wstring& path);
|
||||||
|
|
||||||
const std::string& name() const override { return name_; }
|
const std::string& name() const override { return name_; }
|
||||||
|
|
||||||
bool ContainsAddress(uint64_t address) override;
|
bool ContainsAddress(uint32_t address) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
uint64_t base_address_;
|
uint32_t base_address_;
|
||||||
uint64_t low_address_;
|
uint32_t low_address_;
|
||||||
uint64_t high_address_;
|
uint32_t high_address_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
|
|
|
@ -29,7 +29,7 @@ class BuiltinModule : public Module {
|
||||||
public:
|
public:
|
||||||
BuiltinModule(Runtime* runtime) : Module(runtime), name_("builtin") {}
|
BuiltinModule(Runtime* runtime) : Module(runtime), name_("builtin") {}
|
||||||
const std::string& name() const override { return name_; }
|
const std::string& name() const override { return name_; }
|
||||||
bool ContainsAddress(uint64_t address) override {
|
bool ContainsAddress(uint32_t address) override {
|
||||||
return (address & 0x1FFFFFFF0) == 0x100000000;
|
return (address & 0x1FFFFFFF0) == 0x100000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ Runtime::Runtime(Memory* memory, ExportResolver* export_resolver,
|
||||||
debug_info_flags_(debug_info_flags),
|
debug_info_flags_(debug_info_flags),
|
||||||
trace_flags_(trace_flags),
|
trace_flags_(trace_flags),
|
||||||
builtin_module_(nullptr),
|
builtin_module_(nullptr),
|
||||||
next_builtin_address_(0x100000000ull),
|
next_builtin_address_(0xFFFF0000ul),
|
||||||
export_resolver_(export_resolver) {}
|
export_resolver_(export_resolver) {}
|
||||||
|
|
||||||
Runtime::~Runtime() {
|
Runtime::~Runtime() {
|
||||||
|
@ -138,7 +138,7 @@ std::vector<Module*> Runtime::GetModules() {
|
||||||
FunctionInfo* Runtime::DefineBuiltin(const std::string& name,
|
FunctionInfo* Runtime::DefineBuiltin(const std::string& name,
|
||||||
FunctionInfo::ExternHandler handler,
|
FunctionInfo::ExternHandler handler,
|
||||||
void* arg0, void* arg1) {
|
void* arg0, void* arg1) {
|
||||||
uint64_t address = next_builtin_address_;
|
uint32_t address = next_builtin_address_;
|
||||||
next_builtin_address_ += 4;
|
next_builtin_address_ += 4;
|
||||||
|
|
||||||
FunctionInfo* fn_info;
|
FunctionInfo* fn_info;
|
||||||
|
@ -151,11 +151,11 @@ FunctionInfo* Runtime::DefineBuiltin(const std::string& name,
|
||||||
return fn_info;
|
return fn_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Function*> Runtime::FindFunctionsWithAddress(uint64_t address) {
|
std::vector<Function*> Runtime::FindFunctionsWithAddress(uint32_t address) {
|
||||||
return entry_table_.FindWithAddress(address);
|
return entry_table_.FindWithAddress(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Runtime::ResolveFunction(uint64_t address, Function** out_function) {
|
int Runtime::ResolveFunction(uint32_t address, Function** out_function) {
|
||||||
*out_function = nullptr;
|
*out_function = nullptr;
|
||||||
Entry* entry;
|
Entry* entry;
|
||||||
Entry::Status status = entry_table_.GetOrCreate(address, &entry);
|
Entry::Status status = entry_table_.GetOrCreate(address, &entry);
|
||||||
|
@ -187,7 +187,7 @@ int Runtime::ResolveFunction(uint64_t address, Function** out_function) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Runtime::LookupFunctionInfo(uint64_t address,
|
int Runtime::LookupFunctionInfo(uint32_t address,
|
||||||
FunctionInfo** out_symbol_info) {
|
FunctionInfo** out_symbol_info) {
|
||||||
*out_symbol_info = nullptr;
|
*out_symbol_info = nullptr;
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ int Runtime::LookupFunctionInfo(uint64_t address,
|
||||||
return LookupFunctionInfo(code_module, address, out_symbol_info);
|
return LookupFunctionInfo(code_module, address, out_symbol_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Runtime::LookupFunctionInfo(Module* module, uint64_t address,
|
int Runtime::LookupFunctionInfo(Module* module, uint32_t address,
|
||||||
FunctionInfo** out_symbol_info) {
|
FunctionInfo** out_symbol_info) {
|
||||||
// Atomic create/lookup symbol in module.
|
// Atomic create/lookup symbol in module.
|
||||||
// If we get back the NEW flag we must declare it now.
|
// If we get back the NEW flag we must declare it now.
|
||||||
|
|
|
@ -48,12 +48,12 @@ class Runtime {
|
||||||
FunctionInfo::ExternHandler handler, void* arg0,
|
FunctionInfo::ExternHandler handler, void* arg0,
|
||||||
void* arg1);
|
void* arg1);
|
||||||
|
|
||||||
std::vector<Function*> FindFunctionsWithAddress(uint64_t address);
|
std::vector<Function*> FindFunctionsWithAddress(uint32_t address);
|
||||||
|
|
||||||
int LookupFunctionInfo(uint64_t address, FunctionInfo** out_symbol_info);
|
int LookupFunctionInfo(uint32_t address, FunctionInfo** out_symbol_info);
|
||||||
int LookupFunctionInfo(Module* module, uint64_t address,
|
int LookupFunctionInfo(Module* module, uint32_t address,
|
||||||
FunctionInfo** out_symbol_info);
|
FunctionInfo** out_symbol_info);
|
||||||
int ResolveFunction(uint64_t address, Function** out_function);
|
int ResolveFunction(uint32_t address, Function** out_function);
|
||||||
|
|
||||||
// uint32_t CreateCallback(void (*callback)(void* data), void* data);
|
// uint32_t CreateCallback(void (*callback)(void* data), void* data);
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ class Runtime {
|
||||||
std::mutex modules_lock_;
|
std::mutex modules_lock_;
|
||||||
std::vector<std::unique_ptr<Module>> modules_;
|
std::vector<std::unique_ptr<Module>> modules_;
|
||||||
Module* builtin_module_;
|
Module* builtin_module_;
|
||||||
uint64_t next_builtin_address_;
|
uint32_t next_builtin_address_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
|
|
||||||
SymbolInfo::SymbolInfo(Type type, Module* module, uint64_t address)
|
SymbolInfo::SymbolInfo(Type type, Module* module, uint32_t address)
|
||||||
: type_(type),
|
: type_(type),
|
||||||
module_(module),
|
module_(module),
|
||||||
status_(STATUS_DEFINING),
|
status_(STATUS_DEFINING),
|
||||||
|
@ -21,7 +21,7 @@ SymbolInfo::SymbolInfo(Type type, Module* module, uint64_t address)
|
||||||
|
|
||||||
SymbolInfo::~SymbolInfo() = default;
|
SymbolInfo::~SymbolInfo() = default;
|
||||||
|
|
||||||
FunctionInfo::FunctionInfo(Module* module, uint64_t address)
|
FunctionInfo::FunctionInfo(Module* module, uint32_t address)
|
||||||
: SymbolInfo(SymbolInfo::TYPE_FUNCTION, module, address),
|
: SymbolInfo(SymbolInfo::TYPE_FUNCTION, module, address),
|
||||||
end_address_(0),
|
end_address_(0),
|
||||||
behavior_(BEHAVIOR_DEFAULT),
|
behavior_(BEHAVIOR_DEFAULT),
|
||||||
|
@ -38,7 +38,7 @@ void FunctionInfo::SetupExtern(ExternHandler handler, void* arg0, void* arg1) {
|
||||||
extern_info_.arg1 = arg1;
|
extern_info_.arg1 = arg1;
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableInfo::VariableInfo(Module* module, uint64_t address)
|
VariableInfo::VariableInfo(Module* module, uint32_t address)
|
||||||
: SymbolInfo(SymbolInfo::TYPE_VARIABLE, module, address) {}
|
: SymbolInfo(SymbolInfo::TYPE_VARIABLE, module, address) {}
|
||||||
|
|
||||||
VariableInfo::~VariableInfo() = default;
|
VariableInfo::~VariableInfo() = default;
|
||||||
|
|
|
@ -35,14 +35,14 @@ class SymbolInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SymbolInfo(Type type, Module* module, uint64_t address);
|
SymbolInfo(Type type, Module* module, uint32_t address);
|
||||||
virtual ~SymbolInfo();
|
virtual ~SymbolInfo();
|
||||||
|
|
||||||
Type type() const { return type_; }
|
Type type() const { return type_; }
|
||||||
Module* module() const { return module_; }
|
Module* module() const { return module_; }
|
||||||
Status status() const { return status_; }
|
Status status() const { return status_; }
|
||||||
void set_status(Status value) { status_ = value; }
|
void set_status(Status value) { status_ = value; }
|
||||||
uint64_t address() const { return address_; }
|
uint32_t address() const { return address_; }
|
||||||
|
|
||||||
const std::string& name() const { return name_; }
|
const std::string& name() const { return name_; }
|
||||||
void set_name(const std::string& value) { name_ = value; }
|
void set_name(const std::string& value) { name_ = value; }
|
||||||
|
@ -51,7 +51,7 @@ class SymbolInfo {
|
||||||
Type type_;
|
Type type_;
|
||||||
Module* module_;
|
Module* module_;
|
||||||
Status status_;
|
Status status_;
|
||||||
uint64_t address_;
|
uint32_t address_;
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
@ -67,12 +67,12 @@ class FunctionInfo : public SymbolInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FunctionInfo(Module* module, uint64_t address);
|
FunctionInfo(Module* module, uint32_t address);
|
||||||
~FunctionInfo() override;
|
~FunctionInfo() override;
|
||||||
|
|
||||||
bool has_end_address() const { return end_address_ > 0; }
|
bool has_end_address() const { return end_address_ > 0; }
|
||||||
uint64_t end_address() const { return end_address_; }
|
uint32_t end_address() const { return end_address_; }
|
||||||
void set_end_address(uint64_t value) { end_address_ = value; }
|
void set_end_address(uint32_t value) { end_address_ = value; }
|
||||||
|
|
||||||
Behavior behavior() const { return behavior_; }
|
Behavior behavior() const { return behavior_; }
|
||||||
void set_behavior(Behavior value) { behavior_ = value; }
|
void set_behavior(Behavior value) { behavior_ = value; }
|
||||||
|
@ -87,7 +87,7 @@ class FunctionInfo : public SymbolInfo {
|
||||||
void* extern_arg1() const { return extern_info_.arg1; }
|
void* extern_arg1() const { return extern_info_.arg1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t end_address_;
|
uint32_t end_address_;
|
||||||
Behavior behavior_;
|
Behavior behavior_;
|
||||||
Function* function_;
|
Function* function_;
|
||||||
struct {
|
struct {
|
||||||
|
@ -99,7 +99,7 @@ class FunctionInfo : public SymbolInfo {
|
||||||
|
|
||||||
class VariableInfo : public SymbolInfo {
|
class VariableInfo : public SymbolInfo {
|
||||||
public:
|
public:
|
||||||
VariableInfo(Module* module, uint64_t address);
|
VariableInfo(Module* module, uint32_t address);
|
||||||
~VariableInfo() override;
|
~VariableInfo() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,9 @@ class TestFunction {
|
||||||
xe::cpu::Function* fn;
|
xe::cpu::Function* fn;
|
||||||
runtime->ResolveFunction(0x1000, &fn);
|
runtime->ResolveFunction(0x1000, &fn);
|
||||||
|
|
||||||
uint64_t stack_size = 64 * 1024;
|
uint32_t stack_size = 64 * 1024;
|
||||||
uint64_t stack_address = memory_size - stack_size;
|
uint32_t stack_address = memory_size - stack_size;
|
||||||
uint64_t thread_state_address = stack_address - 0x1000;
|
uint32_t thread_state_address = stack_address - 0x1000;
|
||||||
auto thread_state =
|
auto thread_state =
|
||||||
std::make_unique<ThreadState>(runtime.get(), 0x100, stack_address,
|
std::make_unique<ThreadState>(runtime.get(), 0x100, stack_address,
|
||||||
stack_size, thread_state_address);
|
stack_size, thread_state_address);
|
||||||
|
@ -83,13 +83,13 @@ class TestFunction {
|
||||||
|
|
||||||
pre_call(ctx);
|
pre_call(ctx);
|
||||||
|
|
||||||
fn->Call(thread_state.get(), ctx->lr);
|
fn->Call(thread_state.get(), uint32_t(ctx->lr));
|
||||||
|
|
||||||
post_call(ctx);
|
post_call(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t memory_size;
|
uint32_t memory_size;
|
||||||
std::unique_ptr<Memory> memory;
|
std::unique_ptr<Memory> memory;
|
||||||
std::vector<std::unique_ptr<Runtime>> runtimes;
|
std::vector<std::unique_ptr<Runtime>> runtimes;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,7 @@ using xe::cpu::hir::HIRBuilder;
|
||||||
namespace passes = xe::cpu::compiler::passes;
|
namespace passes = xe::cpu::compiler::passes;
|
||||||
|
|
||||||
TestModule::TestModule(Runtime* runtime, const std::string& name,
|
TestModule::TestModule(Runtime* runtime, const std::string& name,
|
||||||
std::function<bool(uint64_t)> contains_address,
|
std::function<bool(uint32_t)> contains_address,
|
||||||
std::function<bool(hir::HIRBuilder&)> generate)
|
std::function<bool(hir::HIRBuilder&)> generate)
|
||||||
: Module(runtime),
|
: Module(runtime),
|
||||||
name_(name),
|
name_(name),
|
||||||
|
@ -66,11 +66,11 @@ TestModule::TestModule(Runtime* runtime, const std::string& name,
|
||||||
|
|
||||||
TestModule::~TestModule() = default;
|
TestModule::~TestModule() = default;
|
||||||
|
|
||||||
bool TestModule::ContainsAddress(uint64_t address) {
|
bool TestModule::ContainsAddress(uint32_t address) {
|
||||||
return contains_address_(address);
|
return contains_address_(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolInfo::Status TestModule::DeclareFunction(uint64_t address,
|
SymbolInfo::Status TestModule::DeclareFunction(uint32_t address,
|
||||||
FunctionInfo** out_symbol_info) {
|
FunctionInfo** out_symbol_info) {
|
||||||
SymbolInfo::Status status = Module::DeclareFunction(address, out_symbol_info);
|
SymbolInfo::Status status = Module::DeclareFunction(address, out_symbol_info);
|
||||||
if (status == SymbolInfo::STATUS_NEW) {
|
if (status == SymbolInfo::STATUS_NEW) {
|
||||||
|
|
|
@ -25,20 +25,20 @@ namespace cpu {
|
||||||
class TestModule : public Module {
|
class TestModule : public Module {
|
||||||
public:
|
public:
|
||||||
TestModule(Runtime* runtime, const std::string& name,
|
TestModule(Runtime* runtime, const std::string& name,
|
||||||
std::function<bool(uint64_t)> contains_address,
|
std::function<bool(uint32_t)> contains_address,
|
||||||
std::function<bool(hir::HIRBuilder&)> generate);
|
std::function<bool(hir::HIRBuilder&)> generate);
|
||||||
~TestModule() override;
|
~TestModule() override;
|
||||||
|
|
||||||
const std::string& name() const override { return name_; }
|
const std::string& name() const override { return name_; }
|
||||||
|
|
||||||
bool ContainsAddress(uint64_t address) override;
|
bool ContainsAddress(uint32_t address) override;
|
||||||
|
|
||||||
SymbolInfo::Status DeclareFunction(uint64_t address,
|
SymbolInfo::Status DeclareFunction(uint32_t address,
|
||||||
FunctionInfo** out_symbol_info) override;
|
FunctionInfo** out_symbol_info) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
std::function<bool(uint64_t)> contains_address_;
|
std::function<bool(uint32_t)> contains_address_;
|
||||||
std::function<bool(hir::HIRBuilder&)> generate_;
|
std::function<bool(hir::HIRBuilder&)> generate_;
|
||||||
|
|
||||||
std::unique_ptr<hir::HIRBuilder> builder_;
|
std::unique_ptr<hir::HIRBuilder> builder_;
|
||||||
|
|
|
@ -22,8 +22,8 @@ using PPCContext = xe::cpu::frontend::PPCContext;
|
||||||
thread_local ThreadState* thread_state_ = nullptr;
|
thread_local ThreadState* thread_state_ = nullptr;
|
||||||
|
|
||||||
ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id,
|
ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id,
|
||||||
uint64_t stack_address, size_t stack_size,
|
uint32_t stack_address, uint32_t stack_size,
|
||||||
uint64_t thread_state_address)
|
uint32_t thread_state_address)
|
||||||
: runtime_(runtime),
|
: runtime_(runtime),
|
||||||
memory_(runtime->memory()),
|
memory_(runtime->memory()),
|
||||||
thread_id_(thread_id),
|
thread_id_(thread_id),
|
||||||
|
|
|
@ -28,8 +28,8 @@ class Runtime;
|
||||||
|
|
||||||
class ThreadState {
|
class ThreadState {
|
||||||
public:
|
public:
|
||||||
ThreadState(Runtime* runtime, uint32_t thread_id, uint64_t stack_address,
|
ThreadState(Runtime* runtime, uint32_t thread_id, uint32_t stack_address,
|
||||||
size_t stack_size, uint64_t thread_state_address);
|
uint32_t stack_size, uint32_t thread_state_address);
|
||||||
~ThreadState();
|
~ThreadState();
|
||||||
|
|
||||||
Runtime* runtime() const { return runtime_; }
|
Runtime* runtime() const { return runtime_; }
|
||||||
|
@ -39,9 +39,9 @@ class ThreadState {
|
||||||
void set_name(const std::string& value) { name_ = value; }
|
void set_name(const std::string& value) { name_ = value; }
|
||||||
void* backend_data() const { return backend_data_; }
|
void* backend_data() const { return backend_data_; }
|
||||||
void* raw_context() const { return raw_context_; }
|
void* raw_context() const { return raw_context_; }
|
||||||
uint64_t stack_address() const { return stack_address_; }
|
uint32_t stack_address() const { return stack_address_; }
|
||||||
size_t stack_size() const { return stack_size_; }
|
size_t stack_size() const { return stack_size_; }
|
||||||
uint64_t thread_state_address() const { return thread_state_address_; }
|
uint32_t thread_state_address() const { return thread_state_address_; }
|
||||||
xe::cpu::frontend::PPCContext* context() const { return context_; }
|
xe::cpu::frontend::PPCContext* context() const { return context_; }
|
||||||
|
|
||||||
int Suspend() { return Suspend(~0); }
|
int Suspend() { return Suspend(~0); }
|
||||||
|
@ -61,10 +61,10 @@ class ThreadState {
|
||||||
std::string name_;
|
std::string name_;
|
||||||
void* backend_data_;
|
void* backend_data_;
|
||||||
void* raw_context_;
|
void* raw_context_;
|
||||||
uint64_t stack_address_;
|
uint32_t stack_address_;
|
||||||
bool stack_allocated_;
|
bool stack_allocated_;
|
||||||
size_t stack_size_;
|
uint32_t stack_size_;
|
||||||
uint64_t thread_state_address_;
|
uint32_t thread_state_address_;
|
||||||
|
|
||||||
// NOTE: must be 64b aligned for SSE ops.
|
// NOTE: must be 64b aligned for SSE ops.
|
||||||
xe::cpu::frontend::PPCContext* context_;
|
xe::cpu::frontend::PPCContext* context_;
|
||||||
|
|
|
@ -35,11 +35,10 @@ XexModule::XexModule(Runtime* runtime)
|
||||||
low_address_(0),
|
low_address_(0),
|
||||||
high_address_(0) {}
|
high_address_(0) {}
|
||||||
|
|
||||||
XexModule::~XexModule() {
|
XexModule::~XexModule() { xe_xex2_dealloc(xex_); }
|
||||||
xe_xex2_dealloc(xex_);
|
|
||||||
}
|
|
||||||
|
|
||||||
int XexModule::Load(const std::string& name, const std::string& path, xe_xex2_ref xex) {
|
int XexModule::Load(const std::string& name, const std::string& path,
|
||||||
|
xe_xex2_ref xex) {
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
xex_ = xex;
|
xex_ = xex;
|
||||||
|
@ -49,16 +48,15 @@ int XexModule::Load(const std::string& name, const std::string& path, xe_xex2_re
|
||||||
// All code sections are continuous, so this should be easy.
|
// All code sections are continuous, so this should be easy.
|
||||||
low_address_ = UINT_MAX;
|
low_address_ = UINT_MAX;
|
||||||
high_address_ = 0;
|
high_address_ = 0;
|
||||||
for (size_t n = 0, i = 0; n < header->section_count; n++) {
|
for (uint32_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 size_t start_address = header->exe_address + (i * section->page_size);
|
const uint32_t start_address =
|
||||||
const size_t end_address =
|
header->exe_address + (i * section->page_size);
|
||||||
|
const uint32_t end_address =
|
||||||
start_address + (section->info.page_count * section->page_size);
|
start_address + (section->info.page_count * section->page_size);
|
||||||
if (section->info.type == XEX_SECTION_CODE) {
|
if (section->info.type == XEX_SECTION_CODE) {
|
||||||
low_address_ =
|
low_address_ = std::min(low_address_, start_address);
|
||||||
static_cast<uint32_t>(std::min(low_address_, start_address));
|
high_address_ = std::max(high_address_, end_address);
|
||||||
high_address_ =
|
|
||||||
static_cast<uint32_t>(std::max(high_address_, end_address));
|
|
||||||
}
|
}
|
||||||
i += section->info.page_count;
|
i += section->info.page_count;
|
||||||
}
|
}
|
||||||
|
@ -96,8 +94,8 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||||
|
|
||||||
xe_xex2_import_info_t* import_infos;
|
xe_xex2_import_info_t* import_infos;
|
||||||
size_t import_info_count;
|
size_t import_info_count;
|
||||||
if (xe_xex2_get_import_infos(
|
if (xe_xex2_get_import_infos(xex_, library, &import_infos,
|
||||||
xex_, library, &import_infos, &import_info_count)) {
|
&import_info_count)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,8 +105,8 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||||
for (size_t n = 0; n < import_info_count; n++) {
|
for (size_t n = 0; n < import_info_count; n++) {
|
||||||
const xe_xex2_import_info_t* info = &import_infos[n];
|
const xe_xex2_import_info_t* info = &import_infos[n];
|
||||||
|
|
||||||
KernelExport* kernel_export = export_resolver->GetExportByOrdinal(
|
KernelExport* kernel_export =
|
||||||
library->name, info->ordinal);
|
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
||||||
|
|
||||||
if (kernel_export) {
|
if (kernel_export) {
|
||||||
if (info->thunk_address) {
|
if (info->thunk_address) {
|
||||||
|
@ -118,15 +116,15 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(name, poly::countof(name), "__imp_%s_%.3X", library->name,
|
snprintf(name, poly::countof(name), "__imp_%s_%.3X", library->name,
|
||||||
info->ordinal);
|
info->ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableInfo* var_info;
|
VariableInfo* var_info;
|
||||||
DeclareVariable(info->value_address, &var_info);
|
DeclareVariable(info->value_address, &var_info);
|
||||||
//var->set_name(name);
|
// var->set_name(name);
|
||||||
var_info->set_status(SymbolInfo::STATUS_DECLARED);
|
var_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||||
DefineVariable(var_info);
|
DefineVariable(var_info);
|
||||||
//var->kernel_export = kernel_export;
|
// var->kernel_export = kernel_export;
|
||||||
var_info->set_status(SymbolInfo::STATUS_DEFINED);
|
var_info->set_status(SymbolInfo::STATUS_DEFINED);
|
||||||
|
|
||||||
// Grab, if available.
|
// Grab, if available.
|
||||||
|
@ -148,7 +146,8 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||||
poly::store_and_swap<uint32_t>(slot, kernel_export->variable_ptr);
|
poly::store_and_swap<uint32_t>(slot, kernel_export->variable_ptr);
|
||||||
} else {
|
} else {
|
||||||
// Not implemented - write with a dummy value.
|
// Not implemented - write with a dummy value.
|
||||||
poly::store_and_swap<uint32_t>(slot, 0xD000BEEF | (kernel_export->ordinal & 0xFFF) << 16);
|
poly::store_and_swap<uint32_t>(
|
||||||
|
slot, 0xD000BEEF | (kernel_export->ordinal & 0xFFF) << 16);
|
||||||
XELOGCPU("WARNING: imported a variable with no value: %s",
|
XELOGCPU("WARNING: imported a variable with no value: %s",
|
||||||
kernel_export->name);
|
kernel_export->name);
|
||||||
}
|
}
|
||||||
|
@ -186,7 +185,8 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||||
FunctionInfo::ExternHandler handler = 0;
|
FunctionInfo::ExternHandler handler = 0;
|
||||||
void* handler_data = 0;
|
void* handler_data = 0;
|
||||||
if (kernel_export) {
|
if (kernel_export) {
|
||||||
handler = (FunctionInfo::ExternHandler)kernel_export->function_data.shim;
|
handler =
|
||||||
|
(FunctionInfo::ExternHandler)kernel_export->function_data.shim;
|
||||||
handler_data = kernel_export->function_data.shim_data;
|
handler_data = kernel_export->function_data.shim_data;
|
||||||
} else {
|
} else {
|
||||||
handler = (FunctionInfo::ExternHandler)UndefinedImport;
|
handler = (FunctionInfo::ExternHandler)UndefinedImport;
|
||||||
|
@ -205,7 +205,7 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XexModule::ContainsAddress(uint64_t address) {
|
bool XexModule::ContainsAddress(uint32_t address) {
|
||||||
return address >= low_address_ && address < high_address_;
|
return address >= low_address_ && address < high_address_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,180 +217,173 @@ int XexModule::FindSaveRest() {
|
||||||
// __savegprlr_14 to __savegprlr_31
|
// __savegprlr_14 to __savegprlr_31
|
||||||
// __restgprlr_14 to __restgprlr_31
|
// __restgprlr_14 to __restgprlr_31
|
||||||
static const uint32_t gprlr_code_values[] = {
|
static const uint32_t gprlr_code_values[] = {
|
||||||
0x68FFC1F9, // __savegprlr_14
|
0x68FFC1F9, // __savegprlr_14
|
||||||
0x70FFE1F9, // __savegprlr_15
|
0x70FFE1F9, // __savegprlr_15
|
||||||
0x78FF01FA, // __savegprlr_16
|
0x78FF01FA, // __savegprlr_16
|
||||||
0x80FF21FA, // __savegprlr_17
|
0x80FF21FA, // __savegprlr_17
|
||||||
0x88FF41FA, // __savegprlr_18
|
0x88FF41FA, // __savegprlr_18
|
||||||
0x90FF61FA, // __savegprlr_19
|
0x90FF61FA, // __savegprlr_19
|
||||||
0x98FF81FA, // __savegprlr_20
|
0x98FF81FA, // __savegprlr_20
|
||||||
0xA0FFA1FA, // __savegprlr_21
|
0xA0FFA1FA, // __savegprlr_21
|
||||||
0xA8FFC1FA, // __savegprlr_22
|
0xA8FFC1FA, // __savegprlr_22
|
||||||
0xB0FFE1FA, // __savegprlr_23
|
0xB0FFE1FA, // __savegprlr_23
|
||||||
0xB8FF01FB, // __savegprlr_24
|
0xB8FF01FB, // __savegprlr_24
|
||||||
0xC0FF21FB, // __savegprlr_25
|
0xC0FF21FB, // __savegprlr_25
|
||||||
0xC8FF41FB, // __savegprlr_26
|
0xC8FF41FB, // __savegprlr_26
|
||||||
0xD0FF61FB, // __savegprlr_27
|
0xD0FF61FB, // __savegprlr_27
|
||||||
0xD8FF81FB, // __savegprlr_28
|
0xD8FF81FB, // __savegprlr_28
|
||||||
0xE0FFA1FB, // __savegprlr_29
|
0xE0FFA1FB, // __savegprlr_29
|
||||||
0xE8FFC1FB, // __savegprlr_30
|
0xE8FFC1FB, // __savegprlr_30
|
||||||
0xF0FFE1FB, // __savegprlr_31
|
0xF0FFE1FB, // __savegprlr_31
|
||||||
0xF8FF8191,
|
0xF8FF8191, 0x2000804E,
|
||||||
0x2000804E,
|
0x68FFC1E9, // __restgprlr_14
|
||||||
0x68FFC1E9, // __restgprlr_14
|
0x70FFE1E9, // __restgprlr_15
|
||||||
0x70FFE1E9, // __restgprlr_15
|
0x78FF01EA, // __restgprlr_16
|
||||||
0x78FF01EA, // __restgprlr_16
|
0x80FF21EA, // __restgprlr_17
|
||||||
0x80FF21EA, // __restgprlr_17
|
0x88FF41EA, // __restgprlr_18
|
||||||
0x88FF41EA, // __restgprlr_18
|
0x90FF61EA, // __restgprlr_19
|
||||||
0x90FF61EA, // __restgprlr_19
|
0x98FF81EA, // __restgprlr_20
|
||||||
0x98FF81EA, // __restgprlr_20
|
0xA0FFA1EA, // __restgprlr_21
|
||||||
0xA0FFA1EA, // __restgprlr_21
|
0xA8FFC1EA, // __restgprlr_22
|
||||||
0xA8FFC1EA, // __restgprlr_22
|
0xB0FFE1EA, // __restgprlr_23
|
||||||
0xB0FFE1EA, // __restgprlr_23
|
0xB8FF01EB, // __restgprlr_24
|
||||||
0xB8FF01EB, // __restgprlr_24
|
0xC0FF21EB, // __restgprlr_25
|
||||||
0xC0FF21EB, // __restgprlr_25
|
0xC8FF41EB, // __restgprlr_26
|
||||||
0xC8FF41EB, // __restgprlr_26
|
0xD0FF61EB, // __restgprlr_27
|
||||||
0xD0FF61EB, // __restgprlr_27
|
0xD8FF81EB, // __restgprlr_28
|
||||||
0xD8FF81EB, // __restgprlr_28
|
0xE0FFA1EB, // __restgprlr_29
|
||||||
0xE0FFA1EB, // __restgprlr_29
|
0xE8FFC1EB, // __restgprlr_30
|
||||||
0xE8FFC1EB, // __restgprlr_30
|
0xF0FFE1EB, // __restgprlr_31
|
||||||
0xF0FFE1EB, // __restgprlr_31
|
0xF8FF8181, 0xA603887D, 0x2000804E,
|
||||||
0xF8FF8181,
|
|
||||||
0xA603887D,
|
|
||||||
0x2000804E,
|
|
||||||
};
|
};
|
||||||
// __savefpr_14 to __savefpr_31
|
// __savefpr_14 to __savefpr_31
|
||||||
// __restfpr_14 to __restfpr_31
|
// __restfpr_14 to __restfpr_31
|
||||||
static const uint32_t fpr_code_values[] = {
|
static const uint32_t fpr_code_values[] = {
|
||||||
0x70FFCCD9, // __savefpr_14
|
0x70FFCCD9, // __savefpr_14
|
||||||
0x78FFECD9, // __savefpr_15
|
0x78FFECD9, // __savefpr_15
|
||||||
0x80FF0CDA, // __savefpr_16
|
0x80FF0CDA, // __savefpr_16
|
||||||
0x88FF2CDA, // __savefpr_17
|
0x88FF2CDA, // __savefpr_17
|
||||||
0x90FF4CDA, // __savefpr_18
|
0x90FF4CDA, // __savefpr_18
|
||||||
0x98FF6CDA, // __savefpr_19
|
0x98FF6CDA, // __savefpr_19
|
||||||
0xA0FF8CDA, // __savefpr_20
|
0xA0FF8CDA, // __savefpr_20
|
||||||
0xA8FFACDA, // __savefpr_21
|
0xA8FFACDA, // __savefpr_21
|
||||||
0xB0FFCCDA, // __savefpr_22
|
0xB0FFCCDA, // __savefpr_22
|
||||||
0xB8FFECDA, // __savefpr_23
|
0xB8FFECDA, // __savefpr_23
|
||||||
0xC0FF0CDB, // __savefpr_24
|
0xC0FF0CDB, // __savefpr_24
|
||||||
0xC8FF2CDB, // __savefpr_25
|
0xC8FF2CDB, // __savefpr_25
|
||||||
0xD0FF4CDB, // __savefpr_26
|
0xD0FF4CDB, // __savefpr_26
|
||||||
0xD8FF6CDB, // __savefpr_27
|
0xD8FF6CDB, // __savefpr_27
|
||||||
0xE0FF8CDB, // __savefpr_28
|
0xE0FF8CDB, // __savefpr_28
|
||||||
0xE8FFACDB, // __savefpr_29
|
0xE8FFACDB, // __savefpr_29
|
||||||
0xF0FFCCDB, // __savefpr_30
|
0xF0FFCCDB, // __savefpr_30
|
||||||
0xF8FFECDB, // __savefpr_31
|
0xF8FFECDB, // __savefpr_31
|
||||||
0x2000804E,
|
0x2000804E,
|
||||||
0x70FFCCC9, // __restfpr_14
|
0x70FFCCC9, // __restfpr_14
|
||||||
0x78FFECC9, // __restfpr_15
|
0x78FFECC9, // __restfpr_15
|
||||||
0x80FF0CCA, // __restfpr_16
|
0x80FF0CCA, // __restfpr_16
|
||||||
0x88FF2CCA, // __restfpr_17
|
0x88FF2CCA, // __restfpr_17
|
||||||
0x90FF4CCA, // __restfpr_18
|
0x90FF4CCA, // __restfpr_18
|
||||||
0x98FF6CCA, // __restfpr_19
|
0x98FF6CCA, // __restfpr_19
|
||||||
0xA0FF8CCA, // __restfpr_20
|
0xA0FF8CCA, // __restfpr_20
|
||||||
0xA8FFACCA, // __restfpr_21
|
0xA8FFACCA, // __restfpr_21
|
||||||
0xB0FFCCCA, // __restfpr_22
|
0xB0FFCCCA, // __restfpr_22
|
||||||
0xB8FFECCA, // __restfpr_23
|
0xB8FFECCA, // __restfpr_23
|
||||||
0xC0FF0CCB, // __restfpr_24
|
0xC0FF0CCB, // __restfpr_24
|
||||||
0xC8FF2CCB, // __restfpr_25
|
0xC8FF2CCB, // __restfpr_25
|
||||||
0xD0FF4CCB, // __restfpr_26
|
0xD0FF4CCB, // __restfpr_26
|
||||||
0xD8FF6CCB, // __restfpr_27
|
0xD8FF6CCB, // __restfpr_27
|
||||||
0xE0FF8CCB, // __restfpr_28
|
0xE0FF8CCB, // __restfpr_28
|
||||||
0xE8FFACCB, // __restfpr_29
|
0xE8FFACCB, // __restfpr_29
|
||||||
0xF0FFCCCB, // __restfpr_30
|
0xF0FFCCCB, // __restfpr_30
|
||||||
0xF8FFECCB, // __restfpr_31
|
0xF8FFECCB, // __restfpr_31
|
||||||
0x2000804E,
|
0x2000804E,
|
||||||
};
|
};
|
||||||
// __savevmx_14 to __savevmx_31
|
// __savevmx_14 to __savevmx_31
|
||||||
// __savevmx_64 to __savevmx_127
|
// __savevmx_64 to __savevmx_127
|
||||||
// __restvmx_14 to __restvmx_31
|
// __restvmx_14 to __restvmx_31
|
||||||
// __restvmx_64 to __restvmx_127
|
// __restvmx_64 to __restvmx_127
|
||||||
static const uint32_t vmx_code_values[] = {
|
static const uint32_t vmx_code_values[] = {
|
||||||
0xE0FE6039, // __savevmx_14
|
0xE0FE6039, // __savevmx_14
|
||||||
0xCE61CB7D, 0xF0FE6039, 0xCE61EB7D, 0x00FF6039, 0xCE610B7E, 0x10FF6039,
|
0xCE61CB7D, 0xF0FE6039, 0xCE61EB7D, 0x00FF6039, 0xCE610B7E, 0x10FF6039,
|
||||||
0xCE612B7E, 0x20FF6039, 0xCE614B7E, 0x30FF6039, 0xCE616B7E, 0x40FF6039,
|
0xCE612B7E, 0x20FF6039, 0xCE614B7E, 0x30FF6039, 0xCE616B7E, 0x40FF6039,
|
||||||
0xCE618B7E, 0x50FF6039, 0xCE61AB7E, 0x60FF6039, 0xCE61CB7E, 0x70FF6039,
|
0xCE618B7E, 0x50FF6039, 0xCE61AB7E, 0x60FF6039, 0xCE61CB7E, 0x70FF6039,
|
||||||
0xCE61EB7E, 0x80FF6039, 0xCE610B7F, 0x90FF6039, 0xCE612B7F, 0xA0FF6039,
|
0xCE61EB7E, 0x80FF6039, 0xCE610B7F, 0x90FF6039, 0xCE612B7F, 0xA0FF6039,
|
||||||
0xCE614B7F, 0xB0FF6039, 0xCE616B7F, 0xC0FF6039, 0xCE618B7F, 0xD0FF6039,
|
0xCE614B7F, 0xB0FF6039, 0xCE616B7F, 0xC0FF6039, 0xCE618B7F, 0xD0FF6039,
|
||||||
0xCE61AB7F, 0xE0FF6039, 0xCE61CB7F,
|
0xCE61AB7F, 0xE0FF6039, 0xCE61CB7F, 0xF0FF6039, // __savevmx_31
|
||||||
0xF0FF6039, // __savevmx_31
|
0xCE61EB7F, 0x2000804E,
|
||||||
0xCE61EB7F,
|
|
||||||
0x2000804E,
|
|
||||||
|
|
||||||
0x00FC6039, // __savevmx_64
|
0x00FC6039, // __savevmx_64
|
||||||
0xCB610B10, 0x10FC6039, 0xCB612B10, 0x20FC6039, 0xCB614B10, 0x30FC6039,
|
0xCB610B10, 0x10FC6039, 0xCB612B10, 0x20FC6039, 0xCB614B10, 0x30FC6039,
|
||||||
0xCB616B10, 0x40FC6039, 0xCB618B10, 0x50FC6039, 0xCB61AB10, 0x60FC6039,
|
0xCB616B10, 0x40FC6039, 0xCB618B10, 0x50FC6039, 0xCB61AB10, 0x60FC6039,
|
||||||
0xCB61CB10, 0x70FC6039, 0xCB61EB10, 0x80FC6039, 0xCB610B11, 0x90FC6039,
|
0xCB61CB10, 0x70FC6039, 0xCB61EB10, 0x80FC6039, 0xCB610B11, 0x90FC6039,
|
||||||
0xCB612B11, 0xA0FC6039, 0xCB614B11, 0xB0FC6039, 0xCB616B11, 0xC0FC6039,
|
0xCB612B11, 0xA0FC6039, 0xCB614B11, 0xB0FC6039, 0xCB616B11, 0xC0FC6039,
|
||||||
0xCB618B11, 0xD0FC6039, 0xCB61AB11, 0xE0FC6039, 0xCB61CB11, 0xF0FC6039,
|
0xCB618B11, 0xD0FC6039, 0xCB61AB11, 0xE0FC6039, 0xCB61CB11, 0xF0FC6039,
|
||||||
0xCB61EB11, 0x00FD6039, 0xCB610B12, 0x10FD6039, 0xCB612B12, 0x20FD6039,
|
0xCB61EB11, 0x00FD6039, 0xCB610B12, 0x10FD6039, 0xCB612B12, 0x20FD6039,
|
||||||
0xCB614B12, 0x30FD6039, 0xCB616B12, 0x40FD6039, 0xCB618B12, 0x50FD6039,
|
0xCB614B12, 0x30FD6039, 0xCB616B12, 0x40FD6039, 0xCB618B12, 0x50FD6039,
|
||||||
0xCB61AB12, 0x60FD6039, 0xCB61CB12, 0x70FD6039, 0xCB61EB12, 0x80FD6039,
|
0xCB61AB12, 0x60FD6039, 0xCB61CB12, 0x70FD6039, 0xCB61EB12, 0x80FD6039,
|
||||||
0xCB610B13, 0x90FD6039, 0xCB612B13, 0xA0FD6039, 0xCB614B13, 0xB0FD6039,
|
0xCB610B13, 0x90FD6039, 0xCB612B13, 0xA0FD6039, 0xCB614B13, 0xB0FD6039,
|
||||||
0xCB616B13, 0xC0FD6039, 0xCB618B13, 0xD0FD6039, 0xCB61AB13, 0xE0FD6039,
|
0xCB616B13, 0xC0FD6039, 0xCB618B13, 0xD0FD6039, 0xCB61AB13, 0xE0FD6039,
|
||||||
0xCB61CB13, 0xF0FD6039, 0xCB61EB13, 0x00FE6039, 0xCF610B10, 0x10FE6039,
|
0xCB61CB13, 0xF0FD6039, 0xCB61EB13, 0x00FE6039, 0xCF610B10, 0x10FE6039,
|
||||||
0xCF612B10, 0x20FE6039, 0xCF614B10, 0x30FE6039, 0xCF616B10, 0x40FE6039,
|
0xCF612B10, 0x20FE6039, 0xCF614B10, 0x30FE6039, 0xCF616B10, 0x40FE6039,
|
||||||
0xCF618B10, 0x50FE6039, 0xCF61AB10, 0x60FE6039, 0xCF61CB10, 0x70FE6039,
|
0xCF618B10, 0x50FE6039, 0xCF61AB10, 0x60FE6039, 0xCF61CB10, 0x70FE6039,
|
||||||
0xCF61EB10, 0x80FE6039, 0xCF610B11, 0x90FE6039, 0xCF612B11, 0xA0FE6039,
|
0xCF61EB10, 0x80FE6039, 0xCF610B11, 0x90FE6039, 0xCF612B11, 0xA0FE6039,
|
||||||
0xCF614B11, 0xB0FE6039, 0xCF616B11, 0xC0FE6039, 0xCF618B11, 0xD0FE6039,
|
0xCF614B11, 0xB0FE6039, 0xCF616B11, 0xC0FE6039, 0xCF618B11, 0xD0FE6039,
|
||||||
0xCF61AB11, 0xE0FE6039, 0xCF61CB11, 0xF0FE6039, 0xCF61EB11, 0x00FF6039,
|
0xCF61AB11, 0xE0FE6039, 0xCF61CB11, 0xF0FE6039, 0xCF61EB11, 0x00FF6039,
|
||||||
0xCF610B12, 0x10FF6039, 0xCF612B12, 0x20FF6039, 0xCF614B12, 0x30FF6039,
|
0xCF610B12, 0x10FF6039, 0xCF612B12, 0x20FF6039, 0xCF614B12, 0x30FF6039,
|
||||||
0xCF616B12, 0x40FF6039, 0xCF618B12, 0x50FF6039, 0xCF61AB12, 0x60FF6039,
|
0xCF616B12, 0x40FF6039, 0xCF618B12, 0x50FF6039, 0xCF61AB12, 0x60FF6039,
|
||||||
0xCF61CB12, 0x70FF6039, 0xCF61EB12, 0x80FF6039, 0xCF610B13, 0x90FF6039,
|
0xCF61CB12, 0x70FF6039, 0xCF61EB12, 0x80FF6039, 0xCF610B13, 0x90FF6039,
|
||||||
0xCF612B13, 0xA0FF6039, 0xCF614B13, 0xB0FF6039, 0xCF616B13, 0xC0FF6039,
|
0xCF612B13, 0xA0FF6039, 0xCF614B13, 0xB0FF6039, 0xCF616B13, 0xC0FF6039,
|
||||||
0xCF618B13, 0xD0FF6039, 0xCF61AB13, 0xE0FF6039, 0xCF61CB13,
|
0xCF618B13, 0xD0FF6039, 0xCF61AB13, 0xE0FF6039, 0xCF61CB13,
|
||||||
0xF0FF6039, // __savevmx_127
|
0xF0FF6039, // __savevmx_127
|
||||||
0xCF61EB13,
|
0xCF61EB13, 0x2000804E,
|
||||||
0x2000804E,
|
|
||||||
|
|
||||||
0xE0FE6039, // __restvmx_14
|
0xE0FE6039, // __restvmx_14
|
||||||
0xCE60CB7D, 0xF0FE6039, 0xCE60EB7D, 0x00FF6039, 0xCE600B7E, 0x10FF6039,
|
0xCE60CB7D, 0xF0FE6039, 0xCE60EB7D, 0x00FF6039, 0xCE600B7E, 0x10FF6039,
|
||||||
0xCE602B7E, 0x20FF6039, 0xCE604B7E, 0x30FF6039, 0xCE606B7E, 0x40FF6039,
|
0xCE602B7E, 0x20FF6039, 0xCE604B7E, 0x30FF6039, 0xCE606B7E, 0x40FF6039,
|
||||||
0xCE608B7E, 0x50FF6039, 0xCE60AB7E, 0x60FF6039, 0xCE60CB7E, 0x70FF6039,
|
0xCE608B7E, 0x50FF6039, 0xCE60AB7E, 0x60FF6039, 0xCE60CB7E, 0x70FF6039,
|
||||||
0xCE60EB7E, 0x80FF6039, 0xCE600B7F, 0x90FF6039, 0xCE602B7F, 0xA0FF6039,
|
0xCE60EB7E, 0x80FF6039, 0xCE600B7F, 0x90FF6039, 0xCE602B7F, 0xA0FF6039,
|
||||||
0xCE604B7F, 0xB0FF6039, 0xCE606B7F, 0xC0FF6039, 0xCE608B7F, 0xD0FF6039,
|
0xCE604B7F, 0xB0FF6039, 0xCE606B7F, 0xC0FF6039, 0xCE608B7F, 0xD0FF6039,
|
||||||
0xCE60AB7F, 0xE0FF6039, 0xCE60CB7F, 0xF0FF6039, // __restvmx_31
|
0xCE60AB7F, 0xE0FF6039, 0xCE60CB7F, 0xF0FF6039, // __restvmx_31
|
||||||
0xCE60EB7F,
|
0xCE60EB7F, 0x2000804E,
|
||||||
0x2000804E,
|
|
||||||
|
|
||||||
0x00FC6039, // __restvmx_64
|
0x00FC6039, // __restvmx_64
|
||||||
0xCB600B10, 0x10FC6039, 0xCB602B10, 0x20FC6039, 0xCB604B10, 0x30FC6039,
|
0xCB600B10, 0x10FC6039, 0xCB602B10, 0x20FC6039, 0xCB604B10, 0x30FC6039,
|
||||||
0xCB606B10, 0x40FC6039, 0xCB608B10, 0x50FC6039, 0xCB60AB10, 0x60FC6039,
|
0xCB606B10, 0x40FC6039, 0xCB608B10, 0x50FC6039, 0xCB60AB10, 0x60FC6039,
|
||||||
0xCB60CB10, 0x70FC6039, 0xCB60EB10, 0x80FC6039, 0xCB600B11, 0x90FC6039,
|
0xCB60CB10, 0x70FC6039, 0xCB60EB10, 0x80FC6039, 0xCB600B11, 0x90FC6039,
|
||||||
0xCB602B11, 0xA0FC6039, 0xCB604B11, 0xB0FC6039, 0xCB606B11, 0xC0FC6039,
|
0xCB602B11, 0xA0FC6039, 0xCB604B11, 0xB0FC6039, 0xCB606B11, 0xC0FC6039,
|
||||||
0xCB608B11, 0xD0FC6039, 0xCB60AB11, 0xE0FC6039, 0xCB60CB11, 0xF0FC6039,
|
0xCB608B11, 0xD0FC6039, 0xCB60AB11, 0xE0FC6039, 0xCB60CB11, 0xF0FC6039,
|
||||||
0xCB60EB11, 0x00FD6039, 0xCB600B12, 0x10FD6039, 0xCB602B12, 0x20FD6039,
|
0xCB60EB11, 0x00FD6039, 0xCB600B12, 0x10FD6039, 0xCB602B12, 0x20FD6039,
|
||||||
0xCB604B12, 0x30FD6039, 0xCB606B12, 0x40FD6039, 0xCB608B12, 0x50FD6039,
|
0xCB604B12, 0x30FD6039, 0xCB606B12, 0x40FD6039, 0xCB608B12, 0x50FD6039,
|
||||||
0xCB60AB12, 0x60FD6039, 0xCB60CB12, 0x70FD6039, 0xCB60EB12, 0x80FD6039,
|
0xCB60AB12, 0x60FD6039, 0xCB60CB12, 0x70FD6039, 0xCB60EB12, 0x80FD6039,
|
||||||
0xCB600B13, 0x90FD6039, 0xCB602B13, 0xA0FD6039, 0xCB604B13, 0xB0FD6039,
|
0xCB600B13, 0x90FD6039, 0xCB602B13, 0xA0FD6039, 0xCB604B13, 0xB0FD6039,
|
||||||
0xCB606B13, 0xC0FD6039, 0xCB608B13, 0xD0FD6039, 0xCB60AB13, 0xE0FD6039,
|
0xCB606B13, 0xC0FD6039, 0xCB608B13, 0xD0FD6039, 0xCB60AB13, 0xE0FD6039,
|
||||||
0xCB60CB13, 0xF0FD6039, 0xCB60EB13, 0x00FE6039, 0xCF600B10, 0x10FE6039,
|
0xCB60CB13, 0xF0FD6039, 0xCB60EB13, 0x00FE6039, 0xCF600B10, 0x10FE6039,
|
||||||
0xCF602B10, 0x20FE6039, 0xCF604B10, 0x30FE6039, 0xCF606B10, 0x40FE6039,
|
0xCF602B10, 0x20FE6039, 0xCF604B10, 0x30FE6039, 0xCF606B10, 0x40FE6039,
|
||||||
0xCF608B10, 0x50FE6039, 0xCF60AB10, 0x60FE6039, 0xCF60CB10, 0x70FE6039,
|
0xCF608B10, 0x50FE6039, 0xCF60AB10, 0x60FE6039, 0xCF60CB10, 0x70FE6039,
|
||||||
0xCF60EB10, 0x80FE6039, 0xCF600B11, 0x90FE6039, 0xCF602B11, 0xA0FE6039,
|
0xCF60EB10, 0x80FE6039, 0xCF600B11, 0x90FE6039, 0xCF602B11, 0xA0FE6039,
|
||||||
0xCF604B11, 0xB0FE6039, 0xCF606B11, 0xC0FE6039, 0xCF608B11, 0xD0FE6039,
|
0xCF604B11, 0xB0FE6039, 0xCF606B11, 0xC0FE6039, 0xCF608B11, 0xD0FE6039,
|
||||||
0xCF60AB11, 0xE0FE6039, 0xCF60CB11, 0xF0FE6039, 0xCF60EB11, 0x00FF6039,
|
0xCF60AB11, 0xE0FE6039, 0xCF60CB11, 0xF0FE6039, 0xCF60EB11, 0x00FF6039,
|
||||||
0xCF600B12, 0x10FF6039, 0xCF602B12, 0x20FF6039, 0xCF604B12, 0x30FF6039,
|
0xCF600B12, 0x10FF6039, 0xCF602B12, 0x20FF6039, 0xCF604B12, 0x30FF6039,
|
||||||
0xCF606B12, 0x40FF6039, 0xCF608B12, 0x50FF6039, 0xCF60AB12, 0x60FF6039,
|
0xCF606B12, 0x40FF6039, 0xCF608B12, 0x50FF6039, 0xCF60AB12, 0x60FF6039,
|
||||||
0xCF60CB12, 0x70FF6039, 0xCF60EB12, 0x80FF6039, 0xCF600B13, 0x90FF6039,
|
0xCF60CB12, 0x70FF6039, 0xCF60EB12, 0x80FF6039, 0xCF600B13, 0x90FF6039,
|
||||||
0xCF602B13, 0xA0FF6039, 0xCF604B13, 0xB0FF6039, 0xCF606B13, 0xC0FF6039,
|
0xCF602B13, 0xA0FF6039, 0xCF604B13, 0xB0FF6039, 0xCF606B13, 0xC0FF6039,
|
||||||
0xCF608B13, 0xD0FF6039, 0xCF60AB13, 0xE0FF6039, 0xCF60CB13,
|
0xCF608B13, 0xD0FF6039, 0xCF60AB13, 0xE0FF6039, 0xCF60CB13,
|
||||||
0xF0FF6039, // __restvmx_127
|
0xF0FF6039, // __restvmx_127
|
||||||
0xCF60EB13,
|
0xCF60EB13, 0x2000804E,
|
||||||
0x2000804E,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(benvanik): these are almost always sequential, if present.
|
// TODO(benvanik): these are almost always sequential, if present.
|
||||||
// It'd be smarter to search around the other ones to prevent
|
// It'd be smarter to search around the other ones to prevent
|
||||||
// 3 full module scans.
|
// 3 full module scans.
|
||||||
uint64_t gplr_start = 0;
|
uint32_t gplr_start = 0;
|
||||||
uint64_t fpr_start = 0;
|
uint32_t fpr_start = 0;
|
||||||
uint64_t vmx_start = 0;
|
uint32_t vmx_start = 0;
|
||||||
const xe_xex2_header_t* header = xe_xex2_get_header(xex_);
|
const xe_xex2_header_t* header = xe_xex2_get_header(xex_);
|
||||||
for (size_t n = 0, i = 0; n < header->section_count; n++) {
|
for (uint32_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 size_t start_address = header->exe_address + (i * section->page_size);
|
const uint32_t start_address =
|
||||||
const size_t end_address =
|
header->exe_address + (i * section->page_size);
|
||||||
|
const uint32_t end_address =
|
||||||
start_address + (section->info.page_count * section->page_size);
|
start_address + (section->info.page_count * section->page_size);
|
||||||
if (section->info.type == XEX_SECTION_CODE) {
|
if (section->info.type == XEX_SECTION_CODE) {
|
||||||
if (!gplr_start) {
|
if (!gplr_start) {
|
||||||
|
@ -418,7 +411,7 @@ int XexModule::FindSaveRest() {
|
||||||
// Add function stubs.
|
// Add function stubs.
|
||||||
char name[32];
|
char name[32];
|
||||||
if (gplr_start) {
|
if (gplr_start) {
|
||||||
uint64_t address = gplr_start;
|
uint32_t address = gplr_start;
|
||||||
for (int n = 14; n <= 31; n++) {
|
for (int n = 14; n <= 31; n++) {
|
||||||
snprintf(name, poly::countof(name), "__savegprlr_%d", n);
|
snprintf(name, poly::countof(name), "__savegprlr_%d", n);
|
||||||
FunctionInfo* symbol_info;
|
FunctionInfo* symbol_info;
|
||||||
|
@ -446,7 +439,7 @@ int XexModule::FindSaveRest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fpr_start) {
|
if (fpr_start) {
|
||||||
uint64_t address = fpr_start;
|
uint32_t address = fpr_start;
|
||||||
for (int n = 14; n <= 31; n++) {
|
for (int n = 14; n <= 31; n++) {
|
||||||
snprintf(name, poly::countof(name), "__savefpr_%d", n);
|
snprintf(name, poly::countof(name), "__savefpr_%d", n);
|
||||||
FunctionInfo* symbol_info;
|
FunctionInfo* symbol_info;
|
||||||
|
@ -479,7 +472,7 @@ int XexModule::FindSaveRest() {
|
||||||
// 64-127 save
|
// 64-127 save
|
||||||
// 14-31 rest
|
// 14-31 rest
|
||||||
// 64-127 rest
|
// 64-127 rest
|
||||||
uint64_t address = vmx_start;
|
uint32_t address = vmx_start;
|
||||||
for (int n = 14; n <= 31; n++) {
|
for (int n = 14; n <= 31; n++) {
|
||||||
snprintf(name, poly::countof(name), "__savevmx_%d", n);
|
snprintf(name, poly::countof(name), "__savevmx_%d", n);
|
||||||
FunctionInfo* symbol_info;
|
FunctionInfo* symbol_info;
|
||||||
|
|
|
@ -22,8 +22,8 @@ namespace cpu {
|
||||||
class Runtime;
|
class Runtime;
|
||||||
|
|
||||||
class XexModule : public xe::cpu::Module {
|
class XexModule : public xe::cpu::Module {
|
||||||
public:
|
public:
|
||||||
XexModule(Runtime* runtime);
|
XexModule(Runtime* runtime);
|
||||||
virtual ~XexModule();
|
virtual ~XexModule();
|
||||||
|
|
||||||
xe_xex2_ref xex() const { return xex_; }
|
xe_xex2_ref xex() const { return xex_; }
|
||||||
|
@ -32,22 +32,22 @@ public:
|
||||||
|
|
||||||
const std::string& name() const override { return name_; }
|
const std::string& name() const override { return name_; }
|
||||||
|
|
||||||
bool ContainsAddress(uint64_t address) override;
|
bool ContainsAddress(uint32_t address) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int SetupImports(xe_xex2_ref xex);
|
int SetupImports(xe_xex2_ref xex);
|
||||||
int SetupLibraryImports(const xe_xex2_import_library_t* library);
|
int SetupLibraryImports(const xe_xex2_import_library_t* library);
|
||||||
int FindSaveRest();
|
int FindSaveRest();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Runtime* runtime_;
|
Runtime* runtime_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
std::string path_;
|
std::string path_;
|
||||||
xe_xex2_ref xex_;
|
xe_xex2_ref xex_;
|
||||||
|
|
||||||
uint64_t base_address_;
|
uint32_t base_address_;
|
||||||
uint64_t low_address_;
|
uint32_t low_address_;
|
||||||
uint64_t high_address_;
|
uint32_t high_address_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
|
|
|
@ -15,11 +15,9 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
typedef struct xe_ppc_state xe_ppc_state_t;
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
|
||||||
typedef void (*xe_kernel_export_shim_fn)(xe_ppc_state_t*, void*);
|
typedef void (*xe_kernel_export_shim_fn)(void*, void*);
|
||||||
|
|
||||||
class KernelExport {
|
class KernelExport {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -50,7 +50,7 @@ int xe_xex2_read_header(const uint8_t *addr, const size_t length,
|
||||||
xe_xex2_header_t *header);
|
xe_xex2_header_t *header);
|
||||||
int xe_xex2_decrypt_key(xe_xex2_header_t *header);
|
int xe_xex2_decrypt_key(xe_xex2_header_t *header);
|
||||||
int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr,
|
int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr,
|
||||||
const size_t xex_length, xe::Memory *memory);
|
const uint32_t xex_length, xe::Memory *memory);
|
||||||
int xe_xex2_load_pe(xe_xex2_ref xex);
|
int xe_xex2_load_pe(xe_xex2_ref xex);
|
||||||
int xe_xex2_find_import_infos(xe_xex2_ref xex,
|
int xe_xex2_find_import_infos(xe_xex2_ref xex,
|
||||||
const xe_xex2_import_library_t *library);
|
const xe_xex2_import_library_t *library);
|
||||||
|
@ -67,7 +67,8 @@ xe_xex2_ref xe_xex2_load(xe::Memory *memory, const void *addr,
|
||||||
|
|
||||||
XEEXPECTZERO(xe_xex2_decrypt_key(&xex->header));
|
XEEXPECTZERO(xe_xex2_decrypt_key(&xex->header));
|
||||||
|
|
||||||
XEEXPECTZERO(xe_xex2_read_image(xex, (const uint8_t *)addr, length, memory));
|
XEEXPECTZERO(
|
||||||
|
xe_xex2_read_image(xex, (const uint8_t *)addr, uint32_t(length), memory));
|
||||||
|
|
||||||
XEEXPECTZERO(xe_xex2_load_pe(xex));
|
XEEXPECTZERO(xe_xex2_load_pe(xex));
|
||||||
|
|
||||||
|
@ -525,12 +526,12 @@ void xe_xex2_decrypt_buffer(const uint8_t *session_key,
|
||||||
|
|
||||||
int xe_xex2_read_image_uncompressed(const xe_xex2_header_t *header,
|
int xe_xex2_read_image_uncompressed(const xe_xex2_header_t *header,
|
||||||
const uint8_t *xex_addr,
|
const uint8_t *xex_addr,
|
||||||
const size_t xex_length,
|
const uint32_t xex_length,
|
||||||
xe::Memory *memory) {
|
xe::Memory *memory) {
|
||||||
// Allocate in-place the XEX memory.
|
// Allocate in-place the XEX memory.
|
||||||
const size_t exe_length = xex_length - header->exe_offset;
|
const uint32_t exe_length = xex_length - header->exe_offset;
|
||||||
size_t uncompressed_size = exe_length;
|
uint32_t uncompressed_size = exe_length;
|
||||||
uint32_t alloc_result = (uint32_t)memory->HeapAlloc(
|
uint32_t alloc_result = memory->HeapAlloc(
|
||||||
header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO);
|
header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO);
|
||||||
if (!alloc_result) {
|
if (!alloc_result) {
|
||||||
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
||||||
|
@ -562,24 +563,24 @@ int xe_xex2_read_image_uncompressed(const xe_xex2_header_t *header,
|
||||||
|
|
||||||
int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header,
|
int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header,
|
||||||
const uint8_t *xex_addr,
|
const uint8_t *xex_addr,
|
||||||
const size_t xex_length,
|
const uint32_t xex_length,
|
||||||
xe::Memory *memory) {
|
xe::Memory *memory) {
|
||||||
const size_t exe_length = xex_length - header->exe_offset;
|
const uint32_t exe_length = xex_length - header->exe_offset;
|
||||||
const uint8_t *source_buffer = (const uint8_t *)xex_addr + header->exe_offset;
|
const uint8_t *source_buffer = (const uint8_t *)xex_addr + header->exe_offset;
|
||||||
const uint8_t *p = source_buffer;
|
const uint8_t *p = source_buffer;
|
||||||
|
|
||||||
// Calculate uncompressed length.
|
// Calculate uncompressed length.
|
||||||
size_t uncompressed_size = 0;
|
uint32_t uncompressed_size = 0;
|
||||||
const xe_xex2_file_basic_compression_info_t *comp_info =
|
const xe_xex2_file_basic_compression_info_t *comp_info =
|
||||||
&header->file_format_info.compression_info.basic;
|
&header->file_format_info.compression_info.basic;
|
||||||
for (size_t n = 0; n < comp_info->block_count; n++) {
|
for (uint32_t n = 0; n < comp_info->block_count; n++) {
|
||||||
const size_t data_size = comp_info->blocks[n].data_size;
|
const uint32_t data_size = comp_info->blocks[n].data_size;
|
||||||
const size_t zero_size = comp_info->blocks[n].zero_size;
|
const uint32_t zero_size = comp_info->blocks[n].zero_size;
|
||||||
uncompressed_size += data_size + zero_size;
|
uncompressed_size += data_size + zero_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate in-place the XEX memory.
|
// Allocate in-place the XEX memory.
|
||||||
uint32_t alloc_result = (uint32_t)memory->HeapAlloc(
|
uint32_t alloc_result = memory->HeapAlloc(
|
||||||
header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO);
|
header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO);
|
||||||
if (!alloc_result) {
|
if (!alloc_result) {
|
||||||
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
||||||
|
@ -594,8 +595,8 @@ int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header,
|
||||||
int32_t Nr = rijndaelKeySetupDec(rk, header->session_key, 128);
|
int32_t Nr = rijndaelKeySetupDec(rk, header->session_key, 128);
|
||||||
|
|
||||||
for (size_t n = 0; n < comp_info->block_count; n++) {
|
for (size_t n = 0; n < comp_info->block_count; n++) {
|
||||||
const size_t data_size = comp_info->blocks[n].data_size;
|
const uint32_t data_size = comp_info->blocks[n].data_size;
|
||||||
const size_t zero_size = comp_info->blocks[n].zero_size;
|
const uint32_t zero_size = comp_info->blocks[n].zero_size;
|
||||||
|
|
||||||
switch (header->file_format_info.encryption_type) {
|
switch (header->file_format_info.encryption_type) {
|
||||||
case XEX_ENCRYPTION_NONE:
|
case XEX_ENCRYPTION_NONE:
|
||||||
|
@ -634,8 +635,9 @@ int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header,
|
||||||
|
|
||||||
int xe_xex2_read_image_compressed(const xe_xex2_header_t *header,
|
int xe_xex2_read_image_compressed(const xe_xex2_header_t *header,
|
||||||
const uint8_t *xex_addr,
|
const uint8_t *xex_addr,
|
||||||
const size_t xex_length, xe::Memory *memory) {
|
const uint32_t xex_length,
|
||||||
const size_t exe_length = xex_length - header->exe_offset;
|
xe::Memory *memory) {
|
||||||
|
const uint32_t exe_length = xex_length - header->exe_offset;
|
||||||
const uint8_t *exe_buffer = (const uint8_t *)xex_addr + header->exe_offset;
|
const uint8_t *exe_buffer = (const uint8_t *)xex_addr + header->exe_offset;
|
||||||
|
|
||||||
// src -> dest:
|
// src -> dest:
|
||||||
|
@ -653,7 +655,7 @@ int xe_xex2_read_image_compressed(const xe_xex2_header_t *header,
|
||||||
uint8_t *d = NULL;
|
uint8_t *d = NULL;
|
||||||
uint8_t *deblock_buffer = NULL;
|
uint8_t *deblock_buffer = NULL;
|
||||||
size_t block_size = 0;
|
size_t block_size = 0;
|
||||||
size_t uncompressed_size = 0;
|
uint32_t uncompressed_size = 0;
|
||||||
struct mspack_system *sys = NULL;
|
struct mspack_system *sys = NULL;
|
||||||
mspack_memory_file *lzxsrc = NULL;
|
mspack_memory_file *lzxsrc = NULL;
|
||||||
mspack_memory_file *lzxdst = NULL;
|
mspack_memory_file *lzxdst = NULL;
|
||||||
|
@ -714,7 +716,7 @@ int xe_xex2_read_image_compressed(const xe_xex2_header_t *header,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate in-place the XEX memory.
|
// Allocate in-place the XEX memory.
|
||||||
uint32_t alloc_result = (uint32_t)memory->HeapAlloc(
|
uint32_t alloc_result = memory->HeapAlloc(
|
||||||
header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO);
|
header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO);
|
||||||
if (!alloc_result) {
|
if (!alloc_result) {
|
||||||
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
||||||
|
@ -767,7 +769,7 @@ XECLEANUP:
|
||||||
}
|
}
|
||||||
|
|
||||||
int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr,
|
int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr,
|
||||||
const size_t xex_length, xe::Memory *memory) {
|
const uint32_t xex_length, xe::Memory *memory) {
|
||||||
const xe_xex2_header_t *header = &xex->header;
|
const xe_xex2_header_t *header = &xex->header;
|
||||||
switch (header->file_format_info.compression_type) {
|
switch (header->file_format_info.compression_type) {
|
||||||
case XEX_COMPRESSION_NONE:
|
case XEX_COMPRESSION_NONE:
|
||||||
|
|
|
@ -410,7 +410,7 @@ typedef enum {
|
||||||
} xe_xex2_section_type;
|
} xe_xex2_section_type;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t page_size;
|
uint32_t page_size;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
xe_xex2_section_type type : 4;
|
xe_xex2_section_type type : 4;
|
||||||
|
|
|
@ -292,7 +292,8 @@ SHIM_CALL RtlUnicodeStringToAnsiString_shim(PPCContext* ppc_state,
|
||||||
|
|
||||||
X_STATUS result = X_STATUS_SUCCESS;
|
X_STATUS result = X_STATUS_SUCCESS;
|
||||||
if (alloc_dest) {
|
if (alloc_dest) {
|
||||||
auto buffer_ptr = state->memory()->HeapAlloc(0, ansi_str.size() + 1, 0);
|
auto buffer_ptr =
|
||||||
|
state->memory()->HeapAlloc(0, uint32_t(ansi_str.size() + 1), 0);
|
||||||
memcpy(SHIM_MEM_ADDR(buffer_ptr), ansi_str.data(), ansi_str.size() + 1);
|
memcpy(SHIM_MEM_ADDR(buffer_ptr), ansi_str.data(), ansi_str.size() + 1);
|
||||||
SHIM_SET_MEM_16(destination_ptr + 0,
|
SHIM_SET_MEM_16(destination_ptr + 0,
|
||||||
static_cast<uint16_t>(ansi_str.size()));
|
static_cast<uint16_t>(ansi_str.size()));
|
||||||
|
|
|
@ -80,22 +80,22 @@ DEFINE_bool(scribble_heap, false,
|
||||||
* this.
|
* this.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MEMORY_PHYSICAL_HEAP_LOW 0x00010000
|
const uint32_t kMemoryPhysicalHeapLow = 0x00010000;
|
||||||
#define MEMORY_PHYSICAL_HEAP_HIGH 0x20000000
|
const uint32_t kMemoryPhysicalHeapHigh = 0x20000000;
|
||||||
#define MEMORY_VIRTUAL_HEAP_LOW 0x20000000
|
const uint32_t kMemoryVirtualHeapLow = 0x20000000;
|
||||||
#define MEMORY_VIRTUAL_HEAP_HIGH 0x40000000
|
const uint32_t kMemoryVirtualHeapHigh = 0x40000000;
|
||||||
|
|
||||||
class xe::MemoryHeap {
|
class xe::MemoryHeap {
|
||||||
public:
|
public:
|
||||||
MemoryHeap(Memory* memory, bool is_physical);
|
MemoryHeap(Memory* memory, bool is_physical);
|
||||||
~MemoryHeap();
|
~MemoryHeap();
|
||||||
|
|
||||||
int Initialize(uint64_t low, uint64_t high);
|
int Initialize(uint32_t low, uint32_t high);
|
||||||
|
|
||||||
uint64_t Alloc(uint64_t base_address, size_t size, uint32_t flags,
|
uint32_t Alloc(uint32_t base_address, uint32_t size, uint32_t flags,
|
||||||
uint32_t alignment);
|
uint32_t alignment);
|
||||||
uint64_t Free(uint64_t address, size_t size);
|
uint32_t Free(uint32_t address, uint32_t size);
|
||||||
size_t QuerySize(uint64_t base_address);
|
uint32_t QuerySize(uint32_t base_address);
|
||||||
|
|
||||||
void Dump();
|
void Dump();
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ class xe::MemoryHeap {
|
||||||
uint32_t heap_id_;
|
uint32_t heap_id_;
|
||||||
bool is_physical_;
|
bool is_physical_;
|
||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
size_t size_;
|
uint32_t size_;
|
||||||
uint8_t* ptr_;
|
uint8_t* ptr_;
|
||||||
mspace space_;
|
mspace space_;
|
||||||
};
|
};
|
||||||
|
@ -122,7 +122,7 @@ Memory::Memory()
|
||||||
trace_base_(0),
|
trace_base_(0),
|
||||||
mapping_(0),
|
mapping_(0),
|
||||||
mapping_base_(nullptr) {
|
mapping_base_(nullptr) {
|
||||||
system_page_size_ = poly::page_size();
|
system_page_size_ = uint32_t(poly::page_size());
|
||||||
virtual_heap_ = new MemoryHeap(this, false);
|
virtual_heap_ = new MemoryHeap(this, false);
|
||||||
physical_heap_ = new MemoryHeap(this, true);
|
physical_heap_ = new MemoryHeap(this, true);
|
||||||
}
|
}
|
||||||
|
@ -187,9 +187,9 @@ int Memory::Initialize() {
|
||||||
membase_ = mapping_base_;
|
membase_ = mapping_base_;
|
||||||
|
|
||||||
// Prepare heaps.
|
// Prepare heaps.
|
||||||
virtual_heap_->Initialize(MEMORY_VIRTUAL_HEAP_LOW, MEMORY_VIRTUAL_HEAP_HIGH);
|
virtual_heap_->Initialize(kMemoryVirtualHeapLow, kMemoryVirtualHeapHigh);
|
||||||
physical_heap_->Initialize(MEMORY_PHYSICAL_HEAP_LOW,
|
physical_heap_->Initialize(kMemoryPhysicalHeapLow,
|
||||||
MEMORY_PHYSICAL_HEAP_HIGH - 0x1000);
|
kMemoryPhysicalHeapHigh - 0x1000);
|
||||||
|
|
||||||
// GPU writeback.
|
// GPU writeback.
|
||||||
// 0xC... is physical, 0x7F... is virtual. We may need to overlay these.
|
// 0xC... is physical, 0x7F... is virtual. We may need to overlay these.
|
||||||
|
@ -212,9 +212,9 @@ int Memory::Initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const static struct {
|
const static struct {
|
||||||
uint64_t virtual_address_start;
|
uint32_t virtual_address_start;
|
||||||
uint64_t virtual_address_end;
|
uint32_t virtual_address_end;
|
||||||
uint64_t target_address;
|
uint32_t target_address;
|
||||||
} map_info[] = {
|
} map_info[] = {
|
||||||
0x00000000, 0x3FFFFFFF, 0x00000000, // (1024mb) - virtual 4k pages
|
0x00000000, 0x3FFFFFFF, 0x00000000, // (1024mb) - virtual 4k pages
|
||||||
0x40000000, 0x7EFFFFFF, 0x40000000, // (1024mb) - virtual 64k pages (cont)
|
0x40000000, 0x7EFFFFFF, 0x40000000, // (1024mb) - virtual 64k pages (cont)
|
||||||
|
@ -265,23 +265,23 @@ void Memory::UnmapViews() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::Zero(uint64_t address, size_t size) {
|
void Memory::Zero(uint32_t address, uint32_t size) {
|
||||||
uint8_t* p = membase_ + address;
|
uint8_t* p = membase_ + address;
|
||||||
memset(p, 0, size);
|
memset(p, 0, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::Fill(uint64_t address, size_t size, uint8_t value) {
|
void Memory::Fill(uint32_t address, uint32_t size, uint8_t value) {
|
||||||
uint8_t* p = membase_ + address;
|
uint8_t* p = membase_ + address;
|
||||||
memset(p, value, size);
|
memset(p, value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::Copy(uint64_t dest, uint64_t src, size_t size) {
|
void Memory::Copy(uint32_t dest, uint32_t src, uint32_t size) {
|
||||||
uint8_t* pdest = membase_ + dest;
|
uint8_t* pdest = membase_ + dest;
|
||||||
const uint8_t* psrc = membase_ + src;
|
const uint8_t* psrc = membase_ + src;
|
||||||
memcpy(pdest, psrc, size);
|
memcpy(pdest, psrc, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Memory::SearchAligned(uint64_t start, uint64_t end,
|
uint32_t Memory::SearchAligned(uint32_t start, uint32_t end,
|
||||||
const uint32_t* values, size_t value_count) {
|
const uint32_t* values, size_t value_count) {
|
||||||
assert_true(start <= end);
|
assert_true(start <= end);
|
||||||
const uint32_t* p = reinterpret_cast<const uint32_t*>(membase_ + start);
|
const uint32_t* p = reinterpret_cast<const uint32_t*>(membase_ + start);
|
||||||
|
@ -297,7 +297,7 @@ uint64_t Memory::SearchAligned(uint64_t start, uint64_t end,
|
||||||
matched++;
|
matched++;
|
||||||
}
|
}
|
||||||
if (matched == value_count) {
|
if (matched == value_count) {
|
||||||
return uint64_t(reinterpret_cast<const uint8_t*>(p) - membase_);
|
return uint32_t(reinterpret_cast<const uint8_t*>(p) - membase_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
|
@ -305,7 +305,7 @@ uint64_t Memory::SearchAligned(uint64_t start, uint64_t end,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Memory::AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
bool Memory::AddMappedRange(uint32_t address, uint32_t mask, uint32_t size,
|
||||||
void* context, cpu::MMIOReadCallback read_callback,
|
void* context, cpu::MMIOReadCallback read_callback,
|
||||||
cpu::MMIOWriteCallback write_callback) {
|
cpu::MMIOWriteCallback write_callback) {
|
||||||
DWORD protect = PAGE_NOACCESS;
|
DWORD protect = PAGE_NOACCESS;
|
||||||
|
@ -317,7 +317,7 @@ bool Memory::AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
||||||
read_callback, write_callback);
|
read_callback, write_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t Memory::AddWriteWatch(uint32_t guest_address, size_t length,
|
uintptr_t Memory::AddWriteWatch(uint32_t guest_address, uint32_t length,
|
||||||
cpu::WriteWatchCallback callback,
|
cpu::WriteWatchCallback callback,
|
||||||
void* callback_context, void* callback_data) {
|
void* callback_context, void* callback_data) {
|
||||||
return mmio_handler_->AddWriteWatch(guest_address, length, callback,
|
return mmio_handler_->AddWriteWatch(guest_address, length, callback,
|
||||||
|
@ -328,13 +328,13 @@ void Memory::CancelWriteWatch(uintptr_t watch_handle) {
|
||||||
mmio_handler_->CancelWriteWatch(watch_handle);
|
mmio_handler_->CancelWriteWatch(watch_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Memory::HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
uint32_t Memory::HeapAlloc(uint32_t base_address, uint32_t size, uint32_t flags,
|
||||||
uint32_t alignment) {
|
uint32_t alignment) {
|
||||||
// If we were given a base address we are outside of the normal heap and
|
// If we were given a base address we are outside of the normal heap and
|
||||||
// will place wherever asked (so long as it doesn't overlap the heap).
|
// will place wherever asked (so long as it doesn't overlap the heap).
|
||||||
if (!base_address) {
|
if (!base_address) {
|
||||||
// Normal allocation from the managed heap.
|
// Normal allocation from the managed heap.
|
||||||
uint64_t result;
|
uint32_t result;
|
||||||
if (flags & MEMORY_FLAG_PHYSICAL) {
|
if (flags & MEMORY_FLAG_PHYSICAL) {
|
||||||
result = physical_heap_->Alloc(base_address, size, flags, alignment);
|
result = physical_heap_->Alloc(base_address, size, flags, alignment);
|
||||||
} else {
|
} else {
|
||||||
|
@ -347,14 +347,14 @@ uint64_t Memory::HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
if (base_address >= MEMORY_VIRTUAL_HEAP_LOW &&
|
if (base_address >= kMemoryVirtualHeapLow &&
|
||||||
base_address < MEMORY_VIRTUAL_HEAP_HIGH) {
|
base_address < kMemoryVirtualHeapHigh) {
|
||||||
// Overlapping managed heap.
|
// Overlapping managed heap.
|
||||||
assert_always();
|
assert_always();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (base_address >= MEMORY_PHYSICAL_HEAP_LOW &&
|
if (base_address >= kMemoryPhysicalHeapLow &&
|
||||||
base_address < MEMORY_PHYSICAL_HEAP_HIGH) {
|
base_address < kMemoryPhysicalHeapHigh) {
|
||||||
// Overlapping managed heap.
|
// Overlapping managed heap.
|
||||||
assert_always();
|
assert_always();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -378,12 +378,11 @@ uint64_t Memory::HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Memory::HeapFree(uint64_t address, size_t size) {
|
int Memory::HeapFree(uint32_t address, uint32_t size) {
|
||||||
if (address >= MEMORY_VIRTUAL_HEAP_LOW &&
|
if (address >= kMemoryVirtualHeapLow && address < kMemoryVirtualHeapHigh) {
|
||||||
address < MEMORY_VIRTUAL_HEAP_HIGH) {
|
|
||||||
return virtual_heap_->Free(address, size) ? 0 : 1;
|
return virtual_heap_->Free(address, size) ? 0 : 1;
|
||||||
} else if (address >= MEMORY_PHYSICAL_HEAP_LOW &&
|
} else if (address >= kMemoryPhysicalHeapLow &&
|
||||||
address < MEMORY_PHYSICAL_HEAP_HIGH) {
|
address < kMemoryPhysicalHeapHigh) {
|
||||||
return physical_heap_->Free(address, size) ? 0 : 1;
|
return physical_heap_->Free(address, size) ? 0 : 1;
|
||||||
} else {
|
} else {
|
||||||
// A placed address. Decommit.
|
// A placed address. Decommit.
|
||||||
|
@ -392,14 +391,14 @@ int Memory::HeapFree(uint64_t address, size_t size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Memory::QueryInformation(uint64_t base_address, AllocationInfo* mem_info) {
|
bool Memory::QueryInformation(uint32_t base_address, AllocationInfo* mem_info) {
|
||||||
uint8_t* p = Translate(base_address);
|
uint8_t* p = Translate(base_address);
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
if (!VirtualQuery(p, &mbi, sizeof(mbi))) {
|
if (!VirtualQuery(p, &mbi, sizeof(mbi))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mem_info->base_address = base_address;
|
mem_info->base_address = base_address;
|
||||||
mem_info->allocation_base = static_cast<uint64_t>(
|
mem_info->allocation_base = static_cast<uint32_t>(
|
||||||
reinterpret_cast<uint8_t*>(mbi.AllocationBase) - membase_);
|
reinterpret_cast<uint8_t*>(mbi.AllocationBase) - membase_);
|
||||||
mem_info->allocation_protect = mbi.AllocationProtect;
|
mem_info->allocation_protect = mbi.AllocationProtect;
|
||||||
mem_info->region_size = mbi.RegionSize;
|
mem_info->region_size = mbi.RegionSize;
|
||||||
|
@ -409,19 +408,19 @@ bool Memory::QueryInformation(uint64_t base_address, AllocationInfo* mem_info) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Memory::QuerySize(uint64_t base_address) {
|
uint32_t Memory::QuerySize(uint32_t base_address) {
|
||||||
if (base_address >= MEMORY_VIRTUAL_HEAP_LOW &&
|
if (base_address >= kMemoryVirtualHeapLow &&
|
||||||
base_address < MEMORY_VIRTUAL_HEAP_HIGH) {
|
base_address < kMemoryVirtualHeapHigh) {
|
||||||
return virtual_heap_->QuerySize(base_address);
|
return virtual_heap_->QuerySize(base_address);
|
||||||
} else if (base_address >= MEMORY_PHYSICAL_HEAP_LOW &&
|
} else if (base_address >= kMemoryPhysicalHeapLow &&
|
||||||
base_address < MEMORY_PHYSICAL_HEAP_HIGH) {
|
base_address < kMemoryPhysicalHeapHigh) {
|
||||||
return physical_heap_->QuerySize(base_address);
|
return physical_heap_->QuerySize(base_address);
|
||||||
} else {
|
} else {
|
||||||
// A placed address.
|
// A placed address.
|
||||||
uint8_t* p = Translate(base_address);
|
uint8_t* p = Translate(base_address);
|
||||||
MEMORY_BASIC_INFORMATION mem_info;
|
MEMORY_BASIC_INFORMATION mem_info;
|
||||||
if (VirtualQuery(p, &mem_info, sizeof(mem_info))) {
|
if (VirtualQuery(p, &mem_info, sizeof(mem_info))) {
|
||||||
return mem_info.RegionSize;
|
return uint32_t(mem_info.RegionSize);
|
||||||
} else {
|
} else {
|
||||||
// Error.
|
// Error.
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -429,7 +428,7 @@ size_t Memory::QuerySize(uint64_t base_address) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Memory::Protect(uint64_t address, size_t size, uint32_t access) {
|
int Memory::Protect(uint32_t address, uint32_t size, uint32_t access) {
|
||||||
uint8_t* p = Translate(address);
|
uint8_t* p = Translate(address);
|
||||||
|
|
||||||
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
|
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
|
||||||
|
@ -445,7 +444,7 @@ int Memory::Protect(uint64_t address, size_t size, uint32_t access) {
|
||||||
return VirtualProtect(p, size, new_protect, &old_protect) == TRUE ? 0 : 1;
|
return VirtualProtect(p, size, new_protect, &old_protect) == TRUE ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Memory::QueryProtect(uint64_t address) {
|
uint32_t Memory::QueryProtect(uint32_t address) {
|
||||||
uint8_t* p = Translate(address);
|
uint8_t* p = Translate(address);
|
||||||
MEMORY_BASIC_INFORMATION info;
|
MEMORY_BASIC_INFORMATION info;
|
||||||
size_t info_size = VirtualQuery((void*)p, &info, sizeof(info));
|
size_t info_size = VirtualQuery((void*)p, &info, sizeof(info));
|
||||||
|
@ -472,7 +471,7 @@ MemoryHeap::~MemoryHeap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MemoryHeap::Initialize(uint64_t low, uint64_t high) {
|
int MemoryHeap::Initialize(uint32_t low, uint32_t high) {
|
||||||
// Commit the memory where our heap will live and allocate it.
|
// Commit the memory where our heap will live and allocate it.
|
||||||
// TODO(benvanik): replace dlmalloc with an implementation that can commit
|
// TODO(benvanik): replace dlmalloc with an implementation that can commit
|
||||||
// as it goes.
|
// as it goes.
|
||||||
|
@ -487,7 +486,7 @@ int MemoryHeap::Initialize(uint64_t low, uint64_t high) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t MemoryHeap::Alloc(uint64_t base_address, size_t size, uint32_t flags,
|
uint32_t MemoryHeap::Alloc(uint32_t base_address, uint32_t size, uint32_t flags,
|
||||||
uint32_t alignment) {
|
uint32_t alignment) {
|
||||||
size_t alloc_size = size;
|
size_t alloc_size = size;
|
||||||
if (int32_t(alloc_size) < 0) {
|
if (int32_t(alloc_size) < 0) {
|
||||||
|
@ -538,13 +537,13 @@ uint64_t MemoryHeap::Alloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||||
memset(p, 0xCD, alloc_size);
|
memset(p, 0xCD, alloc_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t address =
|
uint32_t address =
|
||||||
(uint64_t)((uintptr_t)p - (uintptr_t)memory_->mapping_base_);
|
(uint32_t)((uintptr_t)p - (uintptr_t)memory_->mapping_base_);
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t MemoryHeap::Free(uint64_t address, size_t size) {
|
uint32_t MemoryHeap::Free(uint32_t address, uint32_t size) {
|
||||||
uint8_t* p = memory_->Translate(address);
|
uint8_t* p = memory_->Translate(address);
|
||||||
|
|
||||||
// Heap allocated address.
|
// Heap allocated address.
|
||||||
|
@ -584,16 +583,16 @@ uint64_t MemoryHeap::Free(uint64_t address, size_t size) {
|
||||||
size, MEM_DECOMMIT);
|
size, MEM_DECOMMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (uint64_t)real_size;
|
return static_cast<uint32_t>(real_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MemoryHeap::QuerySize(uint64_t base_address) {
|
uint32_t MemoryHeap::QuerySize(uint32_t base_address) {
|
||||||
uint8_t* p = memory_->Translate(base_address);
|
uint8_t* p = memory_->Translate(base_address);
|
||||||
|
|
||||||
// Heap allocated address.
|
// Heap allocated address.
|
||||||
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
|
uint32_t heap_guard_size = uint32_t(FLAGS_heap_guard_pages * 4096);
|
||||||
p -= heap_guard_size;
|
p -= heap_guard_size;
|
||||||
size_t real_size = mspace_usable_size(p);
|
uint32_t real_size = uint32_t(mspace_usable_size(p));
|
||||||
real_size -= heap_guard_size * 2;
|
real_size -= heap_guard_size * 2;
|
||||||
if (!real_size) {
|
if (!real_size) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
#include "xenia/common.h"
|
#include "xenia/common.h"
|
||||||
#include "xenia/cpu/mmio_handler.h"
|
#include "xenia/cpu/mmio_handler.h"
|
||||||
|
|
||||||
typedef struct xe_ppc_state xe_ppc_state_t;
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
|
||||||
class MemoryHeap;
|
class MemoryHeap;
|
||||||
|
@ -35,8 +33,8 @@ enum {
|
||||||
// TODO(benvanik): move to heap.
|
// TODO(benvanik): move to heap.
|
||||||
// Equivalent to the Win32 MEMORY_BASIC_INFORMATION struct.
|
// Equivalent to the Win32 MEMORY_BASIC_INFORMATION struct.
|
||||||
struct AllocationInfo {
|
struct AllocationInfo {
|
||||||
uint64_t base_address;
|
uint32_t base_address;
|
||||||
uint64_t allocation_base;
|
uint32_t allocation_base;
|
||||||
uint32_t allocation_protect; // TBD
|
uint32_t allocation_protect; // TBD
|
||||||
size_t region_size;
|
size_t region_size;
|
||||||
uint32_t state; // TBD
|
uint32_t state; // TBD
|
||||||
|
@ -62,37 +60,37 @@ class Memory {
|
||||||
void set_trace_base(uint64_t value) { trace_base_ = value; }
|
void set_trace_base(uint64_t value) { trace_base_ = value; }
|
||||||
|
|
||||||
// TODO(benvanik): make poly memory utils for these.
|
// TODO(benvanik): make poly memory utils for these.
|
||||||
void Zero(uint64_t address, size_t size);
|
void Zero(uint32_t address, uint32_t size);
|
||||||
void Fill(uint64_t address, size_t size, uint8_t value);
|
void Fill(uint32_t address, uint32_t size, uint8_t value);
|
||||||
void Copy(uint64_t dest, uint64_t src, size_t size);
|
void Copy(uint32_t dest, uint32_t src, uint32_t size);
|
||||||
uint64_t SearchAligned(uint64_t start, uint64_t end, const uint32_t* values,
|
uint32_t SearchAligned(uint32_t start, uint32_t end, const uint32_t* values,
|
||||||
size_t value_count);
|
size_t value_count);
|
||||||
|
|
||||||
bool AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
bool AddMappedRange(uint32_t address, uint32_t mask, uint32_t size,
|
||||||
void* context, cpu::MMIOReadCallback read_callback,
|
void* context, cpu::MMIOReadCallback read_callback,
|
||||||
cpu::MMIOWriteCallback write_callback);
|
cpu::MMIOWriteCallback write_callback);
|
||||||
|
|
||||||
uintptr_t AddWriteWatch(uint32_t guest_address, size_t length,
|
uintptr_t AddWriteWatch(uint32_t guest_address, uint32_t length,
|
||||||
cpu::WriteWatchCallback callback,
|
cpu::WriteWatchCallback callback,
|
||||||
void* callback_context, void* callback_data);
|
void* callback_context, void* callback_data);
|
||||||
void CancelWriteWatch(uintptr_t watch_handle);
|
void CancelWriteWatch(uintptr_t watch_handle);
|
||||||
|
|
||||||
uint64_t HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
uint32_t HeapAlloc(uint32_t base_address, uint32_t size, uint32_t flags,
|
||||||
uint32_t alignment = 0x20);
|
uint32_t alignment = 0x20);
|
||||||
int HeapFree(uint64_t address, size_t size);
|
int HeapFree(uint32_t address, uint32_t size);
|
||||||
|
|
||||||
bool QueryInformation(uint64_t base_address, AllocationInfo* mem_info);
|
bool QueryInformation(uint32_t base_address, AllocationInfo* mem_info);
|
||||||
size_t QuerySize(uint64_t base_address);
|
uint32_t QuerySize(uint32_t base_address);
|
||||||
|
|
||||||
int Protect(uint64_t address, size_t size, uint32_t access);
|
int Protect(uint32_t address, uint32_t size, uint32_t access);
|
||||||
uint32_t QueryProtect(uint64_t address);
|
uint32_t QueryProtect(uint32_t address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int MapViews(uint8_t* mapping_base);
|
int MapViews(uint8_t* mapping_base);
|
||||||
void UnmapViews();
|
void UnmapViews();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t system_page_size_;
|
uint32_t system_page_size_;
|
||||||
uint8_t* membase_;
|
uint8_t* membase_;
|
||||||
uint64_t reserve_address_;
|
uint64_t reserve_address_;
|
||||||
uint64_t reserve_value_;
|
uint64_t reserve_value_;
|
||||||
|
|
Loading…
Reference in New Issue