From 705ac744980393d3f4d81501acdedd8b57f6ab3c Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 3 Mar 2016 12:00:07 +0100 Subject: [PATCH] CLI monitor: remove unused GDB command This patch removes the support for executing subsystems of CLI monitor within the GDB monitor. There are multiple reasons: First, the feature remained unused for multiple years. Second, it relied on the base/elf.h header to determine whether the started binary is dynamically or statically linked. This header, however, is going to be removed from the Genode API. Third, the feature will eventually break with the upcoming changes of how components are bootstrapped. Finally, there is the plan to turn CLI monitor into a sole front end of a dynamically configurable init component. Once we pursue this plan, we'd need to reconsider the GDB support anyway. Issue #1832 --- repos/os/src/app/cli_monitor/gdb_command.h | 553 --------------------- repos/os/src/app/cli_monitor/main.cc | 25 - 2 files changed, 578 deletions(-) delete mode 100644 repos/os/src/app/cli_monitor/gdb_command.h diff --git a/repos/os/src/app/cli_monitor/gdb_command.h b/repos/os/src/app/cli_monitor/gdb_command.h deleted file mode 100644 index d52ff0f6e..000000000 --- a/repos/os/src/app/cli_monitor/gdb_command.h +++ /dev/null @@ -1,553 +0,0 @@ -/* - * \brief Gdb command - * \author Norman Feske - * \author Christian Prochaska - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _GDB_COMMAND_H_ -#define _GDB_COMMAND_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include - -/* public CLI-monitor includes */ -#include - -/* local includes */ -#include -#include -#include -#include - -class Gdb_command_child : public Child -{ - private: - - Genode::Signal_context_capability _kill_gdb_sig_cap; - Genode::Signal_context_capability _exit_sig_cap; - - Terminal::Session &_terminal; - - bool _kill_requested; - - void _kill_gdb() - { - _kill_requested = true; - Genode::Signal_transmitter(_kill_gdb_sig_cap).submit(); - } - - public: - - Gdb_command_child(Ram &ram, - char const *label, - char const *binary, - Genode::Cap_session &cap_session, - Genode::size_t ram_quota, - Genode::size_t ram_limit, - Genode::Signal_context_capability yield_response_sig_cap, - Genode::Signal_context_capability kill_gdb_sig_cap, - Genode::Signal_context_capability exit_sig_cap, - Terminal::Session &terminal) - : Child(ram, label, binary, cap_session, ram_quota, ram_limit, - yield_response_sig_cap, exit_sig_cap), - _kill_gdb_sig_cap(kill_gdb_sig_cap), - _exit_sig_cap(exit_sig_cap), - _terminal(terminal), - _kill_requested(false) - { } - - bool kill_requested() const { return _kill_requested; } - - /* - * Check if GDB-related (Noux) session-requests will be successful. - * If not, terminate the subsystem and tell the user about it. - */ - Genode::Service *resolve_session_request(const char *service_name, - const char *args) - { - if (_kill_requested) - return 0; - - Genode::Service *service = - Child::resolve_session_request(service_name, args); - - if (!service) { - tprintf(_terminal, "Error: GDB subsystem session request for service '%s' failed\n", - service_name); - PDBG("session request failed: service_name = %s, args = %s", service_name, args); - _kill_gdb(); - return 0; - } - - /* Find out if the session request comes from Noux */ - - const char *noux_label_suffix = " -> noux"; - - /* Arg::string() needs two extra bytes */ - size_t label_size = strlen(name()) + strlen(noux_label_suffix) + 2; - - char noux_label_buf[label_size]; - snprintf(noux_label_buf, sizeof(noux_label_buf), - "%s%s", name(), noux_label_suffix); - - char label_buf[label_size]; - Genode::Arg_string::find_arg(args, "label").string(label_buf, - sizeof(label_buf), - ""); - - if (strcmp(label_buf, noux_label_buf, label_size) == 0) { - /* Try to create and close the session */ - try { - Genode::Session_capability s = service->session(args, Genode::Affinity()); - service->close(s); - } catch (...) { - tprintf(_terminal, "Error: GDB subsystem session request for service '%s' failed\n", - service_name); - PDBG("session request failed: service_name = %s, args = %s", service_name, args); - _kill_gdb(); - return 0; - } - } - - return service; - } - -}; - - -class Gdb_command : public Command -{ - private: - - typedef Genode::Xml_node Xml_node; - typedef Genode::Signal_context_capability Signal_context_capability; - - struct Child_configuration_failed {}; /* exception */ - - Ram &_ram; - Child_registry &_children; - Genode::Cap_session &_cap; - Subsystem_config_registry &_subsystem_configs; - Signal_context_capability _yield_response_sigh_cap; - Signal_context_capability _kill_gdb_sig_cap; - Signal_context_capability _exit_sig_cap; - - /** - * Generate the config node for the GDB subsystem - */ - Xml_node _gdb_config_node(const char *binary_name, - const char *target_config_addr, - const size_t target_config_size, - Genode::Number_of_bytes gdb_ram_preserve, - Terminal::Session &terminal) - { - /* local exception types */ - struct Config_buffer_overflow { }; - struct Binary_elf_check_failed { }; - - try { - Genode::Attached_rom_dataspace gdb_command_config_ds("gdb_command_config"); - - enum { CONFIG_BUF_SIZE = 4*1024 }; - static char config_buf[CONFIG_BUF_SIZE]; - - int config_bytes_written = 0; - - /* - * Copy the first part of the config file template - */ - - Xml_node init_config_node(gdb_command_config_ds.local_addr(), - gdb_command_config_ds.size()); - - Xml_node noux_node = init_config_node.sub_node("start"); - for (;; noux_node = noux_node.next("start")) - if (noux_node.attribute("name").has_value("noux")) - break; - - Xml_node noux_config_node = noux_node.sub_node("config"); - - /* Genode::strncpy() makes the last character '\0', so we need to add 1 byte */ - size_t bytes_to_copy = (Genode::addr_t)noux_config_node.content_addr() - - (Genode::addr_t)init_config_node.addr() + 1; - - if ((sizeof(config_buf) - config_bytes_written) < bytes_to_copy) - throw Config_buffer_overflow(); - - strncpy(&config_buf[config_bytes_written], - init_config_node.addr(), - bytes_to_copy); - - /* subtract the byte for '\0' again */ - config_bytes_written += bytes_to_copy - 1; - - /* - * Create the GDB arguments for breaking in 'main()' - */ - - enum { GDB_MAIN_BREAKPOINT_ARGS_BUF_SIZE = 768 }; - static char gdb_main_breakpoint_args_buf[GDB_MAIN_BREAKPOINT_ARGS_BUF_SIZE]; - - try { - Genode::Attached_rom_dataspace binary_rom_ds(binary_name); - Genode::Elf_binary elf_binary((Genode::addr_t)binary_rom_ds.local_addr()); - - if (elf_binary.is_dynamically_linked()) { - - snprintf(gdb_main_breakpoint_args_buf, - sizeof(gdb_main_breakpoint_args_buf), - "\n \ - \n \ - \n \ - \n \ - \n \ - \n \ - \n \ - \n \ - \n \ - \n", - binary_name); - } else { - - snprintf(gdb_main_breakpoint_args_buf, - sizeof(gdb_main_breakpoint_args_buf), - "\n \ - \n \ - \n \ - \n", - binary_name); - } - } catch (...) { - throw Binary_elf_check_failed(); - } - - /* - * Insert the '' node for 'noux' - */ - - config_bytes_written += snprintf(&config_buf[config_bytes_written], - sizeof(config_buf) - config_bytes_written, "\n \ - \n \ - \n \ - \n \ - \n \ - \n \ - %s \ - \n \ - ", - gdb_prefix, - binary_name, - gdb_main_breakpoint_args_buf); - - /* - * Copy the second part of the config file template - */ - - Xml_node gdb_monitor_node = noux_node.next("start"); - - /* Genode::strncpy() makes the last character '\0', so we need to add 1 byte */ - bytes_to_copy = (Genode::addr_t)gdb_monitor_node.content_addr() - - (Genode::addr_t)noux_config_node.content_addr() + 1; - - if ((sizeof(config_buf) - config_bytes_written) < bytes_to_copy) - throw Config_buffer_overflow(); - - strncpy(&config_buf[config_bytes_written], - noux_config_node.content_addr(), - bytes_to_copy); - - /* subtract the byte for '\0' again */ - config_bytes_written += bytes_to_copy - 1; - - /* - * Create a zero-terminated string for the GDB target config node - */ - - char target_config[target_config_size + 1]; - if (target_config_addr) - Genode::strncpy(target_config, target_config_addr, sizeof(target_config)); - else - target_config[0] = '\0'; - - /* - * Insert the '' node for 'gdb_monitor' - */ - - config_bytes_written += Genode::snprintf(&config_buf[config_bytes_written], - (sizeof(config_buf) - config_bytes_written), "\n \ - \n \ - \n \ - %s \ - \n \ - \n \ - \ - ", - binary_name, - target_config, - (size_t)gdb_ram_preserve); - - /* - * Copy the third (and final) part of the config file template - */ - - /* Genode::strncpy() makes the last character '\0', so we need to add 1 byte */ - bytes_to_copy = ((Genode::addr_t)init_config_node.addr() + - init_config_node.size()) - - (Genode::addr_t)gdb_monitor_node.content_addr() + 1; - - if ((sizeof(config_buf) - config_bytes_written) < bytes_to_copy) - throw Config_buffer_overflow(); - - strncpy(&config_buf[config_bytes_written], - gdb_monitor_node.content_addr(), - bytes_to_copy); - - /* subtract the byte for '\0' again */ - config_bytes_written += bytes_to_copy - 1; - - return Xml_node(config_buf, config_bytes_written); - - } catch (Config_buffer_overflow) { - tprintf(terminal, "Error: the buffer for the generated GDB " - "subsystem configuration is too small.\n"); - throw Child_configuration_failed(); - } catch (Binary_elf_check_failed) { - tprintf(terminal, "Error: could not determine link type of the " - "GDB target binary.\n"); - throw Child_configuration_failed(); - } - } - - void _execute_subsystem(char const *name, Command_line &cmd, - Terminal::Session &terminal, - Xml_node subsystem_node) - { - Genode::Number_of_bytes ram = 0; - Genode::Number_of_bytes ram_limit = 0; - Genode::Number_of_bytes gdb_ram_preserve = 10*1024*1024; - - /* read default RAM quota from config */ - try { - Xml_node rsc = subsystem_node.sub_node("resource"); - for (;; rsc = rsc.next("resource")) { - if (rsc.attribute("name").has_value("RAM")) { - rsc.attribute("quantum").value(&ram); - - if (rsc.has_attribute("limit")) - rsc.attribute("limit").value(&ram_limit); - break; - } - } - } catch (...) { } - - cmd.parameter("--ram", ram); - cmd.parameter("--ram-limit", ram_limit); - cmd.parameter("--gdb-ram-preserve", gdb_ram_preserve); - - /* account for cli_monitor local metadata */ - size_t preserve_ram = 100*1024; - if ((ram + preserve_ram) > Genode::env()->ram_session()->avail()) { - tprintf(terminal, "Error: RAM quota exceeds available quota\n"); - return; - } - - bool const verbose = cmd.parameter_exists("--verbose"); - - /* - * Determine binary name - * - * Use subsystem name by default, override with '' declaration. - */ - char binary_name[128]; - strncpy(binary_name, name, sizeof(binary_name)); - try { - Xml_node bin = subsystem_node.sub_node("binary"); - bin.attribute("name").value(binary_name, sizeof(binary_name)); - } catch (...) { } - - /* generate unique child name */ - char label[Child_registry::CHILD_NAME_MAX_LEN]; - _children.unique_child_name(name, label, sizeof(label)); - - tprintf(terminal, "starting new subsystem '%s'\n", label); - - if (verbose) { - tprintf(terminal, " RAM quota: "); - tprint_bytes(terminal, ram); - tprintf(terminal,"\n"); - if (ram_limit) { - tprintf(terminal, " RAM limit: "); - tprint_bytes(terminal, ram_limit); - tprintf(terminal,"\n"); - } - tprintf(terminal, " binary: %s\n", binary_name); - } - - Child *child = 0; - try { - - /* create child configuration */ - const char *target_config_addr = 0; - size_t target_config_size = 0; - try { - Xml_node target_config_node = subsystem_node.sub_node("config"); - target_config_addr = target_config_node.addr(); - target_config_size = target_config_node.size(); - } catch (...) { } - - Xml_node config_node = _gdb_config_node(binary_name, - target_config_addr, - target_config_size, - gdb_ram_preserve, - terminal); - - /* create child */ - child = new (Genode::env()->heap()) - Gdb_command_child(_ram, label, "init", _cap, ram, ram_limit, - _yield_response_sigh_cap, _kill_gdb_sig_cap, - _exit_sig_cap, terminal); - - /* configure child */ - try { - child->configure(config_node.addr(), config_node.size()); - if (verbose) - tprintf(terminal, " config: inline\n"); - } catch (...) { - if (verbose) - tprintf(terminal, " config: none\n"); - } - - } - catch (Child_configuration_failed) { - return; - } - catch (Genode::Rom_connection::Rom_connection_failed) { - tprintf(terminal, "Error: could not obtain ROM module \"%s\"\n", - binary_name); - return; - } - catch (Child::Quota_exceeded) { - tprintf(terminal, "Error: insufficient memory, need "); - tprint_bytes(terminal, ram + Child::DONATED_RAM_QUOTA); - tprintf(terminal, ", have "); - tprint_bytes(terminal, Genode::env()->ram_session()->avail()); - tprintf(terminal, "\n"); - return; - } - catch (Genode::Allocator::Out_of_memory) { - tprintf(terminal, "Error: could not allocate meta data, out of memory\n"); - return; - } - - _children.insert(child); - child->start(); - } - - public: - - Gdb_command(Ram &ram, Genode::Cap_session &cap, Child_registry &children, - Subsystem_config_registry &subsustem_configs, - Signal_context_capability yield_response_sigh_cap, - Signal_context_capability kill_gdb_sig_cap, - Signal_context_capability exit_sig_cap) - : - Command("gdb", "create new subsystem with GDB"), - _ram(ram), _children(children), _cap(cap), - _subsystem_configs(subsustem_configs), - _yield_response_sigh_cap(yield_response_sigh_cap), - _kill_gdb_sig_cap(kill_gdb_sig_cap), - _exit_sig_cap(exit_sig_cap) - { - add_parameter(new Parameter("--ram", Parameter::NUMBER, "initial RAM quota")); - add_parameter(new Parameter("--ram-limit", Parameter::NUMBER, "limit for expanding RAM quota")); - add_parameter(new Parameter("--gdb-ram-preserve", Parameter::NUMBER, - "RAM quota which GDB monitor should preserve for itself (default: 5M)")); - add_parameter(new Parameter("--verbose", Parameter::VOID, "show diagnostics")); - } - - void _for_each_argument(Argument_fn const &fn) const override - { - /* functor for processing a subsystem configuration */ - auto process_subsystem_config_fn = [&] (Genode::Xml_node node) { - - char name[Parameter::Name::size()]; - try { node.attribute("name").value(name, sizeof(name)); } - catch (Xml_node::Nonexistent_attribute) { - PWRN("Missing name in '' configuration"); - return; - } - - char const *prefix = "config: "; - size_t const prefix_len = strlen(prefix); - - char help[Parameter::Short_help::size() + prefix_len]; - strncpy(help, prefix, ~0); - try { node.attribute("help").value(help + prefix_len, - sizeof(help) - prefix_len); } - catch (Xml_node::Nonexistent_attribute) { - PWRN("Missing help in '' configuration"); - return; - } - - Argument arg(name, help); - fn(arg); - }; - - /* scan subsystem config registry for possible subsystem arguments */ - _subsystem_configs.for_each_config(process_subsystem_config_fn); - } - - void execute(Command_line &cmd, Terminal::Session &terminal) - { - /* check if the GDB-related ROM modules are available */ - try { - Genode::Rom_connection gdb_command_config("gdb_command_config"); - Genode::Rom_connection terminal_crosslink("terminal_crosslink"); - Genode::Rom_connection noux("noux"); - Genode::Rom_connection gdb_monitor("gdb_monitor"); - } catch (Genode::Rom_connection::Rom_connection_failed) { - tprintf(terminal, "Error: The 'gdb' command needs the following ROM " - "modules (of which some are currently missing): " - "gdb_command_config, terminal_crosslink, noux, ", - "gdb_monitor\n"); - return; - } - - char name[128]; - name[0] = 0; - if (cmd.argument(0, name, sizeof(name)) == false) { - tprintf(terminal, "Error: no configuration name specified\n"); - return; - } - - char buf[128]; - if (cmd.argument(1, buf, sizeof(buf))) { - tprintf(terminal, "Error: unexpected argument \"%s\"\n", buf); - return; - } - - try { - _subsystem_configs.for_config(name, [&] (Genode::Xml_node node) - { - _execute_subsystem(name, cmd, terminal, node); - }); - - } catch (Subsystem_config_registry::Nonexistent_subsystem_config) { - tprintf(terminal, "Error: no configuration for \"%s\"\n", name); - } - } -}; - -#endif /* _GDB_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/main.cc b/repos/os/src/app/cli_monitor/main.cc index 09f0e7741..77c6b80aa 100644 --- a/repos/os/src/app/cli_monitor/main.cc +++ b/repos/os/src/app/cli_monitor/main.cc @@ -31,7 +31,6 @@ #include #include #include -#include using Genode::Xml_node; @@ -127,10 +126,6 @@ int main(int argc, char **argv) static Signal_context yield_broadcast_sig_ctx; static Signal_context resource_avail_sig_ctx; - static Signal_context kill_gdb_sig_ctx; - static Signal_context_capability kill_gdb_sig_cap = - sig_rec.manage(&kill_gdb_sig_ctx); - static Signal_context exited_child_sig_ctx; static Signal_context_capability exited_child_sig_cap = sig_rec.manage(&exited_child_sig_ctx); @@ -143,11 +138,6 @@ int main(int argc, char **argv) commands.insert(new Help_command); Kill_command kill_command(children); commands.insert(&kill_command); - commands.insert(new Gdb_command(ram, cap, children, - subsystem_config_registry(), - yield_response_sig_cap, - kill_gdb_sig_cap, - exited_child_sig_cap)); commands.insert(new Start_command(ram, cap, children, subsystem_config_registry(), yield_response_sig_cap, @@ -203,21 +193,6 @@ int main(int argc, char **argv) child->yield(amount, true); } - if (signal.context() == &kill_gdb_sig_ctx) { - for (Child *child = children.first(); child; child = child->next()) { - Gdb_command_child *gdb_command_child = - dynamic_cast(child); - if (gdb_command_child && gdb_command_child->kill_requested()) { - tprintf(terminal, "Destroying GDB subsystem after an error occured.\n"); - children.remove(gdb_command_child); - Genode::destroy(Genode::env()->heap(), gdb_command_child); - line_editor.reset(); - break; - } - } - continue; - } - if (signal.context() == &exited_child_sig_ctx) { Child *next = nullptr; for (Child *child = children.first(); child; child = next) {