diff --git a/debugger/assets/styles/app.css b/debugger/assets/styles/app.css index fd7b6a8de..b2bea1bd7 100644 --- a/debugger/assets/styles/app.css +++ b/debugger/assets/styles/app.css @@ -134,7 +134,7 @@ body { flex: 0 0 auto; display: flex; flex-flow: column nowrap; - max-width: 200px; + min-width: 270px; } .debugger-fnlist-header { order: 1; diff --git a/src/alloy/runtime/module.cc b/src/alloy/runtime/module.cc index 6d7101dd5..4259eb829 100644 --- a/src/alloy/runtime/module.cc +++ b/src/alloy/runtime/module.cc @@ -9,12 +9,17 @@ #include +#include +#include + +#include + using namespace alloy; using namespace alloy::runtime; -Module::Module(Memory* memory) : - memory_(memory) { +Module::Module(Runtime* runtime) : + runtime_(runtime), memory_(runtime->memory()) { lock_ = AllocMutex(10000); } @@ -164,3 +169,74 @@ void Module::ForEachFunction(std::function callback) { } UnlockMutex(lock_); } + +int Module::ReadMap(const char* file_name) { + std::ifstream infile(file_name); + + // Skip until ' Address'. Skip the next blank line. + std::string line; + while (std::getline(infile, line)) { + if (line.find(" Address") == 0) { + // Skip the next line. + std::getline(infile, line); + break; + } + } + + std::stringstream sstream; + std::string ignore; + std::string name; + std::string addr_str; + std::string type_str; + while (std::getline(infile, line)) { + // Remove newline. + while (line.size() && + (line[line.size() - 1] == '\r' || + line[line.size() - 1] == '\n')) { + line.erase(line.end() - 1); + } + + // End when we hit the first whitespace. + if (line.size() == 0) { + break; + } + + // Line is [ws][ignore][ws][name][ws][hex addr][ws][(f)][ws][library] + sstream.clear(); + sstream.str(line); + sstream >> std::ws; + sstream >> ignore; + sstream >> std::ws; + sstream >> name; + sstream >> std::ws; + sstream >> addr_str; + sstream >> std::ws; + sstream >> type_str; + + uint32_t address = (uint32_t)strtoul(addr_str.c_str(), NULL, 16); + if (!address) { + continue; + } + + if (type_str == "f") { + // Function. + FunctionInfo* fn_info; + if (runtime_->LookupFunctionInfo(this, address, &fn_info)) { + continue; + } + // Don't overwrite names we've set elsewhere. + if (!fn_info->name()) { + // If it's an mangled C++ name (?name@...) just use the name. + if (name[0] == '?') { + size_t at = name.find('@'); + name = name.substr(1, at - 1); + } + fn_info->set_name(name.c_str()); + } + } else { + // Variable. + } + } + + return 0; +} diff --git a/src/alloy/runtime/module.h b/src/alloy/runtime/module.h index c294a66b1..bb86f0dc2 100644 --- a/src/alloy/runtime/module.h +++ b/src/alloy/runtime/module.h @@ -21,11 +21,12 @@ namespace alloy { namespace runtime { class Function; +class Runtime; class Module { public: - Module(Memory* memory); + Module(Runtime* runtime); virtual ~Module(); Memory* memory() const { return memory_; } @@ -45,12 +46,15 @@ public: void ForEachFunction(std::function callback); + int ReadMap(const char* file_name); + private: SymbolInfo::Status DeclareSymbol( SymbolInfo::Type type, uint64_t address, SymbolInfo** out_symbol_info); SymbolInfo::Status DefineSymbol(SymbolInfo* symbol_info); protected: + Runtime* runtime_; Memory* memory_; private: diff --git a/src/alloy/runtime/raw_module.cc b/src/alloy/runtime/raw_module.cc index 2993514f5..c152dcf1c 100644 --- a/src/alloy/runtime/raw_module.cc +++ b/src/alloy/runtime/raw_module.cc @@ -13,10 +13,10 @@ using namespace alloy; using namespace alloy::runtime; -RawModule::RawModule(Memory* memory) : +RawModule::RawModule(Runtime* runtime) : name_(0), base_address_(0), low_address_(0), high_address_(0), - Module(memory) { + Module(runtime) { } RawModule::~RawModule() { diff --git a/src/alloy/runtime/raw_module.h b/src/alloy/runtime/raw_module.h index 34852d416..230e44f7e 100644 --- a/src/alloy/runtime/raw_module.h +++ b/src/alloy/runtime/raw_module.h @@ -19,7 +19,7 @@ namespace runtime { class RawModule : public Module { public: - RawModule(Memory* memory); + RawModule(Runtime* runtime); virtual ~RawModule(); int LoadFile(uint64_t base_address, const char* path); diff --git a/src/alloy/runtime/runtime.cc b/src/alloy/runtime/runtime.cc index dbf9c0825..d27bec265 100644 --- a/src/alloy/runtime/runtime.cc +++ b/src/alloy/runtime/runtime.cc @@ -195,11 +195,16 @@ int Runtime::LookupFunctionInfo( return 1; } + return LookupFunctionInfo(code_module, address, out_symbol_info); +} + +int Runtime::LookupFunctionInfo(Module* module, uint64_t address, + FunctionInfo** out_symbol_info) { // Atomic create/lookup symbol in module. // If we get back the NEW flag we must declare it now. FunctionInfo* symbol_info = NULL; SymbolInfo::Status symbol_status = - code_module->DeclareFunction(address, &symbol_info); + module->DeclareFunction(address, &symbol_info); if (symbol_status == SymbolInfo::STATUS_NEW) { // Symbol is undeclared, so declare now. int result = frontend_->DeclareFunction(symbol_info); diff --git a/src/alloy/runtime/runtime.h b/src/alloy/runtime/runtime.h index df6b96782..dc3e4be4f 100644 --- a/src/alloy/runtime/runtime.h +++ b/src/alloy/runtime/runtime.h @@ -47,6 +47,8 @@ public: ModuleList GetModules(); int LookupFunctionInfo(uint64_t address, FunctionInfo** out_symbol_info); + int LookupFunctionInfo(Module* module, uint64_t address, + FunctionInfo** out_symbol_info); int ResolveFunction(uint64_t address, Function** out_function); void AddRegisterAccessCallbacks( diff --git a/src/alloy/runtime/symbol_info.cc b/src/alloy/runtime/symbol_info.cc index 407dc69a0..3a486840d 100644 --- a/src/alloy/runtime/symbol_info.cc +++ b/src/alloy/runtime/symbol_info.cc @@ -15,10 +15,20 @@ using namespace alloy::runtime; SymbolInfo::SymbolInfo(Type type, Module* module, uint64_t address) : type_(type), status_(STATUS_DEFINING), - module_(module), address_(address) { + module_(module), address_(address), name_(0) { } SymbolInfo::~SymbolInfo() { + if (name_) { + xe_free(name_); + } +} + +void SymbolInfo::set_name(const char* name) { + if (name_) { + xe_free(name_); + } + name_ = xestrdupa(name); } FunctionInfo::FunctionInfo(Module* module, uint64_t address) : diff --git a/src/alloy/runtime/symbol_info.h b/src/alloy/runtime/symbol_info.h index a108adc7e..c91fda40a 100644 --- a/src/alloy/runtime/symbol_info.h +++ b/src/alloy/runtime/symbol_info.h @@ -44,11 +44,16 @@ public: void set_status(Status value) { status_ = value; } uint64_t address() const { return address_; } + const char* name() const { return name_; } + void set_name(const char* name); + protected: Type type_; Module* module_; Status status_; uint64_t address_; + + char* name_; }; class FunctionInfo : public SymbolInfo { diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index a7d7f1fb5..e4da4a76d 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -199,11 +199,14 @@ json_t* Processor::OnDebugRequest( json_t* list = json_array(); module->ForEachFunction([&](FunctionInfo* info) { json_t* fn_json = json_object(); - // TODO(benvanik): get name + const char* name = info->name(); char name_buffer[32]; - xesnprintfa(name_buffer, XECOUNT(name_buffer), "sub_%.8X", - info->address()); - json_t* name_json = json_string(name_buffer); + if (!name) { + xesnprintfa(name_buffer, XECOUNT(name_buffer), "sub_%.8X", + info->address()); + name = name_buffer; + } + json_t* name_json = json_string(name); 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); @@ -241,11 +244,14 @@ json_t* Processor::OnDebugRequest( } json_t* fn_json = json_object(); - // TODO(benvanik): get name + const char* name = info->name(); char name_buffer[32]; - xesnprintfa(name_buffer, XECOUNT(name_buffer), "sub_%.8X", - info->address()); - json_t* name_json = json_string(name_buffer); + if (!name) { + xesnprintfa(name_buffer, XECOUNT(name_buffer), "sub_%.8X", + info->address()); + name = name_buffer; + } + json_t* name_json = json_string(name); 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); diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc index 2ee69ff45..d782297f2 100644 --- a/src/xenia/cpu/xex_module.cc +++ b/src/xenia/cpu/xex_module.cc @@ -10,7 +10,7 @@ #include #include - +#include #include #include @@ -31,7 +31,7 @@ XexModule::XexModule( runtime_(runtime), name_(0), path_(0), xex_(0), base_address_(0), low_address_(0), high_address_(0), - Module(runtime->memory()) { + Module(runtime) { } XexModule::~XexModule() { @@ -82,7 +82,11 @@ int XexModule::Load(const char* name, const char* path, xe_xex2_ref xex) { name_ = xestrdupa(name); path_ = xestrdupa(path); // TODO(benvanik): debug info - // TODO(benvanik): load map file. + + // Load a specified module map and diff. + if (FLAGS_load_module_map.size()) { + ReadMap(FLAGS_load_module_map.c_str()); + } return 0; } @@ -158,7 +162,7 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) { fn_info->set_end_address(info->thunk_address + 16 - 4); //fn->type = FunctionSymbol::Kernel; //fn->kernel_export = kernel_export; - //fn->set_name(name); + fn_info->set_name(name); fn_info->set_status(SymbolInfo::STATUS_DECLARED); ExternFunction::Handler handler = 0; @@ -406,7 +410,7 @@ int XexModule::FindSaveRest() { FunctionInfo* symbol_info; DeclareFunction(address, &symbol_info); symbol_info->set_end_address(address + (31 - n) * 4 + 2 * 4); - // TODO(benvanik): set name + 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); @@ -419,7 +423,7 @@ int XexModule::FindSaveRest() { FunctionInfo* symbol_info; DeclareFunction(address, &symbol_info); symbol_info->set_end_address(address + (31 - n) * 4 + 3 * 4); - // TODO(benvanik): set name + 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); @@ -434,7 +438,7 @@ int XexModule::FindSaveRest() { FunctionInfo* symbol_info; DeclareFunction(address, &symbol_info); symbol_info->set_end_address(address + (31 - n) * 4 + 1 * 4); - // TODO(benvanik): set name + 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); @@ -447,7 +451,7 @@ int XexModule::FindSaveRest() { FunctionInfo* symbol_info; DeclareFunction(address, &symbol_info); symbol_info->set_end_address(address + (31 - n) * 4 + 1 * 4); - // TODO(benvanik): set name + 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); @@ -466,7 +470,7 @@ int XexModule::FindSaveRest() { xesnprintfa(name, XECOUNT(name), "__savevmx_%d", n); FunctionInfo* symbol_info; DeclareFunction(address, &symbol_info); - // TODO(benvanik): set name + 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); @@ -478,7 +482,7 @@ int XexModule::FindSaveRest() { xesnprintfa(name, XECOUNT(name), "__savevmx_%d", n); FunctionInfo* symbol_info; DeclareFunction(address, &symbol_info); - // TODO(benvanik): set name + 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); @@ -490,7 +494,7 @@ int XexModule::FindSaveRest() { xesnprintfa(name, XECOUNT(name), "__restvmx_%d", n); FunctionInfo* symbol_info; DeclareFunction(address, &symbol_info); - // TODO(benvanik): set name + 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); @@ -502,7 +506,7 @@ int XexModule::FindSaveRest() { xesnprintfa(name, XECOUNT(name), "__restvmx_%d", n); FunctionInfo* symbol_info; DeclareFunction(address, &symbol_info); - // TODO(benvanik): set name + 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); diff --git a/tools/alloy-sandbox/alloy-sandbox.cc b/tools/alloy-sandbox/alloy-sandbox.cc index 6afe7b75f..199232b66 100644 --- a/tools/alloy-sandbox/alloy-sandbox.cc +++ b/tools/alloy-sandbox/alloy-sandbox.cc @@ -38,7 +38,7 @@ int alloy_sandbox(int argc, xechar_t** argv) { // runtime); runtime->Initialize(backend); - RawModule* module = new RawModule(runtime->memory()); + RawModule* module = new RawModule(runtime); module->LoadFile(0x82000000, "test\\codegen\\instr_add.bin"); runtime->AddModule(module);