Cleanup before kernel export refactor.

This commit is contained in:
Ben Vanik 2015-05-31 16:31:19 -07:00
parent fccab79a7a
commit 9c3d2b54fb
24 changed files with 2508 additions and 2502 deletions

View File

@ -417,18 +417,27 @@ uint64_t UndefinedCallExtern(void* raw_context, uint64_t symbol_info_ptr) {
}
void X64Emitter::CallExtern(const hir::Instr* instr,
const FunctionInfo* symbol_info) {
assert_true(symbol_info->behavior() == FunctionInfo::BEHAVIOR_EXTERN);
if (!symbol_info->extern_handler()) {
CallNative(UndefinedCallExtern, reinterpret_cast<uint64_t>(symbol_info));
} else {
} else if (symbol_info->behavior() == FunctionBehavior::kBuiltin) {
// rcx = context
// rdx = target host function
// r8 = arg0
// r9 = arg1
mov(rdx, reinterpret_cast<uint64_t>(symbol_info->builtin_handler()));
mov(r8, reinterpret_cast<uint64_t>(symbol_info->builtin_arg0()));
mov(r9, reinterpret_cast<uint64_t>(symbol_info->builtin_arg1()));
auto thunk = backend()->guest_to_host_thunk();
mov(rax, reinterpret_cast<uint64_t>(thunk));
call(rax);
ReloadECX();
ReloadEDX();
// rax = host return
} else if (symbol_info->behavior() == FunctionBehavior::kExtern) {
// rcx = context
// rdx = target host function
mov(rdx, reinterpret_cast<uint64_t>(symbol_info->extern_handler()));
mov(r8, reinterpret_cast<uint64_t>(symbol_info->extern_arg0()));
mov(r9, reinterpret_cast<uint64_t>(symbol_info->extern_arg1()));
mov(r8, qword[rcx + offsetof(cpu::frontend::PPCContext, kernel_state)]);
auto thunk = backend()->guest_to_host_thunk();
mov(rax, reinterpret_cast<uint64_t>(thunk));
call(rax);

View File

@ -20,19 +20,17 @@ ExportResolver::ExportResolver() {}
ExportResolver::~ExportResolver() {}
void ExportResolver::RegisterTable(const std::string& library_name,
KernelExport* exports, const size_t count) {
Export* exports, const size_t count) {
tables_.emplace_back(library_name, exports, count);
for (size_t n = 0; n < count; n++) {
exports[n].is_implemented = false;
exports[n].variable_ptr = 0;
exports[n].function_data.shim_data = nullptr;
exports[n].function_data.shim = nullptr;
}
}
KernelExport* ExportResolver::GetExportByOrdinal(
const std::string& library_name, const uint32_t ordinal) {
Export* ExportResolver::GetExportByOrdinal(const std::string& library_name,
const uint32_t ordinal) {
for (const auto& table : tables_) {
if (table.name == library_name || table.simple_name == library_name) {
// TODO(benvanik): binary search?
@ -50,20 +48,19 @@ KernelExport* ExportResolver::GetExportByOrdinal(
void ExportResolver::SetVariableMapping(const std::string& library_name,
const uint32_t ordinal,
uint32_t value) {
auto kernel_export = GetExportByOrdinal(library_name, ordinal);
assert_not_null(kernel_export);
kernel_export->is_implemented = true;
kernel_export->variable_ptr = value;
auto export = GetExportByOrdinal(library_name, ordinal);
assert_not_null(export);
export->tags |= ExportTag::kImplemented;
export->variable_ptr = value;
}
void ExportResolver::SetFunctionMapping(const std::string& library_name,
const uint32_t ordinal, void* shim_data,
const uint32_t ordinal,
xe_kernel_export_shim_fn shim) {
auto kernel_export = GetExportByOrdinal(library_name, ordinal);
assert_not_null(kernel_export);
kernel_export->is_implemented = true;
kernel_export->function_data.shim_data = shim_data;
kernel_export->function_data.shim = shim;
auto export = GetExportByOrdinal(library_name, ordinal);
assert_not_null(export);
export->tags |= ExportTag::kImplemented;
export->function_data.shim = shim;
}
} // namespace cpu

View File

@ -13,24 +13,51 @@
#include <string>
#include <vector>
#include "xenia/cpu/frontend/ppc_context.h"
namespace xe {
namespace cpu {
struct ExportTag {
typedef uint32_t type;
static const type kImplemented = 1 << 0;
static const type kSketchy = 1 << 1;
static const type kHighFrequency = 1 << 2;
static const type kImportant = 1 << 3;
static const type kThreading = 1 << 10;
static const type kInput = 1 << 11;
static const type kAudio = 1 << 12;
static const type kVideo = 1 << 13;
static const type kFileSystem = 1 << 14;
static const type kModules = 1 << 15;
static const type kUserProfiles = 1 << 16;
static const type kLog = 1 << 31;
};
// DEPRECATED
typedef void (*xe_kernel_export_shim_fn)(void*, void*);
class KernelExport {
class Export {
public:
enum ExportType {
Function = 0,
Variable = 1,
enum class Type {
kFunction = 0,
kVariable = 1,
};
uint32_t ordinal;
ExportType type;
uint32_t flags;
char name[96];
Type type;
std::string name;
ExportTag::type tags;
bool is_implemented;
void (*trampoline)(xe::cpu::frontend::PPCContext* ppc_context);
uint64_t call_count;
bool is_implemented() const {
return (tags & ExportTag::kImplemented) == ExportTag::kImplemented;
}
union {
// Variable data. Only valid when kXEKernelExportFlagVariable is set.
@ -39,9 +66,6 @@ class KernelExport {
uint32_t variable_ptr;
struct {
// Second argument passed to the shim function.
void* shim_data;
// Shimmed implementation.
// This is called directly from generated code.
// It should parse args, do fixups, and call the impl.
@ -55,25 +79,25 @@ class ExportResolver {
ExportResolver();
~ExportResolver();
void RegisterTable(const std::string& library_name, KernelExport* exports,
void RegisterTable(const std::string& library_name, Export* exports,
const size_t count);
KernelExport* GetExportByOrdinal(const std::string& library_name,
Export* GetExportByOrdinal(const std::string& library_name,
const uint32_t ordinal);
void SetVariableMapping(const std::string& library_name,
const uint32_t ordinal, uint32_t value);
void SetFunctionMapping(const std::string& library_name,
const uint32_t ordinal, void* shim_data,
const uint32_t ordinal,
xe_kernel_export_shim_fn shim);
private:
struct ExportTable {
std::string name;
std::string simple_name; // without extension
KernelExport* exports;
Export* exports;
size_t count;
ExportTable(const std::string& name, KernelExport* exports, size_t count)
ExportTable(const std::string& name, Export* exports, size_t count)
: name(name), exports(exports), count(count) {
auto dot_pos = name.find_last_of('.');
if (dot_pos != std::string::npos) {

View File

@ -78,12 +78,10 @@ void HandleGlobalLock(PPCContext* ppc_state, void* arg0, void* arg1) {
bool PPCFrontend::Initialize() {
void* arg0 = reinterpret_cast<void*>(&builtins_.global_lock);
void* arg1 = reinterpret_cast<void*>(&builtins_.global_lock_taken);
builtins_.check_global_lock = processor_->DefineBuiltin(
"CheckGlobalLock", (FunctionInfo::ExternHandler)CheckGlobalLock, arg0,
arg1);
builtins_.check_global_lock =
processor_->DefineBuiltin("CheckGlobalLock", CheckGlobalLock, arg0, arg1);
builtins_.handle_global_lock = processor_->DefineBuiltin(
"HandleGlobalLock", (FunctionInfo::ExternHandler)HandleGlobalLock, arg0,
arg1);
"HandleGlobalLock", HandleGlobalLock, arg0, arg1);
return true;
}

View File

@ -38,7 +38,7 @@ bool PPCScanner::IsRestGprLr(uint32_t address) {
if (!frontend_->processor()->LookupFunctionInfo(address, &symbol_info)) {
return false;
}
return symbol_info->behavior() == FunctionInfo::BEHAVIOR_EPILOG_RETURN;
return symbol_info->behavior() == FunctionBehavior::kEpilogReturn;
}
bool PPCScanner::Scan(FunctionInfo* symbol_info, DebugInfo* debug_info) {

View File

@ -75,14 +75,17 @@ bool Function::Call(ThreadState* thread_state, uint32_t return_address) {
bool result = true;
if (symbol_info_->behavior() == FunctionInfo::BEHAVIOR_EXTERN) {
if (symbol_info_->behavior() == FunctionBehavior::kBuiltin) {
auto handler = symbol_info_->builtin_handler();
assert_not_null(handler);
handler(thread_state->context(), symbol_info_->builtin_arg0(),
symbol_info_->builtin_arg1());
} else if (symbol_info_->behavior() == FunctionBehavior::kExtern) {
auto handler = symbol_info_->extern_handler();
if (handler) {
handler(thread_state->context(), symbol_info_->extern_arg0(),
symbol_info_->extern_arg1());
handler(thread_state->context(), thread_state->context()->kernel_state);
} else {
XELOGW("undefined extern call to %.8llX %s", symbol_info_->address(),
XELOGW("undefined extern call to %.8X %s", symbol_info_->address(),
symbol_info_->name().c_str());
result = false;
}

View File

@ -31,7 +31,7 @@ SymbolInfo* Module::LookupSymbol(uint32_t address, bool wait) {
const auto it = map_.find(address);
SymbolInfo* symbol_info = it != map_.end() ? it->second : nullptr;
if (symbol_info) {
if (symbol_info->status() == SymbolInfo::STATUS_DECLARING) {
if (symbol_info->status() == SymbolStatus::kDeclaring) {
// Some other thread is declaring the symbol - wait.
if (wait) {
do {
@ -39,7 +39,7 @@ SymbolInfo* Module::LookupSymbol(uint32_t address, bool wait) {
// TODO(benvanik): sleep for less time?
xe::threading::Sleep(std::chrono::microseconds(100));
lock_.lock();
} while (symbol_info->status() == SymbolInfo::STATUS_DECLARING);
} while (symbol_info->status() == SymbolStatus::kDeclaring);
} else {
// Immediate request, just return.
symbol_info = nullptr;
@ -50,89 +50,88 @@ SymbolInfo* Module::LookupSymbol(uint32_t address, bool wait) {
return symbol_info;
}
SymbolInfo::Status Module::DeclareSymbol(SymbolInfo::Type type,
uint32_t address,
SymbolStatus Module::DeclareSymbol(SymbolType type, uint32_t address,
SymbolInfo** out_symbol_info) {
*out_symbol_info = nullptr;
lock_.lock();
auto it = map_.find(address);
SymbolInfo* symbol_info = it != map_.end() ? it->second : nullptr;
SymbolInfo::Status status;
SymbolStatus status;
if (symbol_info) {
// If we exist but are the wrong type, die.
if (symbol_info->type() != type) {
lock_.unlock();
return SymbolInfo::STATUS_FAILED;
return SymbolStatus::kFailed;
}
// If we aren't ready yet spin and wait.
if (symbol_info->status() == SymbolInfo::STATUS_DECLARING) {
if (symbol_info->status() == SymbolStatus::kDeclaring) {
// Still declaring, so spin.
do {
lock_.unlock();
// TODO(benvanik): sleep for less time?
xe::threading::Sleep(std::chrono::microseconds(100));
lock_.lock();
} while (symbol_info->status() == SymbolInfo::STATUS_DECLARING);
} while (symbol_info->status() == SymbolStatus::kDeclaring);
}
status = symbol_info->status();
} else {
// Create and return for initialization.
switch (type) {
case SymbolInfo::TYPE_FUNCTION:
case SymbolType::kFunction:
symbol_info = new FunctionInfo(this, address);
break;
case SymbolInfo::TYPE_VARIABLE:
case SymbolType::kVariable:
symbol_info = new VariableInfo(this, address);
break;
}
map_[address] = symbol_info;
list_.emplace_back(symbol_info);
status = SymbolInfo::STATUS_NEW;
status = SymbolStatus::kNew;
}
lock_.unlock();
*out_symbol_info = symbol_info;
// Get debug info from providers, if this is new.
if (status == SymbolInfo::STATUS_NEW) {
if (status == SymbolStatus::kNew) {
// TODO(benvanik): lookup in map data/dwarf/etc?
}
return status;
}
SymbolInfo::Status Module::DeclareFunction(uint32_t address,
SymbolStatus Module::DeclareFunction(uint32_t address,
FunctionInfo** out_symbol_info) {
SymbolInfo* symbol_info;
SymbolInfo::Status status =
DeclareSymbol(SymbolInfo::TYPE_FUNCTION, address, &symbol_info);
SymbolStatus status =
DeclareSymbol(SymbolType::kFunction, address, &symbol_info);
*out_symbol_info = (FunctionInfo*)symbol_info;
return status;
}
SymbolInfo::Status Module::DeclareVariable(uint32_t address,
SymbolStatus Module::DeclareVariable(uint32_t address,
VariableInfo** out_symbol_info) {
SymbolInfo* symbol_info;
SymbolInfo::Status status =
DeclareSymbol(SymbolInfo::TYPE_VARIABLE, address, &symbol_info);
SymbolStatus status =
DeclareSymbol(SymbolType::kVariable, address, &symbol_info);
*out_symbol_info = (VariableInfo*)symbol_info;
return status;
}
SymbolInfo::Status Module::DefineSymbol(SymbolInfo* symbol_info) {
SymbolStatus Module::DefineSymbol(SymbolInfo* symbol_info) {
lock_.lock();
SymbolInfo::Status status;
if (symbol_info->status() == SymbolInfo::STATUS_DECLARED) {
SymbolStatus status;
if (symbol_info->status() == SymbolStatus::kDeclared) {
// Declared but undefined, so request caller define it.
symbol_info->set_status(SymbolInfo::STATUS_DEFINING);
status = SymbolInfo::STATUS_NEW;
} else if (symbol_info->status() == SymbolInfo::STATUS_DEFINING) {
symbol_info->set_status(SymbolStatus::kDefining);
status = SymbolStatus::kNew;
} else if (symbol_info->status() == SymbolStatus::kDefining) {
// Still defining, so spin.
do {
lock_.unlock();
// TODO(benvanik): sleep for less time?
xe::threading::Sleep(std::chrono::microseconds(100));
lock_.lock();
} while (symbol_info->status() == SymbolInfo::STATUS_DEFINING);
} while (symbol_info->status() == SymbolStatus::kDefining);
status = symbol_info->status();
} else {
status = symbol_info->status();
@ -141,11 +140,11 @@ SymbolInfo::Status Module::DefineSymbol(SymbolInfo* symbol_info) {
return status;
}
SymbolInfo::Status Module::DefineFunction(FunctionInfo* symbol_info) {
SymbolStatus Module::DefineFunction(FunctionInfo* symbol_info) {
return DefineSymbol((SymbolInfo*)symbol_info);
}
SymbolInfo::Status Module::DefineVariable(VariableInfo* symbol_info) {
SymbolStatus Module::DefineVariable(VariableInfo* symbol_info) {
return DefineSymbol((SymbolInfo*)symbol_info);
}
@ -153,7 +152,7 @@ void Module::ForEachFunction(std::function<void(FunctionInfo*)> callback) {
SCOPE_profile_cpu_f("cpu");
std::lock_guard<xe::mutex> guard(lock_);
for (auto& symbol_info : list_) {
if (symbol_info->type() == SymbolInfo::TYPE_FUNCTION) {
if (symbol_info->type() == SymbolType::kFunction) {
FunctionInfo* info = static_cast<FunctionInfo*>(symbol_info.get());
callback(info);
}
@ -168,7 +167,7 @@ void Module::ForEachFunction(size_t since, size_t& version,
version = count;
for (size_t n = since; n < count; n++) {
auto& symbol_info = list_[n];
if (symbol_info->type() == SymbolInfo::TYPE_FUNCTION) {
if (symbol_info->type() == SymbolType::kFunction) {
FunctionInfo* info = static_cast<FunctionInfo*>(symbol_info.get());
callback(info);
}

View File

@ -38,13 +38,13 @@ class Module {
virtual bool ContainsAddress(uint32_t address);
SymbolInfo* LookupSymbol(uint32_t address, bool wait = true);
virtual SymbolInfo::Status DeclareFunction(uint32_t address,
virtual SymbolStatus DeclareFunction(uint32_t address,
FunctionInfo** out_symbol_info);
virtual SymbolInfo::Status DeclareVariable(uint32_t address,
virtual SymbolStatus DeclareVariable(uint32_t address,
VariableInfo** out_symbol_info);
SymbolInfo::Status DefineFunction(FunctionInfo* symbol_info);
SymbolInfo::Status DefineVariable(VariableInfo* symbol_info);
SymbolStatus DefineFunction(FunctionInfo* symbol_info);
SymbolStatus DefineVariable(VariableInfo* symbol_info);
void ForEachFunction(std::function<void(FunctionInfo*)> callback);
void ForEachFunction(size_t since, size_t& version,
@ -53,9 +53,9 @@ class Module {
bool ReadMap(const char* file_name);
private:
SymbolInfo::Status DeclareSymbol(SymbolInfo::Type type, uint32_t address,
SymbolStatus DeclareSymbol(SymbolType type, uint32_t address,
SymbolInfo** out_symbol_info);
SymbolInfo::Status DefineSymbol(SymbolInfo* symbol_info);
SymbolStatus DefineSymbol(SymbolInfo* symbol_info);
protected:
Processor* processor_;

View File

@ -76,18 +76,11 @@ Processor::Processor(xe::Memory* memory, ExportResolver* export_resolver,
debug_info_flags_(0),
builtin_module_(nullptr),
next_builtin_address_(0xFFFF0000ul),
export_resolver_(export_resolver),
interrupt_thread_state_(nullptr),
interrupt_thread_block_(0) {
export_resolver_(export_resolver) {
InitializeIfNeeded();
}
Processor::~Processor() {
if (interrupt_thread_block_) {
memory_->SystemHeapFree(interrupt_thread_block_);
delete interrupt_thread_state_;
}
{
std::lock_guard<xe::mutex> guard(modules_lock_);
modules_.clear();
@ -144,18 +137,6 @@ bool Processor::Setup() {
backend_ = std::move(backend);
frontend_ = std::move(frontend);
// DEPRECATED: will be removed.
interrupt_thread_state_ =
new ThreadState(this, 0, ThreadStackType::kKernelStack, 0, 128 * 1024, 0);
interrupt_thread_state_->set_name("Interrupt");
interrupt_thread_block_ = memory_->SystemHeapAlloc(2048);
interrupt_thread_state_->context()->r[13] = interrupt_thread_block_;
XELOGI("Interrupt Thread %X Stack: %.8X-%.8X",
interrupt_thread_state_->thread_id(),
interrupt_thread_state_->stack_address(),
interrupt_thread_state_->stack_address() +
interrupt_thread_state_->stack_size());
return true;
}
@ -185,7 +166,7 @@ std::vector<Module*> Processor::GetModules() {
}
FunctionInfo* Processor::DefineBuiltin(const std::string& name,
FunctionInfo::ExternHandler handler,
FunctionInfo::BuiltinHandler handler,
void* arg0, void* arg1) {
uint32_t address = next_builtin_address_;
next_builtin_address_ += 4;
@ -194,8 +175,8 @@ FunctionInfo* Processor::DefineBuiltin(const std::string& name,
builtin_module_->DeclareFunction(address, &fn_info);
fn_info->set_end_address(address + 4);
fn_info->set_name(name);
fn_info->SetupExtern(handler, arg0, arg1);
fn_info->set_status(SymbolInfo::STATUS_DECLARED);
fn_info->SetupBuiltin(handler, arg0, arg1);
fn_info->set_status(SymbolStatus::kDeclared);
return fn_info;
}
@ -266,15 +247,14 @@ bool Processor::LookupFunctionInfo(Module* module, uint32_t address,
// Atomic create/lookup symbol in module.
// If we get back the NEW flag we must declare it now.
FunctionInfo* symbol_info = nullptr;
SymbolInfo::Status symbol_status =
module->DeclareFunction(address, &symbol_info);
if (symbol_status == SymbolInfo::STATUS_NEW) {
SymbolStatus symbol_status = module->DeclareFunction(address, &symbol_info);
if (symbol_status == SymbolStatus::kNew) {
// Symbol is undeclared, so declare now.
if (!frontend_->DeclareFunction(symbol_info)) {
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
symbol_info->set_status(SymbolStatus::kFailed);
return false;
}
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
symbol_info->set_status(SymbolStatus::kDeclared);
}
*out_symbol_info = symbol_info;
@ -288,12 +268,12 @@ bool Processor::DemandFunction(FunctionInfo* symbol_info,
// Lock function for generation. If it's already being generated
// by another thread this will block and return DECLARED.
Module* module = symbol_info->module();
SymbolInfo::Status symbol_status = module->DefineFunction(symbol_info);
if (symbol_status == SymbolInfo::STATUS_NEW) {
SymbolStatus symbol_status = module->DefineFunction(symbol_info);
if (symbol_status == SymbolStatus::kNew) {
// Symbol is undefined, so define now.
Function* function = nullptr;
if (!frontend_->DefineFunction(symbol_info, debug_info_flags_, &function)) {
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
symbol_info->set_status(SymbolStatus::kFailed);
return false;
}
symbol_info->set_function(function);
@ -303,11 +283,11 @@ bool Processor::DemandFunction(FunctionInfo* symbol_info,
debugger_->OnFunctionDefined(symbol_info, function);
}
symbol_info->set_status(SymbolInfo::STATUS_DEFINED);
symbol_info->set_status(SymbolStatus::kDefined);
symbol_status = symbol_info->status();
}
if (symbol_status == SymbolInfo::STATUS_FAILED) {
if (symbol_status == SymbolStatus::kFailed) {
// Symbol likely failed.
return false;
}
@ -374,18 +354,5 @@ void Processor::LowerIrql(Irql old_value) {
reinterpret_cast<volatile uint32_t*>(&irql_));
}
uint64_t Processor::ExecuteInterrupt(uint32_t address, uint64_t args[],
size_t arg_count) {
SCOPE_profile_cpu_f("cpu");
// Acquire lock on interrupt thread (we can only dispatch one at a time).
std::lock_guard<xe::mutex> lock(interrupt_thread_lock_);
// Execute interrupt.
uint64_t result = Execute(interrupt_thread_state_, address, args, arg_count);
return result;
}
} // namespace cpu
} // namespace xe

View File

@ -58,7 +58,7 @@ class Processor {
Module* builtin_module() const { return builtin_module_; }
FunctionInfo* DefineBuiltin(const std::string& name,
FunctionInfo::ExternHandler handler, void* arg0,
FunctionInfo::BuiltinHandler handler, void* arg0,
void* arg1);
std::vector<Function*> FindFunctionsWithAddress(uint32_t address);
@ -75,10 +75,6 @@ class Processor {
Irql RaiseIrql(Irql new_value);
void LowerIrql(Irql old_value);
// DEPRECATED: will be removed.
uint64_t ExecuteInterrupt(uint32_t address, uint64_t args[],
size_t arg_count);
private:
bool DemandFunction(FunctionInfo* symbol_info, Function** out_function);
@ -98,9 +94,6 @@ class Processor {
uint32_t next_builtin_address_;
Irql irql_;
xe::mutex interrupt_thread_lock_;
ThreadState* interrupt_thread_state_;
uint32_t interrupt_thread_block_;
};
} // namespace cpu

View File

@ -12,34 +12,40 @@
namespace xe {
namespace cpu {
SymbolInfo::SymbolInfo(Type type, Module* module, uint32_t address)
SymbolInfo::SymbolInfo(SymbolType type, Module* module, uint32_t address)
: type_(type),
module_(module),
status_(STATUS_DEFINING),
status_(SymbolStatus::kDefining),
address_(address),
name_("") {}
SymbolInfo::~SymbolInfo() = default;
FunctionInfo::FunctionInfo(Module* module, uint32_t address)
: SymbolInfo(SymbolInfo::TYPE_FUNCTION, module, address),
: SymbolInfo(SymbolType::kFunction, module, address),
end_address_(0),
behavior_(BEHAVIOR_DEFAULT),
function_(0) {
behavior_(FunctionBehavior::kDefault),
function_(nullptr) {
std::memset(&extern_info_, 0, sizeof(extern_info_));
}
FunctionInfo::~FunctionInfo() = default;
void FunctionInfo::SetupExtern(ExternHandler handler, void* arg0, void* arg1) {
behavior_ = BEHAVIOR_EXTERN;
void FunctionInfo::SetupBuiltin(BuiltinHandler handler, void* arg0,
void* arg1) {
behavior_ = FunctionBehavior::kBuiltin;
builtin_info_.handler = handler;
builtin_info_.arg0 = arg0;
builtin_info_.arg1 = arg1;
}
void FunctionInfo::SetupExtern(ExternHandler handler) {
behavior_ = FunctionBehavior::kExtern;
extern_info_.handler = handler;
extern_info_.arg0 = arg0;
extern_info_.arg1 = arg1;
}
VariableInfo::VariableInfo(Module* module, uint32_t address)
: SymbolInfo(SymbolInfo::TYPE_VARIABLE, module, address) {}
: SymbolInfo(SymbolType::kVariable, module, address) {}
VariableInfo::~VariableInfo() = default;

View File

@ -13,59 +13,61 @@
#include <cstdint>
#include <string>
#include "xenia/cpu/frontend/ppc_context.h"
namespace xe {
namespace cpu {
class Function;
class Module;
enum class SymbolType {
kFunction,
kVariable,
};
enum class SymbolStatus {
kNew,
kDeclaring,
kDeclared,
kDefining,
kDefined,
kFailed,
};
class SymbolInfo {
public:
enum Type {
TYPE_FUNCTION,
TYPE_VARIABLE,
};
enum Status {
STATUS_NEW,
STATUS_DECLARING,
STATUS_DECLARED,
STATUS_DEFINING,
STATUS_DEFINED,
STATUS_FAILED,
};
public:
SymbolInfo(Type type, Module* module, uint32_t address);
SymbolInfo(SymbolType type, Module* module, uint32_t address);
virtual ~SymbolInfo();
Type type() const { return type_; }
SymbolType type() const { return type_; }
Module* module() const { return module_; }
Status status() const { return status_; }
void set_status(Status value) { status_ = value; }
SymbolStatus status() const { return status_; }
void set_status(SymbolStatus value) { status_ = value; }
uint32_t address() const { return address_; }
const std::string& name() const { return name_; }
void set_name(const std::string& value) { name_ = value; }
protected:
Type type_;
SymbolType type_;
Module* module_;
Status status_;
SymbolStatus status_;
uint32_t address_;
std::string name_;
};
class FunctionInfo : public SymbolInfo {
public:
enum Behavior {
BEHAVIOR_DEFAULT = 0,
BEHAVIOR_PROLOG,
BEHAVIOR_EPILOG,
BEHAVIOR_EPILOG_RETURN,
BEHAVIOR_EXTERN,
};
enum class FunctionBehavior {
kDefault = 0,
kProlog,
kEpilog,
kEpilogReturn,
kBuiltin,
kExtern,
};
class FunctionInfo : public SymbolInfo {
public:
FunctionInfo(Module* module, uint32_t address);
~FunctionInfo() override;
@ -74,27 +76,38 @@ class FunctionInfo : public SymbolInfo {
uint32_t end_address() const { return end_address_; }
void set_end_address(uint32_t value) { end_address_ = value; }
Behavior behavior() const { return behavior_; }
void set_behavior(Behavior value) { behavior_ = value; }
FunctionBehavior behavior() const { return behavior_; }
void set_behavior(FunctionBehavior value) { behavior_ = value; }
Function* function() const { return function_; }
void set_function(Function* value) { function_ = value; }
typedef void (*ExternHandler)(void* context, void* arg0, void* arg1);
void SetupExtern(ExternHandler handler, void* arg0, void* arg1);
typedef void (*BuiltinHandler)(frontend::PPCContext* ppc_context, void* arg0,
void* arg1);
void SetupBuiltin(BuiltinHandler handler, void* arg0, void* arg1);
BuiltinHandler builtin_handler() const { return builtin_info_.handler; }
void* builtin_arg0() const { return builtin_info_.arg0; }
void* builtin_arg1() const { return builtin_info_.arg1; }
typedef void (*ExternHandler)(frontend::PPCContext* ppc_context,
kernel::KernelState* kernel_state);
void SetupExtern(ExternHandler handler);
ExternHandler extern_handler() const { return extern_info_.handler; }
void* extern_arg0() const { return extern_info_.arg0; }
void* extern_arg1() const { return extern_info_.arg1; }
private:
uint32_t end_address_;
Behavior behavior_;
FunctionBehavior behavior_;
Function* function_;
union {
struct {
ExternHandler handler;
} extern_info_;
struct {
BuiltinHandler handler;
void* arg0;
void* arg1;
} extern_info_;
} builtin_info_;
};
};
class VariableInfo : public SymbolInfo {

View File

@ -71,10 +71,10 @@ bool TestModule::ContainsAddress(uint32_t address) {
return contains_address_(address);
}
SymbolInfo::Status TestModule::DeclareFunction(uint32_t address,
SymbolStatus TestModule::DeclareFunction(uint32_t address,
FunctionInfo** out_symbol_info) {
SymbolInfo::Status status = Module::DeclareFunction(address, out_symbol_info);
if (status == SymbolInfo::STATUS_NEW) {
SymbolStatus status = Module::DeclareFunction(address, out_symbol_info);
if (status == SymbolStatus::kNew) {
auto symbol_info = *out_symbol_info;
// Reset() all caching when we leave.
@ -82,8 +82,8 @@ SymbolInfo::Status TestModule::DeclareFunction(uint32_t address,
xe::make_reset_scope(assembler_);
if (!generate_(*builder_.get())) {
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
return SymbolInfo::STATUS_FAILED;
symbol_info->set_status(SymbolStatus::kFailed);
return SymbolStatus::kFailed;
}
compiler_->Compile(builder_.get());
@ -92,7 +92,7 @@ SymbolInfo::Status TestModule::DeclareFunction(uint32_t address,
assembler_->Assemble(symbol_info, builder_.get(), 0, nullptr, &fn);
symbol_info->set_function(fn);
status = SymbolInfo::STATUS_DEFINED;
status = SymbolStatus::kDefined;
symbol_info->set_status(status);
}
return status;

View File

@ -33,7 +33,7 @@ class TestModule : public Module {
bool ContainsAddress(uint32_t address) override;
SymbolInfo::Status DeclareFunction(uint32_t address,
SymbolStatus DeclareFunction(uint32_t address,
FunctionInfo** out_symbol_info) override;
private:

View File

@ -29,7 +29,8 @@ using namespace xe::kernel;
using PPCContext = xe::cpu::frontend::PPCContext;
void UndefinedImport(PPCContext* ppc_state, void* arg0, void* arg1) {
void UndefinedImport(PPCContext* ppc_context,
kernel::KernelState* kernel_state) {
XELOGE("call to undefined import");
}
@ -118,7 +119,7 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
libname = libname.substr(0, dot);
}
KernelExport* kernel_export = NULL; // kernel export info
Export* kernel_export = nullptr; // kernel export info
uint32_t user_export_addr = 0; // user export address
if (kernel_state_->IsKernelModule(library->name)) {
@ -145,15 +146,15 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
VariableInfo* var_info;
DeclareVariable(info->value_address, &var_info);
// var->set_name(name);
var_info->set_status(SymbolInfo::STATUS_DECLARED);
var_info->set_status(SymbolStatus::kDeclared);
DefineVariable(var_info);
// var->kernel_export = kernel_export;
var_info->set_status(SymbolInfo::STATUS_DEFINED);
var_info->set_status(SymbolStatus::kDefined);
// Grab, if available.
auto slot = memory_->TranslateVirtual<uint32_t*>(info->value_address);
if (kernel_export) {
if (kernel_export->type == KernelExport::Function) {
if (kernel_export->type == Export::Type::kFunction) {
// Not exactly sure what this should be...
if (info->thunk_address) {
*slot = xe::byte_swap(info->thunk_address);
@ -164,7 +165,7 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
*slot = xe::byte_swap(0xF00DF00D);
}
} else {
if (kernel_export->is_implemented) {
if (kernel_export->is_implemented()) {
// Implemented - replace with pointer.
xe::store_and_swap<uint32_t>(slot, kernel_export->variable_ptr);
} else {
@ -232,22 +233,19 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
xe::store_and_swap<uint32_t>(p + 0xC, 0x60000000);
FunctionInfo::ExternHandler handler = 0;
void* handler_data = 0;
if (kernel_export) {
handler =
(FunctionInfo::ExternHandler)kernel_export->function_data.shim;
handler_data = kernel_export->function_data.shim_data;
} else {
handler = (FunctionInfo::ExternHandler)UndefinedImport;
handler_data = this;
handler = UndefinedImport;
}
FunctionInfo* fn_info;
DeclareFunction(info->thunk_address, &fn_info);
fn_info->set_end_address(info->thunk_address + 16 - 4);
fn_info->set_name(name);
fn_info->SetupExtern(handler, handler_data, NULL);
fn_info->set_status(SymbolInfo::STATUS_DECLARED);
fn_info->SetupExtern(handler);
fn_info->set_status(SymbolStatus::kDeclared);
}
}
}
@ -470,8 +468,8 @@ bool XexModule::FindSaveRest() {
symbol_info->set_name(name);
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveGprLr;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
symbol_info->set_behavior(FunctionBehavior::kProlog);
symbol_info->set_status(SymbolStatus::kDeclared);
address += 4;
}
address = gplr_start + 20 * 4;
@ -483,8 +481,8 @@ bool XexModule::FindSaveRest() {
symbol_info->set_name(name);
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestGprLr;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG_RETURN);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
symbol_info->set_behavior(FunctionBehavior::kEpilogReturn);
symbol_info->set_status(SymbolStatus::kDeclared);
address += 4;
}
}
@ -498,8 +496,8 @@ bool XexModule::FindSaveRest() {
symbol_info->set_name(name);
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveFpr;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
symbol_info->set_behavior(FunctionBehavior::kProlog);
symbol_info->set_status(SymbolStatus::kDeclared);
address += 4;
}
address = fpr_start + (18 * 4) + (1 * 4);
@ -511,8 +509,8 @@ bool XexModule::FindSaveRest() {
symbol_info->set_name(name);
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestFpr;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
symbol_info->set_behavior(FunctionBehavior::kEpilog);
symbol_info->set_status(SymbolStatus::kDeclared);
address += 4;
}
}
@ -530,8 +528,8 @@ bool XexModule::FindSaveRest() {
symbol_info->set_name(name);
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
symbol_info->set_behavior(FunctionBehavior::kProlog);
symbol_info->set_status(SymbolStatus::kDeclared);
address += 2 * 4;
}
address += 4;
@ -542,8 +540,8 @@ bool XexModule::FindSaveRest() {
symbol_info->set_name(name);
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
symbol_info->set_behavior(FunctionBehavior::kProlog);
symbol_info->set_status(SymbolStatus::kDeclared);
address += 2 * 4;
}
address = vmx_start + (18 * 2 * 4) + (1 * 4) + (64 * 2 * 4) + (1 * 4);
@ -554,8 +552,8 @@ bool XexModule::FindSaveRest() {
symbol_info->set_name(name);
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
symbol_info->set_behavior(FunctionBehavior::kEpilog);
symbol_info->set_status(SymbolStatus::kDeclared);
address += 2 * 4;
}
address += 4;
@ -566,8 +564,8 @@ bool XexModule::FindSaveRest() {
symbol_info->set_name(name);
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
symbol_info->set_behavior(FunctionBehavior::kEpilog);
symbol_info->set_status(SymbolStatus::kDeclared);
address += 2 * 4;
}
}

View File

@ -34,7 +34,7 @@ uint32_t XKernelModule::GetProcAddressByOrdinal(uint16_t ordinal) {
// Export (or its parent library) not found.
return 0;
}
if (export->type == cpu::KernelExport::ExportType::Variable) {
if (export->type == cpu::Export::Type::kVariable) {
if (export->variable_ptr) {
return export->variable_ptr;
} else {

View File

@ -338,11 +338,11 @@ void XUserModule::Dump() {
const xe_xex2_import_info_t* info = &import_infos[m];
if (kernel_state_->IsKernelModule(library->name)) {
KernelExport* kernel_export =
auto kernel_export =
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
if (kernel_export) {
known_count++;
if (kernel_export->is_implemented) {
if (kernel_export->is_implemented()) {
impl_count++;
} else {
unimpl_count++;
@ -384,13 +384,13 @@ void XUserModule::Dump() {
const char* name = "UNKNOWN";
bool implemented = false;
KernelExport* kernel_export = nullptr;
Export* kernel_export = nullptr;
if (kernel_state_->IsKernelModule(library->name)) {
kernel_export =
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
if (kernel_export) {
name = kernel_export->name;
implemented = kernel_export->is_implemented;
name = kernel_export->name.c_str();
implemented = kernel_export->is_implemented();
}
} else {
auto module = kernel_state_->GetModule(library->name);
@ -399,7 +399,7 @@ void XUserModule::Dump() {
implemented = true;
}
}
if (kernel_export && kernel_export->type == KernelExport::Variable) {
if (kernel_export && kernel_export->type == Export::Type::kVariable) {
printf(" V %.8X %.3X (%3d) %s %s\n", info->value_address,
info->ordinal, info->ordinal, implemented ? " " : "!!", name);
} else if (info->thunk_address) {

View File

@ -13,7 +13,7 @@
*
* // Build the export table used for resolution.
* #include "xenia/kernel/util/export_table_pre.inc"
* static KernelExport my_module_export_table[] = {
* static Export my_module_export_table[] = {
* #include "xenia/kernel/my_module/my_module_table.inc"
* };
* #include "xenia/kernel/util/export_table_post.inc"
@ -23,11 +23,10 @@
*/
#define XE_EXPORT(module, ordinal, name, type, flags) \
#define XE_EXPORT(module, ordinal, name, type) \
{ \
ordinal, \
xe::cpu::KernelExport::type, \
flags, \
xe::cpu::Export::Type::type, \
#name, \
}

View File

@ -22,6 +22,6 @@
*/
#define XE_EXPORT(module, ordinal, name, type, flags) \
#define XE_EXPORT(module, ordinal, name, type) \
name = ordinal

View File

@ -21,7 +21,7 @@ using PPCContext = xe::cpu::frontend::PPCContext;
#define SHIM_CALL void _cdecl
#define SHIM_SET_MAPPING(library_name, export_name, shim_data) \
export_resolver->SetFunctionMapping( \
library_name, ordinals::##export_name, shim_data, \
library_name, ordinals::##export_name, \
(xe::cpu::xe_kernel_export_shim_fn)export_name##_shim);
#define SHIM_MEM_BASE ppc_state->virtual_membase

View File

@ -42,7 +42,7 @@ void XamModule::RegisterExportTable(xe::cpu::ExportResolver* export_resolver) {
// Build the export table used for resolution.
#include "xenia/kernel/util/export_table_pre.inc"
static xe::cpu::KernelExport xam_export_table[] = {
static xe::cpu::Export xam_export_table[] = {
#include "xenia/kernel/xam_table.inc"
};
#include "xenia/kernel/util/export_table_post.inc"

File diff suppressed because it is too large Load Diff

View File

@ -159,7 +159,7 @@ void XboxkrnlModule::RegisterExportTable(
// Build the export table used for resolution.
#include "xenia/kernel/util/export_table_pre.inc"
static xe::cpu::KernelExport xboxkrnl_export_table[] = {
static xe::cpu::Export xboxkrnl_export_table[] = {
#include "xenia/kernel/xboxkrnl_table.inc"
};
#include "xenia/kernel/util/export_table_post.inc"

File diff suppressed because it is too large Load Diff