Function listing and selection.
This commit is contained in:
@@ -152,3 +152,15 @@ SymbolInfo::Status Module::DefineFunction(FunctionInfo* symbol_info) {
|
||||
SymbolInfo::Status Module::DefineVariable(VariableInfo* symbol_info) {
|
||||
return DefineSymbol((SymbolInfo*)symbol_info);
|
||||
}
|
||||
|
||||
void Module::ForEachFunction(std::function<void (FunctionInfo*)> callback) {
|
||||
LockMutex(lock_);
|
||||
for (SymbolMap::iterator it = map_.begin();
|
||||
it != map_.end(); ++it) {
|
||||
if (it->second->type() == SymbolInfo::TYPE_FUNCTION) {
|
||||
FunctionInfo* info = (FunctionInfo*)it->second;
|
||||
callback(info);
|
||||
}
|
||||
}
|
||||
UnlockMutex(lock_);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#ifndef ALLOY_RUNTIME_MODULE_H_
|
||||
#define ALLOY_RUNTIME_MODULE_H_
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <alloy/core.h>
|
||||
#include <alloy/memory.h>
|
||||
#include <alloy/runtime/symbol_info.h>
|
||||
@@ -41,6 +43,8 @@ public:
|
||||
SymbolInfo::Status DefineFunction(FunctionInfo* symbol_info);
|
||||
SymbolInfo::Status DefineVariable(VariableInfo* symbol_info);
|
||||
|
||||
void ForEachFunction(std::function<void (FunctionInfo*)> callback);
|
||||
|
||||
private:
|
||||
SymbolInfo::Status DeclareSymbol(
|
||||
SymbolInfo::Type type, uint64_t address, SymbolInfo** out_symbol_info);
|
||||
|
||||
@@ -116,6 +116,29 @@ int Runtime::AddModule(Module* module) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Module* Runtime::GetModule(const char* name) {
|
||||
Module* result = NULL;
|
||||
LockMutex(modules_lock_);
|
||||
for (ModuleList::iterator it = modules_.begin();
|
||||
it != modules_.end(); ++it) {
|
||||
Module* module = *it;
|
||||
if (xestrcmpa(module->name(), name) == 0) {
|
||||
result = module;
|
||||
break;
|
||||
}
|
||||
}
|
||||
UnlockMutex(modules_lock_);
|
||||
return result;
|
||||
}
|
||||
|
||||
Runtime::ModuleList Runtime::GetModules() {
|
||||
ModuleList clone;
|
||||
LockMutex(modules_lock_);
|
||||
clone = modules_;
|
||||
UnlockMutex(modules_lock_);
|
||||
return clone;
|
||||
}
|
||||
|
||||
int Runtime::ResolveFunction(uint64_t address, Function** out_function) {
|
||||
*out_function = NULL;
|
||||
Entry* entry;
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace runtime {
|
||||
|
||||
|
||||
class Runtime {
|
||||
public:
|
||||
typedef std::vector<Module*> ModuleList;
|
||||
|
||||
public:
|
||||
Runtime(Memory* memory);
|
||||
virtual ~Runtime();
|
||||
@@ -40,6 +43,8 @@ public:
|
||||
int Initialize(frontend::Frontend* frontend, backend::Backend* backend = 0);
|
||||
|
||||
int AddModule(Module* module);
|
||||
Module* GetModule(const char* name);
|
||||
ModuleList GetModules();
|
||||
|
||||
int LookupFunctionInfo(uint64_t address, FunctionInfo** out_symbol_info);
|
||||
int ResolveFunction(uint64_t address, Function** out_function);
|
||||
@@ -60,7 +65,6 @@ protected:
|
||||
|
||||
EntryTable entry_table_;
|
||||
Mutex* modules_lock_;
|
||||
typedef std::vector<Module*> ModuleList;
|
||||
ModuleList modules_;
|
||||
|
||||
RegisterAccessCallbacks* access_callbacks_;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <xenia/emulator.h>
|
||||
#include <xenia/cpu/xenon_memory.h>
|
||||
#include <xenia/cpu/xenon_runtime.h>
|
||||
#include <xenia/cpu/xex_module.h>
|
||||
|
||||
|
||||
using namespace alloy;
|
||||
@@ -169,5 +170,90 @@ uint64_t Processor::ExecuteInterrupt(
|
||||
json_t* Processor::OnDebugRequest(
|
||||
const char* command, json_t* request, bool& succeeded) {
|
||||
succeeded = true;
|
||||
return json_null();
|
||||
if (xestrcmpa(command, "get_module_list") == 0) {
|
||||
json_t* list = json_array();
|
||||
Runtime::ModuleList modules = runtime_->GetModules();
|
||||
for (Runtime::ModuleList::iterator it = modules.begin();
|
||||
it != modules.end(); ++it) {
|
||||
XexModule* module = (XexModule*)(*it);
|
||||
json_t* module_json = json_object();
|
||||
json_t* module_name_json = json_string(module->name());
|
||||
json_object_set_new(module_json, "name", module_name_json);
|
||||
json_array_append_new(list, module_json);
|
||||
}
|
||||
return list;
|
||||
/*} else if (xestrcmpa(command, "get_module") == 0) {
|
||||
return json_null();*/
|
||||
} else if (xestrcmpa(command, "get_function_list") == 0) {
|
||||
json_t* module_name_json = json_object_get(request, "module");
|
||||
if (!module_name_json || !json_is_string(module_name_json)) {
|
||||
succeeded = false;
|
||||
return json_string("Module name not specified");
|
||||
}
|
||||
const char* module_name = json_string_value(module_name_json);
|
||||
XexModule* module = (XexModule*)runtime_->GetModule(module_name);
|
||||
if (!module) {
|
||||
succeeded = false;
|
||||
return json_string("Module not found");
|
||||
}
|
||||
json_t* list = json_array();
|
||||
module->ForEachFunction([&](FunctionInfo* info) {
|
||||
json_t* fn_json = json_object();
|
||||
// TODO(benvanik): get name
|
||||
char name_buffer[32];
|
||||
xesnprintfa(name_buffer, XECOUNT(name_buffer), "sub_%.8X",
|
||||
info->address());
|
||||
json_t* name_json = json_string(name_buffer);
|
||||
json_object_set_new(fn_json, "name", name_json);
|
||||
json_t* address_json = json_integer(info->address());
|
||||
json_object_set_new(fn_json, "address", address_json);
|
||||
json_t* link_status_json = json_integer(info->status());
|
||||
json_object_set_new(fn_json, "linkStatus", link_status_json);
|
||||
json_array_append_new(list, fn_json);
|
||||
});
|
||||
return list;
|
||||
} else if (xestrcmpa(command, "get_function") == 0) {
|
||||
json_t* address_json = json_object_get(request, "address");
|
||||
if (!address_json || !json_is_number(address_json)) {
|
||||
succeeded = false;
|
||||
return json_string("Function address not specified");
|
||||
}
|
||||
uint64_t address = (uint64_t)json_number_value(address_json);
|
||||
|
||||
FunctionInfo* info;
|
||||
if (runtime_->LookupFunctionInfo(address, &info)) {
|
||||
succeeded = false;
|
||||
return json_string("Function not found");
|
||||
}
|
||||
|
||||
// Demand a new function with all debug info retained.
|
||||
// If we ever wanted absolute x64 addresses/etc we could
|
||||
// use the x64 from the function in the symbol table.
|
||||
Function* fn;
|
||||
if (runtime_->frontend()->DefineFunction(info, &fn)) {
|
||||
succeeded = false;
|
||||
return json_string("Unable to resolve function");
|
||||
}
|
||||
|
||||
json_t* fn_json = json_object();
|
||||
// TODO(benvanik): get name
|
||||
char name_buffer[32];
|
||||
xesnprintfa(name_buffer, XECOUNT(name_buffer), "sub_%.8X",
|
||||
info->address());
|
||||
json_t* name_json = json_string(name_buffer);
|
||||
json_object_set_new(fn_json, "name", name_json);
|
||||
json_t* start_address_json = json_integer(info->address());
|
||||
json_object_set_new(fn_json, "startAddress", start_address_json);
|
||||
json_t* end_address_json = json_integer(info->end_address());
|
||||
json_object_set_new(fn_json, "endAddress", end_address_json);
|
||||
json_t* link_status_json = json_integer(info->status());
|
||||
json_object_set_new(fn_json, "linkStatus", link_status_json);
|
||||
|
||||
delete fn;
|
||||
|
||||
return fn_json;
|
||||
} else {
|
||||
succeeded = false;
|
||||
return json_string("Unknown command");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user