diff --git a/os/src/app/cli_monitor/arm/gdb_prefix.h b/os/src/app/cli_monitor/arm/gdb_prefix.h
new file mode 100644
index 0000000000..796bdb4514
--- /dev/null
+++ b/os/src/app/cli_monitor/arm/gdb_prefix.h
@@ -0,0 +1,19 @@
+/*
+ * \brief Prefix of the GDB binary
+ * \author Christian Prochaska
+ * \date 2013-10-23
+ */
+
+/*
+ * 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_PREFIX_H_
+#define _GDB_PREFIX_H_
+
+static const char *gdb_prefix = "genode-arm-";
+
+#endif /* _GDB_PREFIX_H_ */
diff --git a/os/src/app/cli_monitor/gdb_command.h b/os/src/app/cli_monitor/gdb_command.h
new file mode 100644
index 0000000000..699a6320f9
--- /dev/null
+++ b/os/src/app/cli_monitor/gdb_command.h
@@ -0,0 +1,546 @@
+/*
+ * \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
+
+/* local includes */
+#include
+#include
+#include
+#include
+#include
+
+class Gdb_command_child : public Child
+{
+ private:
+
+ Genode::Signal_context_capability _kill_gdb_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,
+ Terminal::Session &terminal)
+ : Child(ram, label, binary, cap_session, ram_quota, ram_limit,
+ yield_response_sig_cap),
+ _kill_gdb_sig_cap(kill_gdb_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;
+ }
+
+};
+
+
+struct Gdb_command : Command
+{
+ 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;
+ Xml_node _config;
+ Process_arg_registry &_process_args;
+ List _arguments;
+ Signal_context_capability _yield_response_sigh_cap;
+ Signal_context_capability _kill_gdb_sig_cap;
+
+ Gdb_command(Ram &ram, Genode::Cap_session &cap, Child_registry &children,
+ Xml_node config, Process_arg_registry &process_args,
+ Signal_context_capability yield_response_sigh_cap,
+ Signal_context_capability kill_gdb_sig_cap)
+ :
+ Command("gdb", "create new subsystem with GDB"),
+ _ram(ram), _children(children), _cap(cap), _config(config),
+ _process_args(process_args),
+ _yield_response_sigh_cap(yield_response_sigh_cap),
+ _kill_gdb_sig_cap(kill_gdb_sig_cap)
+ {
+ /* scan config for possible subsystem arguments */
+ try {
+ Xml_node node = _config.sub_node("subsystem");
+ for (;; node = node.next("subsystem")) {
+
+ char name[Parameter::NAME_MAX_LEN];
+ try { node.attribute("name").value(name, sizeof(name)); }
+ catch (Xml_node::Nonexistent_attribute) {
+ PWRN("Missing name in '' configuration");
+ continue;
+ }
+
+ char const *prefix = "config: ";
+ size_t const prefix_len = strlen(prefix);
+
+ char help[Parameter::SHORT_HELP_MAX_LEN + 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");
+ continue;
+ }
+
+ _arguments.insert(new Argument(name, help));
+ }
+ } catch (Xml_node::Nonexistent_sub_node) { /* end of list */ }
+
+ 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"));
+ }
+
+ /**
+ * Lookup subsystem in config
+ */
+ Xml_node _subsystem_node(char const *name)
+ {
+ Xml_node node = _config.sub_node("subsystem");
+ for (;; node = node.next("subsystem")) {
+ if (node.attribute("name").has_value(name))
+ return node;
+ }
+ }
+
+ /**
+ * 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(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;
+ }
+
+ Genode::Number_of_bytes ram = 0;
+ Genode::Number_of_bytes ram_limit = 0;
+ Genode::Number_of_bytes gdb_ram_preserve = 10*1024*1024;
+
+ 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;
+ }
+
+ /* check if a configuration for the subsystem exists */
+ try { _subsystem_node(name); }
+ catch (Xml_node::Nonexistent_sub_node) {
+ tprintf(terminal, "Error: no configuration for \"%s\"\n", name);
+ return;
+ }
+
+ /* read default RAM quota from config */
+ try {
+ Xml_node rsc = _subsystem_node(name).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(name).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(name).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,
+ 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;
+ }
+
+ _process_args.list.insert(&child->argument);
+ _children.insert(child);
+ child->start();
+ }
+
+ List &arguments() { return _arguments; }
+};
+
+#endif /* _GDB_COMMAND_H_ */
diff --git a/os/src/app/cli_monitor/gdb_command_config b/os/src/app/cli_monitor/gdb_command_config
new file mode 100644
index 0000000000..5c912d5567
--- /dev/null
+++ b/os/src/app/cli_monitor/gdb_command_config
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/os/src/app/cli_monitor/main.cc b/os/src/app/cli_monitor/main.cc
index 3e9843ea94..11012a2ea3 100644
--- a/os/src/app/cli_monitor/main.cc
+++ b/os/src/app/cli_monitor/main.cc
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
using Genode::Xml_node;
@@ -101,6 +102,10 @@ 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 Ram ram(ram_preservation_from_config(),
sig_rec.manage(&yield_broadcast_sig_ctx),
sig_rec.manage(&resource_avail_sig_ctx));
@@ -109,6 +114,11 @@ int main(int argc, char **argv)
commands.insert(new Help_command);
Kill_command kill_command(children, process_args);
commands.insert(&kill_command);
+ commands.insert(new Gdb_command(ram, cap, children,
+ Genode::config()->xml_node(),
+ process_args,
+ yield_response_sig_cap,
+ kill_gdb_sig_cap));
commands.insert(new Start_command(ram, cap, children,
Genode::config()->xml_node(),
process_args,
@@ -164,6 +174,22 @@ 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");
+ process_args.list.remove(&gdb_command_child->argument);
+ children.remove(gdb_command_child);
+ Genode::destroy(Genode::env()->heap(), gdb_command_child);
+ line_editor.reset();
+ break;
+ }
+ }
+ continue;
+ }
+
if (!line_editor.is_complete())
continue;
diff --git a/os/src/app/cli_monitor/target.mk b/os/src/app/cli_monitor/target.mk
index e6fa140576..1f3fe53048 100644
--- a/os/src/app/cli_monitor/target.mk
+++ b/os/src/app/cli_monitor/target.mk
@@ -2,3 +2,11 @@ TARGET = cli_monitor
SRC_CC = main.cc
LIBS = base cli_monitor config
INC_DIR += $(PRG_DIR)
+
+ifeq ($(findstring arm, $(SPECS)), arm)
+INC_DIR += $(PRG_DIR)/arm
+else
+ifeq ($(findstring x86, $(SPECS)), x86)
+INC_DIR += $(PRG_DIR)/x86
+endif
+endif
diff --git a/os/src/app/cli_monitor/x86/gdb_prefix.h b/os/src/app/cli_monitor/x86/gdb_prefix.h
new file mode 100644
index 0000000000..decbd52d7a
--- /dev/null
+++ b/os/src/app/cli_monitor/x86/gdb_prefix.h
@@ -0,0 +1,19 @@
+/*
+ * \brief Prefix of the GDB binary
+ * \author Christian Prochaska
+ * \date 2013-10-23
+ */
+
+/*
+ * 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_PREFIX_H_
+#define _GDB_PREFIX_H_
+
+static const char *gdb_prefix = "genode-x86-";
+
+#endif /* _GDB_PREFIX_H_ */
diff --git a/ports/run/noux_gdb.inc b/ports/run/noux_gdb.inc
new file mode 100644
index 0000000000..211c55c4f6
--- /dev/null
+++ b/ports/run/noux_gdb.inc
@@ -0,0 +1,69 @@
+#
+# Utility functions for run scripts using Noux GDB
+#
+
+
+#
+# Return the name of the Noux GDB package for the configured platform
+#
+proc noux_gdb_pkg_name { } {
+ if {[have_spec arm]} {
+ return "gdb_arm"
+ } elseif {[have_spec x86]} {
+ return "gdb_x86"
+ }
+}
+
+
+#
+# Create a tar archive for GDB (stripped)
+#
+proc create_gdb_tar { } {
+ exec sh -c "find bin/[noux_gdb_pkg_name]/ -type f | (xargs [cross_dev_prefix]strip || true) 2>/dev/null"
+ exec tar cfhv bin/gdb.tar -C bin/[noux_gdb_pkg_name] .
+}
+
+
+#
+# Create a tar archive for a Noux application and its shared libraries (unstripped)
+#
+proc create_binary_tar { application_name application_binaries } {
+ foreach application_binary ${application_binaries} {
+ exec tar ufv bin/${application_name}.tar -h -C bin ${application_binary}
+ }
+}
+
+
+#
+# Create a tar archive for the source code of a Noux application and its shared
+# libraries.
+#
+# Currently, directories need to have their own tar records
+#
+proc create_source_tar { application_name application_binaries } {
+ exec mkdir -p bin/${application_name}-src
+ foreach application_binary $application_binaries {
+ set source_files [ exec [cross_dev_prefix]objdump -dl bin/${application_binary} | grep "^/.*:.*" | sed -e "s/:.*//" | uniq ]
+ foreach source_file ${source_files} {
+ # resolve '..' to avoid problems with 'tar' with parts like '/a/b/../'
+ # where '/a' exists, but '/a/b' does not
+ set source_file [file normalize ${source_file}]
+ if [file exists ${source_file}] {
+ set dirname [ exec dirname ${source_file}]
+ exec mkdir -p bin/${application_name}-src${dirname}
+ exec ln -sf ${source_file} bin/${application_name}-src${source_file}
+ }
+ }
+ }
+ exec tar chf bin/${application_name}-src.tar -C bin/${application_name}-src .
+}
+
+
+#
+# Create tar archives for binaries and source code of a Noux application
+#
+proc create_binary_and_source_tars { application_name application_binaries } {
+ create_binary_tar ${application_name} ${application_binaries}
+ create_source_tar ${application_name} ${application_binaries}
+}
+
diff --git a/ports/run/noux_gdb.run b/ports/run/noux_gdb.run
index 329d5083a2..f4c6d1df08 100644
--- a/ports/run/noux_gdb.run
+++ b/ports/run/noux_gdb.run
@@ -3,13 +3,13 @@ if {![have_spec foc] || ![have_spec 32bit]} {
exit 0
}
+source ${genode_dir}/ports/run/noux_gdb.inc
+
if {[have_spec arm]} {
- set gdb "gdb_arm"
set tool_prefix "genode-arm-"
}
if {[have_spec x86]} {
- set gdb "gdb_x86"
set tool_prefix "genode-x86-"
}
@@ -17,57 +17,34 @@ if {[have_spec x86]} {
# Uncomment the following line when working on the GDB source code. Otherwise,
# the package may get recompiled, yet it does not get reinstalled into 'bin/'.
#
-#exec rm -rf noux-pkg/$gdb/ bin/$gdb/
+#exec rm -rf noux-pkg/[noux_gdb_pkg_name]/ bin/[noux_gdb_pkg_name]/
set build_components {
core init drivers/timer noux lib/libc_noux
drivers/framebuffer drivers/pci drivers/input drivers/usb
server/terminal server/terminal_crosslink
- server/ram_fs app/gdb_monitor
+ app/gdb_monitor
test/gdb_monitor
}
-lappend build_components noux-pkg/$gdb
+lappend build_components noux-pkg/[noux_gdb_pkg_name]
+
+# the application to be debugged with GDB
+lappend build_components test/gdb_monitor
+set gdb_target_binary_name test-gdb_monitor
build $build_components
-# tar archive for GDB
-
-exec sh -c "find bin/$gdb/ -type f | (xargs [cross_dev_prefix]strip || true) 2>/dev/null"
-exec tar cfhv bin/gdb.tar -C bin/$gdb .
-
# names of the binaries needed for the GDB monitor test
-
-set test_binaries {
+set gdb_target_binaries {
test-gdb_monitor
ld.lib.so
libc.lib.so
libc_log.lib.so
}
+lappend gdb_target_binaries ${gdb_target_binary_name}
-# tar archive for the unstripped binaries of the GDB monitor test
-
-foreach test_binary $test_binaries {
- exec tar ufv bin/test-gdb_monitor.tar -h -C bin $test_binary
-}
-
-# tar archive for the source code of the GDB monitor test
-# currently, directories need to have their own tar records
-
-exec mkdir -p bin/test-gdb_monitor-src
-foreach test_binary $test_binaries {
- set source_files [ exec [cross_dev_prefix]objdump -dl bin/$test_binary | grep "^/.*:.*" | sed -e "s/:.*//" | uniq ]
- foreach source_file $source_files {
- # resolve '..' to avoid problems with 'tar' with parts like '/a/b/../'
- # where '/a' exists, but '/a/b' does not
- set source_file [file normalize $source_file]
- if [file exists $source_file] {
- set dirname [ exec dirname $source_file]
- exec mkdir -p bin/test-gdb_monitor-src$dirname
- exec ln -sf $source_file bin/test-gdb_monitor-src$source_file
- }
- }
-}
-exec tar chf bin/test-gdb_monitor-src.tar -C bin/test-gdb_monitor-src .
+create_gdb_tar
+create_binary_and_source_tars ${gdb_target_binary_name} ${gdb_target_binaries}
create_boot_directory
@@ -149,39 +126,13 @@ append config {
-
-
+ }
+append config "
+ "
+append config {
-
-
-
-
-
-
-
- set interactive-mode off
- directory /gdb/src
- target remote /dev/gdb
- symbol-file /gdb/ld.lib.so
- b call_main
- c
- delete 1
- symbol-file /gdb/test-gdb_monitor
- b main
- set solib-search-path /gdb
- sharedlibrary
- c
- delete 2
- set interactive-mode auto
-
-
-
-
-
-
-
@@ -197,17 +148,34 @@ append config {
-
-
-
-
+ }
+append config "
+
+ "
+append config {
}
append config "
- "
+
+
+ "
append config {
-
-
+
+
+
+
+
+
+ }
+append config "
+ "
+append config {
+
+
+
+
+
+
@@ -226,7 +194,7 @@ set boot_modules {
core init timer ld.lib.so noux terminal terminal_crosslink
libc.lib.so libm.lib.so libc_noux.lib.so ncurses.lib.so expat.lib.so
libc_lock_pipe.lib.so libc_log.lib.so libc_terminal.lib.so
- ram_fs gdb_monitor test-gdb_monitor
+ gdb_monitor test-gdb_monitor
gdb.tar test-gdb_monitor.tar test-gdb_monitor-src.tar
}
diff --git a/ports/run/noux_gdb_dynamic.run b/ports/run/noux_gdb_dynamic.run
new file mode 100644
index 0000000000..5f10020e95
--- /dev/null
+++ b/ports/run/noux_gdb_dynamic.run
@@ -0,0 +1,165 @@
+if {![have_spec foc] || ![have_spec 32bit]} {
+ puts "\nThe Noux GDB scenario is supported on 32-bit Fiasco.OC only\n"
+ exit 0
+}
+
+source ${genode_dir}/ports/run/noux_gdb.inc
+
+#
+# Uncomment the following line when working on the GDB source code. Otherwise,
+# the package may get recompiled, yet it does not get reinstalled into 'bin/'.
+#
+#exec rm -rf noux-pkg/[noux_gdb_pkg_name]/ bin/[noux_gdb_pkg_name]/
+
+set build_components {
+ core init drivers/timer noux lib/libc_noux
+ drivers/uart
+ server/terminal_mux server/terminal_crosslink
+ server/terminal_log
+ app/cli_monitor
+ app/gdb_monitor
+}
+lappend build_components noux-pkg/[noux_gdb_pkg_name]
+
+lappend build_components test/gdb_monitor
+set gdb_target_binary_name test-gdb_monitor
+
+build $build_components
+
+# names of the binaries needed for the GDB monitor test
+set gdb_target_binaries {
+ ld.lib.so
+ libc.lib.so
+ libc_log.lib.so
+}
+lappend gdb_target_binaries ${gdb_target_binary_name}
+
+create_gdb_tar
+create_binary_and_source_tars "gdb_target" ${gdb_target_binaries}
+
+create_boot_directory
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+# use kernel debugger as UART on Fiasco.OC
+append_if [have_spec foc] config {
+ }
+
+append config {
+
+
+
+
+
+ }
+
+# on Fiasco.OC the kdb_uart_drv is always UART 0
+append_if [have_spec foc] config {
+ }
+
+# on all other kernels, direct terminal_mux to UART 1 (Qemu stdio, see below)
+append_if [expr ![have_spec foc]] config {
+ }
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+append config "
+ "
+append config {
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+
+#
+# Boot modules
+#
+
+exec cp ${genode_dir}/os/src/app/cli_monitor/gdb_command_config bin
+
+# generic modules
+set boot_modules {
+ core init timer ld.lib.so noux terminal_mux terminal_crosslink
+ libc.lib.so libm.lib.so libc_noux.lib.so ncurses.lib.so expat.lib.so
+ libc_lock_pipe.lib.so libc_log.lib.so libc_terminal.lib.so
+ cli_monitor gdb_monitor terminal_log gdb.tar
+ gdb_command_config
+ gdb_target.tar
+ gdb_target-src.tar
+}
+lappend boot_modules ${gdb_target_binary_name}
+
+# platform-specific modules
+lappend_if [expr ![have_spec foc]] boot_modules uart_drv
+lappend_if [have_spec foc] boot_modules kdb_uart_drv
+
+set fiasco_serial_esc_arg ""
+
+build_boot_image $boot_modules
+
+append qemu_args " -nographic "
+
+run_genode_until forever
+
+exec rm bin/gdb.tar