From 0af6c1ce8b4a8988c2c728499b7c25d4add62109 Mon Sep 17 00:00:00 2001 From: dave-br Date: Fri, 9 May 2025 16:04:32 -0700 Subject: [PATCH] debugger: symlist usability + symbol table extensibility Address issue #6655 (symlist command usability), add a bit of plumbing for future extensibility. symlist with no arguments displays all global *and* :maincpu symbols, with clear header text for each list. At the bottom, prints helper text to make user aware of the cpu form To allow for adding new kinds of symbols in the future, this adds an enum field to symbol table for its 'type', for prettier printing from symlist. Symlist now traverses symbol table chain completely. --- src/emu/debug/debugcmd.cpp | 96 ++++++++++++++++----------- src/emu/debug/debugcpu.cpp | 4 +- src/emu/debug/express.cpp | 3 +- src/emu/debug/express.h | 13 +++- src/frontend/mame/cheat.cpp | 4 +- src/frontend/mame/luaengine_debug.cpp | 2 +- 6 files changed, 78 insertions(+), 44 deletions(-) diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index 0b7efa44a938d..76a6053477f9c 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -3909,58 +3909,80 @@ void debugger_commands::execute_memdump(const std::vector &par void debugger_commands::execute_symlist(const std::vector ¶ms) { - const char *namelist[1000]; + // Default to CPU "0" if none specified + const char * cpuname = (params.empty()) ? "0" : params[0].cbegin(); + device_t *cpu = nullptr; symbol_table *symtable; - int count = 0; - - if (!params.empty()) + if (!m_console.validate_cpu_parameter(cpuname, cpu)) { - // validate parameters - device_t *cpu; - if (!m_console.validate_cpu_parameter(params[0], cpu)) - return; - symtable = &cpu->debug()->symtable(); - m_console.printf("CPU '%s' symbols:\n", cpu->tag()); + if (!params.empty()) + return; // Explicitly specified cpu is invalid + + // Somehow cpu "0" is invalid, so just stick with global symbol table + symtable = &m_machine.debugger().cpu().global_symtable(); } else { - symtable = &m_machine.debugger().cpu().global_symtable(); - m_console.printf("Global symbols:\n"); + symtable = &cpu->debug()->symtable(); } - // gather names for all symbols - for (auto &entry : symtable->entries()) + // Traverse symbol_table parent chain, printing each table's symbols in its own block + for (; symtable != nullptr; symtable = symtable->parent()) { - // only display "register" type symbols - if (!entry.second->is_function()) + // Skip globals if user explicitly requested CPU + if (symtable->type() == symbol_table::BUILTIN_GLOBALS && !params.empty()) + continue; + + if (symtable->entries().size() == 0) + continue; + + std::vector namelist; + + // Print heading for table + switch (symtable->type()) { - namelist[count++] = entry.second->name(); - if (count >= std::size(namelist)) - break; + case symbol_table::CPU_STATE: + m_console.printf("\n**** CPU '%s' symbols ****\n", cpu->tag()); + break; + case symbol_table::BUILTIN_GLOBALS: + m_console.printf("\n**** Global symbols ****\n"); + break; + default: + assert (!"Unrecognized symbol table type"); } - } - // sort the symbols - if (count > 1) - { + // gather names for all relevant symbols + for (auto &entry : symtable->entries()) + { + // ignore built-in function symbols + if (!entry.second->is_function()) + { + namelist.push_back(entry.second->name()); + } + } + + // sort the symbols std::sort( - &namelist[0], - &namelist[count], + namelist.begin(), + namelist.end(), [] (const char *item1, const char *item2) { return strcmp(item1, item2) < 0; }); - } - // iterate over symbols and print out relevant ones - for (int symnum = 0; symnum < count; symnum++) + // iterate over symbols and print them + for (const char * symname : namelist) + { + symbol_entry const *const entry = symtable->find(symname); + assert(entry != nullptr); + m_console.printf("%s = %X", symname, entry->value()); + if (!entry->is_lval()) + m_console.printf(" (read-only)"); + m_console.printf("\n"); + } + } + if (params.empty()) { - symbol_entry const *const entry = symtable->find(namelist[symnum]); - assert(entry != nullptr); - u64 value = entry->value(); - - // only display "register" type symbols - m_console.printf("%s = %X", namelist[symnum], value); - if (!entry->is_lval()) - m_console.printf(" (read-only)"); - m_console.printf("\n"); + m_console.printf( + "\nTo view the symbols for a particular CPU, try symlist ,\n" + "where is the ID number or tag for a CPU.\n"); } } diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp index 968966b1b74ac..c975bdd4471ed 100644 --- a/src/emu/debug/debugcpu.cpp +++ b/src/emu/debug/debugcpu.cpp @@ -57,7 +57,7 @@ debugger_cpu::debugger_cpu(running_machine &machine) m_tempvar = make_unique_clear(NUM_TEMP_VARIABLES); /* create a global symbol table */ - m_symtable = std::make_unique(machine); + m_symtable = std::make_unique(machine, symbol_table::BUILTIN_GLOBALS); m_symtable->set_memory_modified_func([this]() { set_memory_modified(true); }); /* add "wpaddr", "wpdata", "wpsize" to the global symbol table */ @@ -488,7 +488,7 @@ device_debug::device_debug(device_t &device) , m_state(nullptr) , m_disasm(nullptr) , m_flags(0) - , m_symtable(std::make_unique(device.machine(), &device.machine().debugger().cpu().global_symtable(), &device)) + , m_symtable(std::make_unique(device.machine(), symbol_table::CPU_STATE, &device.machine().debugger().cpu().global_symtable(), &device)) , m_stepaddr(0) , m_stepsleft(0) , m_delay_steps(0) diff --git a/src/emu/debug/express.cpp b/src/emu/debug/express.cpp index 9ab75b7b65587..219ed6a89ef9a 100644 --- a/src/emu/debug/express.cpp +++ b/src/emu/debug/express.cpp @@ -363,8 +363,9 @@ symbol_entry::~symbol_entry() // symbol_table - constructor //------------------------------------------------- -symbol_table::symbol_table(running_machine &machine, symbol_table *parent, device_t *device) +symbol_table::symbol_table(running_machine &machine, table_type type, symbol_table *parent, device_t *device) : m_machine(machine) + , m_type(type) , m_parent(parent) , m_memintf(dynamic_cast(device)) , m_memory_modified(nullptr) diff --git a/src/emu/debug/express.h b/src/emu/debug/express.h index 251d8b4365c0d..33ab9c3b472b9 100644 --- a/src/emu/debug/express.h +++ b/src/emu/debug/express.h @@ -171,11 +171,21 @@ class symbol_table READ_WRITE }; + // Identifies the type of symbols stored in this table. These help symlist create + // useful output + enum table_type + { + CPU_STATE, // CPU registers, etc. + BUILTIN_GLOBALS, // Built-in MAME global symbols (e.g., beamx, beamy, frame, etc.) + // (also used for tables outside debugger: lua scripts, cheat engine) + }; + // construction/destruction - symbol_table(running_machine &machine, symbol_table *parent = nullptr, device_t *device = nullptr); + symbol_table(running_machine &machine, table_type type, symbol_table *parent = nullptr, device_t *device = nullptr); // getters const std::unordered_map> &entries() const { return m_symlist; } + table_type type() const { return m_type; } symbol_table *parent() const { return m_parent; } running_machine &machine() { return m_machine; } @@ -212,6 +222,7 @@ class symbol_table // internal state running_machine & m_machine; // reference to the machine + table_type m_type; // kind of symbols stored in this table symbol_table * m_parent; // pointer to the parent symbol table std::unordered_map> m_symlist; // list of symbols device_memory_interface *const m_memintf; // pointer to the local memory interface (if any) diff --git a/src/frontend/mame/cheat.cpp b/src/frontend/mame/cheat.cpp index e0d890ebda6fa..6e10f650328ed 100644 --- a/src/frontend/mame/cheat.cpp +++ b/src/frontend/mame/cheat.cpp @@ -683,7 +683,7 @@ void cheat_script::script_entry::output_argument::save(util::core_file &cheatfil cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, std::string const &filename, util::xml::data_node const &cheatnode) : m_manager(manager) - , m_symbols(manager.machine(), &globaltable) + , m_symbols(manager.machine(), symbol_table::BUILTIN_GLOBALS, &globaltable) , m_state(SCRIPT_STATE_OFF) , m_numtemp(DEFAULT_TEMP_VARIABLES) , m_argindex(0) @@ -1065,7 +1065,7 @@ cheat_manager::cheat_manager(running_machine &machine) , m_numlines(0) , m_lastline(0) , m_disabled(true) - , m_symtable(machine) + , m_symtable(machine, symbol_table::BUILTIN_GLOBALS) { // if the cheat engine is disabled, we're done if (!machine.options().cheat()) diff --git a/src/frontend/mame/luaengine_debug.cpp b/src/frontend/mame/luaengine_debug.cpp index 8cdf29246c019..992a9cc791a73 100644 --- a/src/frontend/mame/luaengine_debug.cpp +++ b/src/frontend/mame/luaengine_debug.cpp @@ -91,7 +91,7 @@ class lua_engine::symbol_table_wrapper symbol_table_wrapper(lua_engine &host, running_machine &machine, std::shared_ptr const &parent, device_t *device) : m_host(host) - , m_table(machine, parent ? &parent->table() : nullptr, device) + , m_table(machine, symbol_table::BUILTIN_GLOBALS, parent ? &parent->table() : nullptr, device) , m_parent(parent) { }