diff --git a/repos/ports/doc/gdb.txt b/repos/ports/doc/gdb.txt
index b8b5d908be..e2f06911ae 100644
--- a/repos/ports/doc/gdb.txt
+++ b/repos/ports/doc/gdb.txt
@@ -256,7 +256,7 @@ via 'make run/gdb_monitor_interactive'. It will execute the scenario on Qemu and
use the UART to communicate with GDB. Qemu is instructed to redirect the second
serial interface to a local socket (using the port 5555):
! -serial chardev:uart
-! -chardev socket,id=uart,port=5555,host=localhost,server,nowait
+! -chardev socket,id=uart,port=5555,host=localhost,server,nowait,ipv4
The used TCP port is then specified to the GDB as remote target:
! target remote localhost:5555
diff --git a/repos/ports/lib/mk/gdbserver_libc_support.mk b/repos/ports/lib/mk/gdbserver_libc_support.mk
index e52d76297f..b716c6fa02 100644
--- a/repos/ports/lib/mk/gdbserver_libc_support.mk
+++ b/repos/ports/lib/mk/gdbserver_libc_support.mk
@@ -1,7 +1 @@
INC_DIR += $(REP_DIR)/src/lib/gdbserver_libc_support
-
-SRC_C += gdbserver_libc_support.c
-
-LIBS += libc
-
-vpath %.c $(REP_DIR)/src/lib/gdbserver_libc_support
diff --git a/repos/ports/lib/mk/spec/fiasco_x86/gdbserver_platform.mk b/repos/ports/lib/mk/spec/fiasco_x86/gdbserver_platform.mk
deleted file mode 100644
index a389462f51..0000000000
--- a/repos/ports/lib/mk/spec/fiasco_x86/gdbserver_platform.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-SRC_CC = spec/fiasco_x86/low.cc
-
-include $(REP_DIR)/lib/mk/spec/x86_32/gdbserver_platform.inc
diff --git a/repos/ports/lib/mk/spec/foc_arm/gdbserver_platform.mk b/repos/ports/lib/mk/spec/foc_arm/gdbserver_platform.mk
index 87a74cea87..5ed1b416f2 100644
--- a/repos/ports/lib/mk/spec/foc_arm/gdbserver_platform.mk
+++ b/repos/ports/lib/mk/spec/foc_arm/gdbserver_platform.mk
@@ -1,4 +1,6 @@
-SRC_CC = spec/foc_arm/low.cc
+SRC_CC = spec/foc_arm/low.cc \
+ spec/foc/native_cpu.cc
+
SRC_C = reg-arm.c \
linux-arm-low.c
diff --git a/repos/ports/lib/mk/spec/foc_x86_32/gdbserver_platform.mk b/repos/ports/lib/mk/spec/foc_x86_32/gdbserver_platform.mk
index 7d18946b4e..7d91ae7430 100644
--- a/repos/ports/lib/mk/spec/foc_x86_32/gdbserver_platform.mk
+++ b/repos/ports/lib/mk/spec/foc_x86_32/gdbserver_platform.mk
@@ -1,3 +1,4 @@
-SRC_CC = spec/foc_x86_32/low.cc
+SRC_CC = spec/foc_x86_32/low.cc \
+ spec/foc/native_cpu.cc
include $(REP_DIR)/lib/mk/spec/x86_32/gdbserver_platform.inc
diff --git a/repos/ports/lib/mk/spec/linux_x86_32/gdbserver_platform.mk b/repos/ports/lib/mk/spec/linux_x86_32/gdbserver_platform.mk
deleted file mode 100644
index ae562c4c41..0000000000
--- a/repos/ports/lib/mk/spec/linux_x86_32/gdbserver_platform.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-SRC_CC = spec/linux_x86_32/low.cc
-
-include $(REP_DIR)/lib/mk/spec/x86_32/gdbserver_platform.inc
diff --git a/repos/ports/lib/mk/spec/nova_x86_32/gdbserver_platform.mk b/repos/ports/lib/mk/spec/nova_x86_32/gdbserver_platform.mk
index bc3fade94a..e173570aa7 100644
--- a/repos/ports/lib/mk/spec/nova_x86_32/gdbserver_platform.mk
+++ b/repos/ports/lib/mk/spec/nova_x86_32/gdbserver_platform.mk
@@ -1,3 +1,4 @@
-SRC_CC = spec/nova_x86_32/low.cc
+SRC_CC = spec/nova_x86_32/low.cc \
+ spec/nova/native_cpu.cc
include $(REP_DIR)/lib/mk/spec/x86_32/gdbserver_platform.inc
diff --git a/repos/ports/lib/mk/spec/okl4_x86/gdbserver_platform.mk b/repos/ports/lib/mk/spec/okl4_x86/gdbserver_platform.mk
deleted file mode 100644
index 129224ed9a..0000000000
--- a/repos/ports/lib/mk/spec/okl4_x86/gdbserver_platform.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-SRC_CC = spec/okl4_x86/low.cc
-
-include $(REP_DIR)/lib/mk/spec/x86_32/gdbserver_platform.inc
diff --git a/repos/ports/lib/mk/spec/pistachio_x86/gdbserver_platform.mk b/repos/ports/lib/mk/spec/pistachio_x86/gdbserver_platform.mk
deleted file mode 100644
index 27f9a04314..0000000000
--- a/repos/ports/lib/mk/spec/pistachio_x86/gdbserver_platform.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-SRC_CC = spec/pistachio_x86/low.cc
-
-include $(REP_DIR)/lib/mk/spec/x86_32/gdbserver_platform.inc
diff --git a/repos/ports/ports/gdb.hash b/repos/ports/ports/gdb.hash
index 8798b2eb20..0b9c4d66a5 100644
--- a/repos/ports/ports/gdb.hash
+++ b/repos/ports/ports/gdb.hash
@@ -1 +1 @@
-ca63e9871478fe3c800d7be3a26a5c4093d38f69
+408b65147b4253d1ffa3d9ebd7b197df2a666261
diff --git a/repos/ports/ports/gdb.port b/repos/ports/ports/gdb.port
index bfcbf6afab..95a84e825c 100644
--- a/repos/ports/ports/gdb.port
+++ b/repos/ports/ports/gdb.port
@@ -11,6 +11,7 @@ DIR(gdb) := src/noux-pkg/gdb
GENODE_DIR := $(REP_DIR)/../..
PATCHES_DIR := $(GENODE_DIR)/tool/patches/gdb-$(VERSION)
PATCHES := $(addprefix $(PATCHES_DIR)/,$(shell cat $(PATCHES_DIR)/series)) \
+ $(REP_DIR)/src/app/gdb_monitor/siginfo.patch \
$(REP_DIR)/src/app/gdb_monitor/gdbserver_genode.patch \
$(REP_DIR)/src/noux-pkg/gdb/build.patch
PATCH_OPT := -p1 -d ${DIR(gdb)}
diff --git a/repos/ports/run/debug_nitpicker.run b/repos/ports/run/debug_nitpicker.run
index 1e16685b38..65535c152f 100644
--- a/repos/ports/run/debug_nitpicker.run
+++ b/repos/ports/run/debug_nitpicker.run
@@ -143,14 +143,14 @@ append qemu_args " -serial mon:stdio "
# connect comport 1 with TCP port $local_port
append qemu_args " -serial chardev:uart "
-append qemu_args " -chardev socket,id=uart,port=$local_port,host=localhost,server,nowait "
+append qemu_args " -chardev socket,id=uart,port=$local_port,host=localhost,server,nowait,ipv4 "
-run_genode_until {.*Remote debugging using /dev/terminal.*} 30
+run_genode_until {.*\[init -> gdb_monitor\].*} 30
puts "GDB monitor is up, starting GDB in a new terminal"
exec [terminal] -e "[gdb] bin/nitpicker -ex \"target remote localhost:$local_port\"" &
-interact
+interact -i [output_spawn_id]
# vi: set ft=tcl :
diff --git a/repos/ports/run/gdb_monitor.inc b/repos/ports/run/gdb_monitor.inc
index 5a59e9fd29..c02d8f1e23 100644
--- a/repos/ports/run/gdb_monitor.inc
+++ b/repos/ports/run/gdb_monitor.inc
@@ -19,20 +19,17 @@ proc gdb_main_breakpoint_cmds { target_binary_name } {
# don't ask for y/n when loading a new symbol file
append gdb_cmds {-ex "set interactive-mode off" }
- # load the symbols of ld.lib.so
- append gdb_cmds {-ex "symbol-file bin/ld.lib.so" }
-
- # set a breakpoint in the 'Linker::Binary::call_entry_point' function
- append gdb_cmds {-ex "b Linker::Binary::call_entry_point" }
+ # set a breakpoint in the 'binary_ready_hook_for_gdb' function
+ append gdb_cmds {-ex "b binary_ready_hook_for_gdb" }
# continue execution until the breakpoint triggers
append gdb_cmds {-ex "c" }
- # delete the 'call_program_main()' breakpoint
+ # delete the 'binary_ready_hook_for_gdb' breakpoint
append gdb_cmds {-ex "delete 1" }
# load the symbols of the test application
- append gdb_cmds "-ex \"symbol-file bin/$target_binary_name\" "
+ append gdb_cmds "-ex \"file bin/$target_binary_name\" "
# set a breakpoint in the application's 'main()' function
append gdb_cmds {-ex "b main" }
diff --git a/repos/ports/run/gdb_monitor.run b/repos/ports/run/gdb_monitor.run
index 749065e740..089527eb7b 100644
--- a/repos/ports/run/gdb_monitor.run
+++ b/repos/ports/run/gdb_monitor.run
@@ -6,8 +6,8 @@
#
#
-# Only Genode/Fiasco.OC and Genode/NOVA supports all the tested features
-# at this time
+# Only the 32-bit NOVA and Fiasco.OC base platforms support most of the tested features
+# at this time.
#
if {![have_include "power_on/qemu"] || (![have_spec foc] && ![have_spec nova])} {
@@ -50,11 +50,11 @@ set config {
-
+
-
+
@@ -109,9 +109,9 @@ append qemu_args " -serial mon:stdio "
# connect comport 1 with TCP port $local_port
append qemu_args " -serial chardev:uart "
-append qemu_args " -chardev socket,id=uart,port=$local_port,host=localhost,server,nowait "
+append qemu_args " -chardev socket,id=uart,port=$local_port,host=localhost,server,nowait,ipv4 "
-run_genode_until {.*Remote debugging using /dev/terminal.*} 30
+run_genode_until {.*\[init -> gdb_monitor\].*} 30
set genode_id [output_spawn_id]
puts "GDB monitor is up, starting GDB"
@@ -123,128 +123,164 @@ set gdb_target_binary "test-gdb_monitor"
# sequence of GDB commands to execute at startup
set gdb_cmds ""
append gdb_cmds {-ex "target remote localhost:$local_port" }
-
append gdb_cmds [gdb_main_breakpoint_cmds $gdb_target_binary]
-#
-# Test commands
-#
+# run GDB and redirect stderr to stdio to get the relevant output into the expect buffer
+eval spawn [gdb] bin/ld.lib.so -n $gdb_cmds 2&>1
+set gdb_id [list $spawn_id $genode_id]
-# test: breakpoint in shared library
-append gdb_cmds {-ex "b puts" }
-append gdb_cmds {-ex "c" }
+puts ""
+puts "----- test: breakpoint in 'main()' -----"
+puts ""
-# test: stack trace when not in syscall
-append gdb_cmds {-ex "bt" }
+run_genode_until {\(gdb\)} 60 $gdb_id
-# test: modify variable
-append gdb_cmds {-ex "print test_var" }
-append gdb_cmds {-ex "set var test_var=2" }
-append gdb_cmds {-ex "print test_var" }
-
-# test: 'call' command
-if {![have_spec nova]} {
-append gdb_cmds {-ex "call test_var_func()" }
-}
-
-# test: thread info
-append gdb_cmds {-ex "b Test_thread::entry()" }
-append gdb_cmds {-ex "c" }
-append gdb_cmds {-ex "info threads" }
-
-# test: single stepping
-append gdb_cmds {-ex "step" }
-
-# test: catch segmentation fault
-append gdb_cmds {-ex "c" }
-
-# test: stack trace when in syscall
-append gdb_cmds {-ex "thread 1" }
-append gdb_cmds {-ex "bt" }
-
-# quit
-append gdb_cmds {-ex "q" }
-
-# run GDB and redirect stderr to stdio to get the relevant output into the expect buffer
-eval spawn [gdb] bin/$gdb_target_binary -n -batch $gdb_cmds 2&>1
-set gdb_id $spawn_id
-
-set timeout 120
-expect {
- -i [list $genode_id $gdb_id]
- timeout { puts stderr "Error: Test execution timed out"; exit -2 }
-}
-
-set gdb_output $expect_out(buffer)
-
-#
-# Evaluate the test results
-#
-
-if {![regexp {Breakpoint 2, main ()} $gdb_output]} {
- puts stderr "Error: Breakpoint in main() did not trigger"
+if {![regexp {Breakpoint 2, main ()} $output]} {
+ puts stderr "*** Error: Breakpoint in main() did not trigger"
exit -1
}
-if {![regexp {Breakpoint 3, puts (.*)} $gdb_output]} {
- puts "Error: Breakpoint in shared library did not trigger"
+puts "\n"
+puts "----- test: breakpoint in shared library -----"
+puts ""
+
+send "b puts\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+send "c\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+
+if {![regexp {Breakpoint 3, puts ()} $output]} {
+ puts "*** Error: Breakpoint in shared library did not trigger"
exit -1
}
-if {![regexp {#0 puts} $gdb_output] ||
- ![regexp {in func2()} $gdb_output] ||
- ![regexp {in func1()} $gdb_output] ||
- ![regexp {in main ()} $gdb_output]} {
+puts "\n"
+puts "----- test: stack trace when not in syscall -----"
+puts ""
- puts stderr "Error: Stack trace when not in syscall is not as expected"
+send "bt\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+
+if {![regexp {#0 puts} $output] ||
+ ![regexp {in func2()} $output] ||
+ ![regexp {in func1()} $output] ||
+ ![regexp {in main ()} $output]} {
+
+ puts stderr "*** Error: Stack trace when not in syscall is not as expected"
exit -1
}
-if {![regexp {\$1 = 1} $gdb_output]} {
- puts stderr "Error: first 'print test_var' command didn't result in the expected output"
+puts "\n"
+puts "----- test: modification of a variable value -----"
+puts ""
+
+send "print test_var\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+
+if {![regexp {\$1 = 1} $output]} {
+ puts stderr "*** Error: first 'print test_var' command didn't result in the expected output"
exit -1
}
-if {![regexp {\$2 = 2} $gdb_output]} {
- puts stderr "Error: second 'print test_var' command didn't result in the expected output"
+send "set var test_var=2\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+
+send "print test_var\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+
+if {![regexp {\$2 = 2} $output]} {
+ puts stderr "*** Error: second 'print test_var' command didn't result in the expected output"
exit -1
}
-if {![have_spec nova]} {
-if {![regexp {\$3 = 3} $gdb_output]} {
- puts stderr "Error: 'call' command didn't result in the expected output"
- exit -1
-}
-}
+puts "\n"
+puts "----- test: 'call' command -----"
+puts ""
-if {![regexp {Breakpoint 4, Test_thread::entry()} $gdb_output]} {
- puts stderr "Error: Breakpoint in test thread did not trigger"
+send "call test_var_func()\n"
+run_genode_until {\(gdb\)} 60 $gdb_id
+
+if {![regexp {\$3 = 3} $output]} {
+ puts stderr "*** Error: 'call' command didn't result in the expected output"
exit -1
}
-if {![regexp {\* 2 Thread 2 Test_thread::entry} $gdb_output] ||
- ![regexp { 1 Thread 1} $gdb_output]} {
- puts stderr "Error: Thread info is not as expected"
+puts "\n"
+puts "----- test: thread info -----"
+puts ""
+
+send "b Test_thread::entry()\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+
+send "c\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+
+if {![regexp {Breakpoint 4, Test_thread::entry()} $output]} {
+ puts stderr "*** Error: Breakpoint in test thread did not trigger"
exit -1
}
-if {![regexp {38 static Timer::Connection timer} $gdb_output]} {
- puts stderr "Error: Single stepping didn't result in the expected output"
+send "info threads\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+
+if {![regexp { 4 Thread 3} $output] ||
+ ![regexp {\* 3 Thread 4 Test_thread::entry} $output] ||
+ ![regexp { 2 Thread 2} $output] ||
+ ![regexp { 1 Thread 1} $output]} {
+ puts stderr "*** Error: Thread info is not as expected"
exit -1
}
-if {![regexp {Program received signal SIGSEGV, Segmentation fault.} $gdb_output]} {
- puts stderr "Error: Segmentation fault exception was not catched"
+puts "\n"
+puts "----- test: step into function -----"
+puts ""
+
+send "step\n"
+run_genode_until {\(gdb\)} 30 $gdb_id
+
+send "thread 2\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+
+if {![regexp {Test_thread::step_func} $output]} {
+ puts stderr "*** Error: Step into function didn't result in the expected output"
exit -1
}
-if {![regexp {Genode::Cancelable_lock::lock\(\)} $gdb_output] ||
- ![regexp {Genode::Thread::join\(\)} $gdb_output] ||
- ![regexp {in main \(\)} $gdb_output]} {
+puts "\n"
+puts "----- test: catching a segmentation fault -----"
+puts ""
- puts stderr "Error: Stack trace when in syscall is not as expected"
+send "c\n"
+run_genode_until {\(gdb\)} 20 $gdb_id
+
+if {![regexp {Program received signal SIGSEGV, Segmentation fault.} $output]} {
+ puts stderr "*** Error: Segmentation fault exception was not caught"
exit -1
-
}
+# does not work well on ARM yet
+if {![have_spec arm]} {
+
+ puts "\n"
+ puts "----- test: stack trace when in syscall -----"
+ puts ""
+
+ send "thread 2\n"
+ run_genode_until {\(gdb\)} 20 $gdb_id
+
+ send "bt\n"
+ run_genode_until {\(gdb\)} 20 $gdb_id
+
+ if {![regexp {Genode::Cancelable_lock::lock\(\)} $output] ||
+ ![regexp {Genode::Thread::join\(\)} $output] ||
+ ![regexp {in main \(\)} $output]} {
+
+ puts stderr "*** Error: Stack trace when in syscall is not as expected"
+ exit -1
+
+ }
+}
+
+puts ""
+
# vi: set ft=tcl :
diff --git a/repos/ports/run/gdb_monitor_interactive.run b/repos/ports/run/gdb_monitor_interactive.run
index 148d1cbc4a..7f7afc354d 100644
--- a/repos/ports/run/gdb_monitor_interactive.run
+++ b/repos/ports/run/gdb_monitor_interactive.run
@@ -39,11 +39,11 @@ set config {
-
+
-
+
@@ -98,7 +98,7 @@ append qemu_args " -serial mon:stdio "
# connect comport 1 with TCP port $local_port
append qemu_args " -serial chardev:uart "
-append qemu_args " -chardev socket,id=uart,port=$local_port,host=localhost,server,nowait "
+append qemu_args " -chardev socket,id=uart,port=$local_port,host=localhost,server,nowait,ipv4 "
run_genode_until {.*Remote debugging using /dev/terminal.*} 30
@@ -119,7 +119,7 @@ append gdb_cmds {-ex "set interactive-mode auto" }
puts "command: [gdb] bin/$gdb_target_binary $gdb_cmds"
-exec [terminal] -e "[gdb] bin/test-gdb_monitor $gdb_cmds" &
+exec [terminal] -e "[gdb] bin/ld.lib.so $gdb_cmds" &
interact -i [output_spawn_id]
diff --git a/repos/ports/run/gdb_monitor_target_config.run b/repos/ports/run/gdb_monitor_target_config.run
index 60fcf40e72..c159f549d2 100644
--- a/repos/ports/run/gdb_monitor_target_config.run
+++ b/repos/ports/run/gdb_monitor_target_config.run
@@ -92,7 +92,7 @@ append qemu_args " -serial mon:stdio "
# connect comport 1 with TCP port $local_port
append qemu_args " -serial chardev:uart "
-append qemu_args " -chardev socket,id=uart,port=$local_port,host=localhost,server,nowait "
+append qemu_args " -chardev socket,id=uart,port=$local_port,host=localhost,server,nowait,ipv4 "
run_genode_until {.*Remote debugging using /dev/terminal.*} 30
diff --git a/repos/ports/run/noux_gdb.run b/repos/ports/run/noux_gdb.run
index c57b8ead10..b6b1ef2ee5 100644
--- a/repos/ports/run/noux_gdb.run
+++ b/repos/ports/run/noux_gdb.run
@@ -1,5 +1,5 @@
-if {![have_spec foc] || ![have_spec 32bit]} {
- puts "\nThe Noux GDB scenario is supported on 32-bit Fiasco.OC only\n"
+if {![have_spec foc] && ![have_spec nova]} {
+ puts "\nThe Noux GDB scenario is supported on NOVA and Fiasco.OC only\n"
exit 0
}
@@ -126,7 +126,7 @@ append config {
-
+
@@ -171,19 +171,18 @@ append config {
}
append config "
- "
+ "
append config {
-
-
+
}
append config "
- "
+ "
append config {
-
+
diff --git a/repos/ports/src/app/gdb_monitor/app_child.h b/repos/ports/src/app/gdb_monitor/app_child.h
index 9bb31bda46..33a145ab36 100644
--- a/repos/ports/src/app/gdb_monitor/app_child.h
+++ b/repos/ports/src/app/gdb_monitor/app_child.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009-2013 Genode Labs GmbH
+ * Copyright (C) 2009-2016 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.
@@ -26,292 +26,333 @@
#include
#include "cpu_root.h"
-#include "gdb_stub_thread.h"
-#include "ram_root.h"
+#include "genode_child_resources.h"
#include "pd_session_component.h"
+#include "ram_root.h"
#include "rom.h"
-namespace Gdb_monitor {
+namespace Gdb_monitor { class App_child; }
- class App_child : public Child_policy, public Init::Child_policy_enforce_labeling
- {
- private:
+class Gdb_monitor::App_child : public Child_policy,
+ public Init::Child_policy_enforce_labeling
+{
+ private:
- enum { STACK_SIZE = 4*1024*sizeof(long) };
+ enum { STACK_SIZE = 4*1024*sizeof(long) };
- const char *_unique_name;
+ const char *_unique_name;
- Rpc_entrypoint _entrypoint;
+ Genode::Dataspace_capability _elf_ds;
+ Genode::Dataspace_capability _ldso_ds;
- Service_registry *_parent_services;
- Service_registry _local_services;
+ Rpc_entrypoint _entrypoint;
- Init::Child_config _child_config;
+ Service_registry *_parent_services;
+ Service_registry _local_services;
- Init::Child_policy_provide_rom_file _binary_policy;
- Init::Child_policy_provide_rom_file _config_policy;
+ Genode::Rpc_entrypoint *_root_ep;
- Gdb_stub_thread _gdb_stub_thread;
- Dataspace_pool _managed_ds_map;
+ Init::Child_config _child_config;
- Cpu_root _cpu_root;
- Cpu_session_client _cpu_session;
+ Init::Child_policy_provide_rom_file _binary_policy;
+ Init::Child_policy_provide_rom_file _config_policy;
- Ram_session_client _ram_session;
+ Genode_child_resources _genode_child_resources;
- Pd_session_component _pd { _unique_name, _entrypoint,
- _managed_ds_map };
+ Signal_dispatcher _unresolved_page_fault_dispatcher;
- Region_map_client _address_space { _pd.address_space() };
+ Dataspace_pool _managed_ds_map;
- Child::Initial_thread _initial_thread;
+ Pd_session_component _pd {_unique_name, _entrypoint, _managed_ds_map};
- Child _child;
+ Cpu_root _cpu_root;
+ Cpu_session_client _cpu_session;
- Genode::Rpc_entrypoint *_root_ep;
+ Ram_session_client _ram_session;
- Rom_service _rom_service;
+ Region_map_client _address_space { _pd.address_space() };
- Cpu_session_capability _get_cpu_session_cap()
- {
- _entrypoint.manage(&_cpu_root);
- char args[64];
- Genode::snprintf(args, sizeof(args), "ram_quota=32K, label=\"%s\"", _unique_name);
- return static_cap_cast(_cpu_root.session(args, Affinity()));
- }
+ Child::Initial_thread _initial_thread;
- /**
- * Proxy for a service provided by the child
- */
- class Child_service_root : public Genode::Rpc_object
- {
- private:
+ Parent_service _parent_pd_service { "" };
+ Parent_service _parent_ram_service { "" };
+ Parent_service _parent_cpu_service { "" };
- /**
- * Root interface of the real service, provided by the child
+ Child *_child;
+
+ Rom_service _rom_service;
+
+
+ Cpu_session_capability _get_cpu_session_cap()
+ {
+ _entrypoint.manage(&_cpu_root);
+ char args[64];
+ Genode::snprintf(args, sizeof(args), "ram_quota=64K, label=\"%s\"", _unique_name);
+ return static_cap_cast(_cpu_root.session(args, Affinity()));
+ }
+
+ /**
+ * Proxy for a service provided by the child
+ */
+ class Child_service_root : public Genode::Rpc_object
+ {
+ private:
+
+ /**
+ * Root interface of the real service, provided by the child
+ */
+ Genode::Root_client _child_root;
+
+ /**
+ * Child's RAM session used for quota transfers
+ */
+ Genode::Ram_session_capability _child_ram;
+
+ struct Child_session;
+ typedef Genode::Object_pool Session_pool;
+
+ /**
+ * Per-session meta data
+ *
+ * For each session, we need to keep track of the quota
+ * attached to it - in order to revert the quota donation
+ * when the session gets closed.
+ */
+ struct Child_session : public Session_pool::Entry
+ {
+ Genode::size_t ram_quota;
+
+ Child_session(Genode::Session_capability cap,
+ Genode::size_t ram_quota)
+ : Session_pool::Entry(cap), ram_quota(ram_quota) { }
+ };
+
+ /**
+ * Data base containing per-session meta data
+ */
+ Session_pool _sessions;
+
+ public:
+
+ /**
+ * Constructor
+ */
+
+ Child_service_root(Genode::Ram_session_capability child_ram,
+ Genode::Root_capability child_root)
+ : _child_root(child_root), _child_ram(child_ram)
+ { }
+
+ /********************
+ ** Root interface **
+ ********************/
+
+ Session_capability session(Session_args const &args,
+ Affinity const &affinity)
+ {
+ using namespace Genode;
+
+ Genode::size_t ram_quota =
+ Arg_string::find_arg(args.string(),
+ "ram_quota").ulong_value(0);
+
+ /* forward session quota to child */
+ env()->ram_session()->transfer_quota(_child_ram, ram_quota);
+
+ Session_capability cap = _child_root.session(args, affinity);
+
+ /*
+ * Keep information about donated quota in '_sessions'
+ * data base.
*/
- Genode::Root_client _child_root;
+ _sessions.insert(new (env()->heap())
+ Child_session(cap, ram_quota));
+ return cap;
+ }
- /**
- * Child's RAM session used for quota transfers
- */
- Genode::Ram_session_capability _child_ram;
+ void upgrade(Session_capability session_cap,
+ Upgrade_args const &args)
+ {
+ using namespace Genode;
- struct Child_session;
- typedef Genode::Object_pool Session_pool;
-
- /**
- * Per-session meta data
- *
- * For each session, we need to keep track of the quota
- * attached to it - in order to revert the quota donation
- * when the session gets closed.
- */
- struct Child_session : public Session_pool::Entry
- {
- Genode::size_t ram_quota;
-
- Child_session(Genode::Session_capability cap,
- Genode::size_t ram_quota)
- : Session_pool::Entry(cap), ram_quota(ram_quota) { }
- };
-
- /**
- * Data base containing per-session meta data
- */
- Session_pool _sessions;
-
- public:
-
- /**
- * Constructor
- */
- Child_service_root(Genode::Ram_session_capability child_ram,
- Genode::Root_capability child_root)
- : _child_root(child_root), _child_ram(child_ram)
- { }
-
- /********************
- ** Root interface **
- ********************/
-
- Session_capability session(Session_args const &args,
- Affinity const &affinity)
- {
- using namespace Genode;
+ auto lambda = [&] (Child_session *session) {
+ if (!session) {
+ PERR("attempt to upgrade unknown session");
+ return;
+ }
Genode::size_t ram_quota =
Arg_string::find_arg(args.string(),
- "ram_quota").ulong_value(0);
+ "ram_quota").ulong_value(0);
/* forward session quota to child */
env()->ram_session()->transfer_quota(_child_ram, ram_quota);
- Session_capability cap = _child_root.session(args, affinity);
+ session->ram_quota += ram_quota;
- /*
- * Keep information about donated quota in '_sessions'
- * data base.
- */
- _sessions.insert(new (env()->heap())
- Child_session(cap, ram_quota));
- return cap;
- }
+ /* inform child about quota upgrade */
+ _child_root.upgrade(session_cap, args);
+ };
- void upgrade(Session_capability session_cap,
- Upgrade_args const &args)
- {
- using namespace Genode;
-
- auto lambda = [&] (Child_session *session) {
- if (!session) {
- PERR("attempt to upgrade unknown session");
- return;
- }
-
- Genode::size_t ram_quota =
- Arg_string::find_arg(args.string(),
- "ram_quota").ulong_value(0);
-
- /* forward session quota to child */
- env()->ram_session()->transfer_quota(_child_ram, ram_quota);
-
- session->ram_quota += ram_quota;
-
- /* inform child about quota upgrade */
- _child_root.upgrade(session_cap, args);
- };
-
- _sessions.apply(session_cap, lambda);
- }
-
- void close(Session_capability session_cap)
- {
- using namespace Genode;
-
- Child_session *session;
-
- auto lambda = [&] (Child_session *s) {
- session = s;
-
- if (!session) {
- PERR("attempt to close unknown session");
- return;
- }
- _sessions.remove(session);
- };
- _sessions.apply(session_cap, lambda);
-
- Genode::size_t ram_quota = session->ram_quota;
- destroy(env()->heap(), session);
-
- _child_root.close(session_cap);
-
- /*
- * The child is expected to free enough quota to revert
- * the quota donation.
- */
-
- Ram_session_client child_ram(_child_ram);
- child_ram.transfer_quota(env()->ram_session_cap(), ram_quota);
- }
- };
-
- public:
-
- /**
- * Constructor
- *
- * \param root_ep entrypoint serving the root interfaces of the
- * services provided by the child and announced
- * towards the parent of GDB monitor
- */
- App_child(const char *unique_name,
- Genode::Dataspace_capability elf_ds,
- Genode::Dataspace_capability ldso_ds,
- Genode::Ram_session_capability ram_session,
- Genode::Cap_session *cap_session,
- Service_registry *parent_services,
- Genode::Rpc_entrypoint *root_ep,
- Xml_node target_node)
- : Init::Child_policy_enforce_labeling(unique_name),
- _unique_name(unique_name),
- _entrypoint(cap_session, STACK_SIZE, "GDB monitor entrypoint name"),
- _parent_services(parent_services),
- _child_config(ram_session, target_node),
- _binary_policy("binary", elf_ds, &_entrypoint),
- _config_policy("config", _child_config.dataspace(), &_entrypoint),
- _gdb_stub_thread(),
- _cpu_root(&_entrypoint, env()->heap() /* should be _child.heap() */, &_gdb_stub_thread),
- _cpu_session(_get_cpu_session_cap()),
- _ram_session(ram_session),
- _initial_thread(_cpu_session, _pd.cap(), unique_name),
- _child(elf_ds, ldso_ds, _pd.cap(), _pd,
- _ram_session, _ram_session, _cpu_session, _initial_thread,
- *Genode::env()->rm_session(), _address_space, _entrypoint, *this),
- _root_ep(root_ep),
- _rom_service(&_entrypoint, _child.heap())
- {
- _gdb_stub_thread.set_region_map_component(&_pd.region_map());
- _local_services.insert(&_rom_service);
- _gdb_stub_thread.start();
- }
-
- ~App_child()
- {
- }
-
- /****************************
- ** Child-policy interface **
- ****************************/
-
- const char *name() const { return _unique_name; }
-
- void filter_session_args(const char *, char *args, Genode::size_t args_len)
- {
- Init::Child_policy_enforce_labeling::filter_session_args(0, args, args_len);
- }
-
- Service *resolve_session_request(const char *service_name,
- const char *args)
- {
- Service *service = 0;
-
- /* check for binary file request */
- if ((service = _binary_policy.resolve_session_request(service_name, args)))
- return service;
-
- /* check for config file request */
- if ((service = _config_policy.resolve_session_request(service_name, args)))
- return service;
-
- service = _local_services.find(service_name);
- if (service)
- return service;
-
- service = _parent_services->find(service_name);
- if (!service) {
- service = new (env()->heap()) Parent_service(service_name);
- _parent_services->insert(service);
+ _sessions.apply(session_cap, lambda);
}
+ void close(Session_capability session_cap)
+ {
+ using namespace Genode;
+
+ Child_session *session;
+
+ auto lambda = [&] (Child_session *s) {
+ session = s;
+
+ if (!session) {
+ PERR("attempt to close unknown session");
+ return;
+ }
+ _sessions.remove(session);
+ };
+ _sessions.apply(session_cap, lambda);
+
+ Genode::size_t ram_quota = session->ram_quota;
+ destroy(env()->heap(), session);
+
+ _child_root.close(session_cap);
+
+ /*
+ * The child is expected to free enough quota to revert
+ * the quota donation.
+ */
+
+ Ram_session_client child_ram(_child_ram);
+ child_ram.transfer_quota(env()->ram_session_cap(), ram_quota);
+ }
+ };
+
+ void _dispatch_unresolved_page_fault(unsigned)
+ {
+ _genode_child_resources.cpu_session_component()->handle_unresolved_page_fault();
+ }
+
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param root_ep entrypoint serving the root interfaces of the
+ * services provided by the child and announced
+ * towards the parent of GDB monitor
+ */
+ App_child(const char *unique_name,
+ Genode::Dataspace_capability elf_ds,
+ Genode::Dataspace_capability ldso_ds,
+ Genode::Ram_session_capability ram_session,
+ Genode::Cap_session *cap_session,
+ Service_registry *parent_services,
+ Genode::Rpc_entrypoint *root_ep,
+ Signal_receiver *signal_receiver,
+ Xml_node target_node)
+ : Init::Child_policy_enforce_labeling(unique_name),
+ _unique_name(unique_name),
+ _elf_ds(elf_ds),
+ _ldso_ds(ldso_ds),
+ _entrypoint(cap_session, STACK_SIZE, "GDB monitor entrypoint name"),
+ _parent_services(parent_services),
+ _root_ep(root_ep),
+ _child_config(ram_session, target_node),
+ _binary_policy("binary", elf_ds, &_entrypoint),
+ _config_policy("config", _child_config.dataspace(), &_entrypoint),
+ _unresolved_page_fault_dispatcher(*signal_receiver,
+ *this,
+ &App_child::_dispatch_unresolved_page_fault),
+ _cpu_root(&_entrypoint, &_entrypoint, env()->heap(), _pd.core_pd_cap(),
+ signal_receiver, &_genode_child_resources),
+ _cpu_session(_get_cpu_session_cap()),
+ _ram_session(ram_session),
+ _initial_thread(_cpu_session, _pd.cap(), unique_name),
+ _rom_service(&_entrypoint, env()->heap())
+ {
+ _genode_child_resources.region_map_component(&_pd.region_map());
+ _pd.region_map().fault_handler(_unresolved_page_fault_dispatcher);
+ _local_services.insert(&_rom_service);
+ }
+
+ ~App_child()
+ {
+ destroy(env()->heap(), _child);
+ }
+
+ Genode_child_resources *genode_child_resources()
+ {
+ return &_genode_child_resources;
+ }
+
+ void start()
+ {
+ _child = new (env()->heap()) Child(_elf_ds,
+ _ldso_ds,
+ _pd.cap(),
+ _pd,
+ _ram_session,
+ _ram_session,
+ _cpu_session,
+ _initial_thread,
+ *Genode::env()->rm_session(),
+ _address_space,
+ _entrypoint,
+ *this);
+ }
+
+ /****************************
+ ** Child-policy interface **
+ ****************************/
+
+ const char *name() const { return _unique_name; }
+
+ void filter_session_args(const char *, char *args, Genode::size_t args_len)
+ {
+ Init::Child_policy_enforce_labeling::filter_session_args(0, args, args_len);
+ }
+
+ Service *resolve_session_request(const char *service_name,
+ const char *args)
+ {
+ Service *service = 0;
+
+ /* check for binary file request */
+ if ((service = _binary_policy.resolve_session_request(service_name, args)))
return service;
+
+ /* check for config file request */
+ if ((service = _config_policy.resolve_session_request(service_name, args)))
+ return service;
+
+ service = _local_services.find(service_name);
+ if (service)
+ return service;
+
+ service = _parent_services->find(service_name);
+ if (!service) {
+ service = new (env()->heap()) Parent_service(service_name);
+ _parent_services->insert(service);
}
- bool announce_service(const char *name,
- Root_capability root,
- Allocator *alloc,
- Server *server)
- {
- /* create and announce proxy for the child's root interface */
- Child_service_root *r = new (alloc)
- Child_service_root(_ram_session, root);
+ return service;
+ }
- Genode::env()->parent()->announce(name, _root_ep->manage(r));
- return true;
- }
- };
-}
+ bool announce_service(const char *name,
+ Root_capability root,
+ Allocator *alloc,
+ Server *server)
+ {
+ /* create and announce proxy for the child's root interface */
+ Child_service_root *r = new (alloc)
+ Child_service_root(_ram_session, root);
+
+ Genode::env()->parent()->announce(name, _root_ep->manage(r));
+ return true;
+ }
+};
#endif /* _APP_CHILD_H_ */
diff --git a/repos/ports/src/app/gdb_monitor/cpu_root.h b/repos/ports/src/app/gdb_monitor/cpu_root.h
index 2c71e5c33a..e80cfc842a 100644
--- a/repos/ports/src/app/gdb_monitor/cpu_root.h
+++ b/repos/ports/src/app/gdb_monitor/cpu_root.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2006-2013 Genode Labs GmbH
+ * Copyright (C) 2006-2016 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.
@@ -21,43 +21,58 @@
#include
/* GDB monitor includes */
-#include "gdb_stub_thread.h"
+#include "genode_child_resources.h"
-namespace Gdb_monitor {
+namespace Gdb_monitor { class Cpu_root; }
- class Cpu_root : public Root_component
- {
- private:
- Gdb_stub_thread *_gdb_stub_thread;
+class Gdb_monitor::Cpu_root : public Root_component
+{
+ private:
- protected:
+ Rpc_entrypoint *_thread_ep;
+ Allocator *_md_alloc;
+ Pd_session_capability _core_pd;
+ Genode::Signal_receiver *_signal_receiver;
+ Genode_child_resources *_genode_child_resources;
- Cpu_session_component *_create_session(const char *args)
- {
- Cpu_session_component *cpu_session_component =
- new (md_alloc())
- Cpu_session_component(_gdb_stub_thread->exception_signal_receiver(), args);
- _gdb_stub_thread->set_cpu_session_component(cpu_session_component);
- return cpu_session_component;
- }
+ protected:
- public:
+ Cpu_session_component *_create_session(const char *args)
+ {
+ Cpu_session_component *cpu_session_component =
+ new (md_alloc())
+ Cpu_session_component(_thread_ep,
+ _md_alloc,
+ _core_pd,
+ _signal_receiver,
+ args);
+ _genode_child_resources->cpu_session_component(cpu_session_component);
+ return cpu_session_component;
+ }
- /**
- * Constructor
- *
- * \param session_ep entry point for managing cpu session objects
- * \param thread_ep entry point for managing threads
- * \param md_alloc meta data allocator to be used by root component
- */
- Cpu_root(Rpc_entrypoint *session_ep,
- Allocator *md_alloc,
- Gdb_stub_thread *gdb_stub_thread)
- :
- Root_component(session_ep, md_alloc),
- _gdb_stub_thread(gdb_stub_thread)
- { }
- };
-}
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param session_ep entry point for managing cpu session objects
+ * \param thread_ep entry point for managing threads
+ * \param md_alloc meta data allocator to be used by root component
+ */
+ Cpu_root(Rpc_entrypoint *session_ep,
+ Rpc_entrypoint *thread_ep,
+ Allocator *md_alloc,
+ Pd_session_capability core_pd,
+ Genode::Signal_receiver *signal_receiver,
+ Genode_child_resources *genode_child_resources)
+ :
+ Root_component(session_ep, md_alloc),
+ _thread_ep(thread_ep),
+ _md_alloc(md_alloc),
+ _core_pd(core_pd),
+ _signal_receiver(signal_receiver),
+ _genode_child_resources(genode_child_resources)
+ { }
+};
#endif /* _CPU_ROOT_H_ */
diff --git a/repos/ports/src/app/gdb_monitor/cpu_session_component.cc b/repos/ports/src/app/gdb_monitor/cpu_session_component.cc
index 0115c94cfc..c2980c4124 100644
--- a/repos/ports/src/app/gdb_monitor/cpu_session_component.cc
+++ b/repos/ports/src/app/gdb_monitor/cpu_session_component.cc
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -14,31 +14,69 @@
/* Genode includes */
#include
#include
+#include
#include
#include
/* GDB monitor includes */
-#include "config.h"
+#include "cpu_thread_component.h"
-extern void genode_add_thread(unsigned long lwpid);
+/* genode-low.cc */
extern void genode_remove_thread(unsigned long lwpid);
using namespace Genode;
using namespace Gdb_monitor;
-/* FIXME: use an allocator */
-static unsigned long new_lwpid = GENODE_LWP_BASE;
-
-Thread_info *Cpu_session_component::_thread_info(Thread_capability thread_cap)
+Cpu_session &Cpu_session_component::parent_cpu_session()
{
- Thread_info *thread_info = _thread_list.first();
- while (thread_info) {
- if (thread_info->thread_cap().local_name() == thread_cap.local_name()) {
- return thread_info;
- break;
- }
- thread_info = thread_info->next();
+ return _parent_cpu_session;
+}
+
+
+Rpc_entrypoint &Cpu_session_component::thread_ep()
+{
+ return *_thread_ep;
+}
+
+
+Signal_receiver *Cpu_session_component::exception_signal_receiver()
+{
+ return _exception_signal_receiver;
+}
+
+
+Thread_capability Cpu_session_component::thread_cap(unsigned long lwpid)
+{
+ Cpu_thread_component *cpu_thread = _thread_list.first();
+ while (cpu_thread) {
+ if (cpu_thread->lwpid() == lwpid)
+ return cpu_thread->thread_cap();
+ cpu_thread = cpu_thread->next();
+ }
+ return Thread_capability();
+}
+
+
+Cpu_thread_component *Cpu_session_component::lookup_cpu_thread(unsigned long lwpid)
+{
+ Cpu_thread_component *cpu_thread = _thread_list.first();
+ while (cpu_thread) {
+ if (cpu_thread->lwpid() == lwpid)
+ return cpu_thread;
+ cpu_thread = cpu_thread->next();
+ }
+ return nullptr;
+}
+
+
+Cpu_thread_component *Cpu_session_component::lookup_cpu_thread(Thread_capability thread_cap)
+{
+ Cpu_thread_component *cpu_thread = _thread_list.first();
+ while (cpu_thread) {
+ if (cpu_thread->thread_cap().local_name() == thread_cap.local_name())
+ return cpu_thread;
+ cpu_thread = cpu_thread->next();
}
return 0;
}
@@ -46,68 +84,150 @@ Thread_info *Cpu_session_component::_thread_info(Thread_capability thread_cap)
unsigned long Cpu_session_component::lwpid(Thread_capability thread_cap)
{
- return _thread_info(thread_cap)->lwpid();
+ return lookup_cpu_thread(thread_cap)->lwpid();
}
-Thread_capability Cpu_session_component::thread_cap(unsigned long lwpid)
+int Cpu_session_component::signal_pipe_read_fd(Thread_capability thread_cap)
{
- Thread_info *thread_info = _thread_list.first();
- while (thread_info) {
- if (thread_info->lwpid() == lwpid) {
- return thread_info->thread_cap();
+ return lookup_cpu_thread(thread_cap)->signal_pipe_read_fd();
+}
+
+
+int Cpu_session_component::send_signal(Thread_capability thread_cap,
+ int signo)
+{
+ Cpu_thread_component *cpu_thread = lookup_cpu_thread(thread_cap);
+
+ cpu_thread->pause();
+
+ switch (signo) {
+ case SIGSTOP:
+ Signal_transmitter(cpu_thread->sigstop_signal_context_cap()).submit();
+ return 1;
+ case SIGINT:
+ Signal_transmitter(cpu_thread->sigint_signal_context_cap()).submit();
+ return 1;
+ default:
+ PERR("unexpected signal %d", signo);
+ return 0;
+ }
+}
+
+
+/*
+ * This function delivers a SIGSEGV to the first thread with an unresolved
+ * page fault that it finds. Multiple page-faulted threads are currently
+ * not supported.
+ */
+
+void Cpu_session_component::handle_unresolved_page_fault()
+{
+ /*
+ * It can happen that the thread state of the thread which caused the
+ * page fault is not accessible yet. In that case, we'll retry until
+ * it is accessible.
+ */
+
+ while (1) {
+
+ Thread_capability thread_cap = first();
+
+ while (thread_cap.valid()) {
+
+ try {
+
+ Cpu_thread_component *cpu_thread = lookup_cpu_thread(thread_cap);
+
+ Thread_state thread_state = cpu_thread->state();
+
+ if (thread_state.unresolved_page_fault) {
+
+ /*
+ * On base-foc it is necessary to pause the thread before
+ * IP and SP are available in the thread state.
+ */
+ cpu_thread->pause();
+ cpu_thread->deliver_signal(SIGSEGV);
+
+ return;
+ }
+
+ } catch (Cpu_thread::State_access_failed) { }
+
+ thread_cap = next(thread_cap);
}
- thread_info = thread_info->next();
+
}
- return Thread_capability();
}
-Thread_capability
-Cpu_session_component::create_thread(Capability pd,
- Name const &name,
- Affinity::Location location,
- Weight weight,
- addr_t utcb)
+void Cpu_session_component::stop_new_threads(bool stop)
{
- Thread_capability thread_cap =
- _parent_cpu_session.create_thread(pd, name, location, weight, utcb);
-
- if (thread_cap.valid()) {
- Thread_info *thread_info = new (env()->heap()) Thread_info(thread_cap, new_lwpid++);
- _thread_list.append(thread_info);
- }
-
- return thread_cap;
+ _stop_new_threads = stop;
}
-//Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread)
-//{
-// return _parent_cpu_session.utcb(thread);
-//}
-
-
-void Cpu_session_component::kill_thread(Thread_capability thread_cap)
+bool Cpu_session_component::stop_new_threads()
{
- Thread_info *thread_info = _thread_info(thread_cap);
+ return _stop_new_threads;
+}
- if (thread_info) {
- _exception_signal_receiver->dissolve(thread_info);
- genode_remove_thread(thread_info->lwpid());
- _thread_list.remove(thread_info);
- destroy(env()->heap(), thread_info);
+
+Lock &Cpu_session_component::stop_new_threads_lock()
+{
+ return _stop_new_threads_lock;
+}
+
+
+int Cpu_session_component::handle_initial_breakpoint(unsigned long lwpid)
+{
+ Cpu_thread_component *cpu_thread = _thread_list.first();
+ while (cpu_thread) {
+ if (cpu_thread->lwpid() == lwpid)
+ return cpu_thread->handle_initial_breakpoint();
+ cpu_thread = cpu_thread->next();
}
+ return 0;
+}
- _parent_cpu_session.kill_thread(thread_cap);
+
+void Cpu_session_component::pause_all_threads()
+{
+ Lock::Guard stop_new_threads_lock_guard(stop_new_threads_lock());
+
+ stop_new_threads(true);
+
+ for (Cpu_thread_component *cpu_thread = _thread_list.first();
+ cpu_thread;
+ cpu_thread = cpu_thread->next()) {
+
+ cpu_thread->pause();
+ }
+}
+
+
+void Cpu_session_component::resume_all_threads()
+{
+Lock::Guard stop_new_threads_guard(stop_new_threads_lock());
+
+ stop_new_threads(false);
+
+ for (Cpu_thread_component *cpu_thread = _thread_list.first();
+ cpu_thread;
+ cpu_thread = cpu_thread->next()) {
+
+ cpu_thread->single_step(false);
+ cpu_thread->resume();
+ }
}
Thread_capability Cpu_session_component::first()
{
- Thread_info *thread_info = _thread_list.first();
- if (thread_info)
- return thread_info->thread_cap();
+ Cpu_thread_component *cpu_thread = _thread_list.first();
+ if (cpu_thread)
+ return cpu_thread->thread_cap();
else
return Thread_capability();
}
@@ -115,77 +235,50 @@ Thread_capability Cpu_session_component::first()
Thread_capability Cpu_session_component::next(Thread_capability thread_cap)
{
- Thread_info *next_thread_info = _thread_info(thread_cap)->next();
- if (next_thread_info)
- return next_thread_info->thread_cap();
+ Cpu_thread_component *next_cpu_thread = lookup_cpu_thread(thread_cap)->next();
+ if (next_cpu_thread)
+ return next_cpu_thread->thread_cap();
else
return Thread_capability();
}
-//int Cpu_session_component::start(Thread_capability thread_cap,
-// addr_t ip, addr_t sp)
-//{
-// Thread_info *thread_info = _thread_info(thread_cap);
-//
-// if (thread_info)
-// exception_handler(thread_cap, _exception_signal_receiver->manage(thread_info));
-//
-// int result = _parent_cpu_session.start(thread_cap, ip, sp);
-//
-// if (thread_info) {
-// /* pause the first thread */
-// if (thread_info->lwpid() == GENODE_LWP_BASE)
-// pause(thread_cap);
-//
-// genode_add_thread(thread_info->lwpid());
-// }
-//
-// return result;
-//}
-
-
-//void Cpu_session_component::pause(Thread_capability thread_cap)
-//{
-// _parent_cpu_session.pause(thread_cap);
-//}
-
-
-//void Cpu_session_component::resume(Thread_capability thread_cap)
-//{
-// _parent_cpu_session.resume(thread_cap);
-//}
-
-
-//void Cpu_session_component::cancel_blocking(Thread_capability thread_cap)
-//{
-// _parent_cpu_session.cancel_blocking(thread_cap);
-//}
-
-
-//void Cpu_session_component::state(Thread_capability thread_cap,
-// Thread_state const &state)
-//{
-// _parent_cpu_session.state(thread_cap, state);
-//}
-
-
-//Thread_state Cpu_session_component::state(Thread_capability thread_cap)
-//{
-// return _parent_cpu_session.state(thread_cap);
-//}
-
-
-void Cpu_session_component::exception_sigh(Signal_context_capability sigh_cap)
+Thread_capability Cpu_session_component::create_thread(Capability pd,
+ Cpu_session::Name const &name,
+ Affinity::Location affinity,
+ Weight weight,
+ addr_t utcb)
{
- _parent_cpu_session.exception_sigh(sigh_cap);
+ Cpu_thread_component *cpu_thread =
+ new (_md_alloc) Cpu_thread_component(*this, _core_pd, name,
+ affinity, weight, utcb);
+
+ _thread_list.append(cpu_thread);
+
+ return cpu_thread->cap();
}
-//void Cpu_session_component::single_step(Thread_capability thread_cap, bool enable)
-//{
-// _parent_cpu_session.single_step(thread_cap, enable);
-//}
+void Cpu_session_component::kill_thread(Thread_capability thread_cap)
+{
+ Cpu_thread_component *cpu_thread = lookup_cpu_thread(thread_cap);
+
+ if (cpu_thread) {
+ genode_remove_thread(cpu_thread->lwpid());
+ _thread_list.remove(cpu_thread);
+ destroy(_md_alloc, cpu_thread);
+ } else
+ PERR("%s: could not find thread info for the given thread capability",
+ __PRETTY_FUNCTION__);
+
+ _parent_cpu_session.kill_thread(thread_cap);
+}
+
+
+void Cpu_session_component::exception_sigh(Signal_context_capability handler)
+{
+ _parent_cpu_session.exception_sigh(handler);
+}
Affinity::Space Cpu_session_component::affinity_space() const
@@ -194,56 +287,49 @@ Affinity::Space Cpu_session_component::affinity_space() const
}
-//void Cpu_session_component::affinity(Thread_capability thread_cap,
-// Affinity::Location location)
-//{
-// _parent_cpu_session.affinity(thread_cap, location);
-//}
-
-
Dataspace_capability Cpu_session_component::trace_control()
{
return _parent_cpu_session.trace_control();
}
-//unsigned Cpu_session_component::trace_control_index(Thread_capability thread)
-//{
-// return _parent_cpu_session.trace_control_index(thread);
-//}
-
-
-//Dataspace_capability Cpu_session_component::trace_buffer(Thread_capability thread)
-//{
-// return _parent_cpu_session.trace_buffer(thread);
-//}
-
-
-//Dataspace_capability Cpu_session_component::trace_policy(Thread_capability thread)
-//{
-// return _parent_cpu_session.trace_policy(thread);
-//}
-
-
Capability Cpu_session_component::native_cpu()
{
- return _parent_cpu_session.native_cpu();
+ return _native_cpu_cap;
}
-Cpu_session_component::Cpu_session_component(Signal_receiver *exception_signal_receiver, const char *args)
-: _parent_cpu_session(env()->parent()->session(args)),
- _exception_signal_receiver(exception_signal_receiver)
+Cpu_session_component::Cpu_session_component(Rpc_entrypoint *thread_ep,
+ Allocator *md_alloc,
+ Pd_session_capability core_pd,
+ Signal_receiver *exception_signal_receiver,
+ const char *args)
+: _thread_ep(thread_ep),
+ _md_alloc(md_alloc),
+ _core_pd(core_pd),
+ _parent_cpu_session(env()->parent()->session(args)),
+ _exception_signal_receiver(exception_signal_receiver),
+ _native_cpu_cap(_setup_native_cpu())
{
}
Cpu_session_component::~Cpu_session_component()
{
+ for (Cpu_thread_component *cpu_thread = _thread_list.first();
+ cpu_thread; cpu_thread = _thread_list.first()) {
+ _thread_list.remove(cpu_thread);
+ destroy(_md_alloc, cpu_thread);
+ }
+
+ _cleanup_native_cpu();
}
+
int Cpu_session_component::ref_account(Cpu_session_capability) { return -1; }
+
int Cpu_session_component::transfer_quota(Cpu_session_capability, size_t) { return -1; }
+
Cpu_session::Quota Cpu_session_component::quota() { return Quota(); }
diff --git a/repos/ports/src/app/gdb_monitor/cpu_session_component.h b/repos/ports/src/app/gdb_monitor/cpu_session_component.h
index b919749fc4..ce678faf45 100644
--- a/repos/ports/src/app/gdb_monitor/cpu_session_component.h
+++ b/repos/ports/src/app/gdb_monitor/cpu_session_component.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2006-2013 Genode Labs GmbH
+ * Copyright (C) 2006-2016 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.
@@ -15,40 +15,77 @@
#define _CPU_SESSION_COMPONENT_H_
/* Genode includes */
+#include
#include
+#include
#include
+#include
/* GDB monitor includes */
-#include "thread_info.h"
+#include "append_list.h"
-using namespace Genode;
-using namespace Gdb_monitor;
-
-class Cpu_session_component : public Rpc_object
+namespace Gdb_monitor
{
+ class Cpu_session_component;
+ class Cpu_thread_component;
+ using namespace Genode;
+}
+
+class Gdb_monitor::Cpu_session_component : public Rpc_object
+{
+
private:
+ Rpc_entrypoint *_thread_ep;
+ Allocator *_md_alloc;
+
+ Pd_session_capability _core_pd;
+
Cpu_session_client _parent_cpu_session;
Signal_receiver *_exception_signal_receiver;
- Append_list _thread_list;
+ Append_list _thread_list;
- Thread_info *_thread_info(Thread_capability thread_cap);
+ bool _stop_new_threads = true;
+ Lock _stop_new_threads_lock;
+
+ Capability _native_cpu_cap;
+
+ Capability _setup_native_cpu();
+ void _cleanup_native_cpu();
public:
/**
* Constructor
*/
- Cpu_session_component(Signal_receiver *exception_signal_receiver, const char *args);
+ Cpu_session_component(Rpc_entrypoint *thread_ep,
+ Allocator *md_alloc,
+ Pd_session_capability core_pd,
+ Signal_receiver *exception_signal_receiver,
+ const char *args);
/**
* Destructor
*/
~Cpu_session_component();
- unsigned long lwpid(Thread_capability thread_cap);
+ Cpu_session &parent_cpu_session();
+ Rpc_entrypoint &thread_ep();
+ Signal_receiver *exception_signal_receiver();
Thread_capability thread_cap(unsigned long lwpid);
+ unsigned long lwpid(Thread_capability thread_cap);
+ Cpu_thread_component *lookup_cpu_thread(unsigned long lwpid);
+ Cpu_thread_component *lookup_cpu_thread(Thread_capability thread_cap);
+ int signal_pipe_read_fd(Thread_capability thread_cap);
+ int send_signal(Thread_capability thread_cap, int signo);
+ void handle_unresolved_page_fault();
+ void stop_new_threads(bool stop);
+ bool stop_new_threads();
+ Lock &stop_new_threads_lock();
+ int handle_initial_breakpoint(unsigned long lwpid);
+ void pause_all_threads();
+ void resume_all_threads();
Thread_capability first();
Thread_capability next(Thread_capability);
@@ -56,8 +93,11 @@ class Cpu_session_component : public Rpc_object
** CPU session interface **
***************************/
- Thread_capability create_thread(Capability, Name const &,
- Affinity::Location, Weight, addr_t) override;
+ Thread_capability create_thread(Capability,
+ Name const &,
+ Affinity::Location,
+ Weight,
+ addr_t) override;
void kill_thread(Thread_capability) override;
void exception_sigh(Signal_context_capability handler) override;
Affinity::Space affinity_space() const override;
diff --git a/repos/ports/src/app/gdb_monitor/cpu_thread_component.cc b/repos/ports/src/app/gdb_monitor/cpu_thread_component.cc
new file mode 100644
index 0000000000..bb20930455
--- /dev/null
+++ b/repos/ports/src/app/gdb_monitor/cpu_thread_component.cc
@@ -0,0 +1,151 @@
+/*
+ * \brief Cpu_thread_component class for GDB monitor
+ * \author Christian Prochaska
+ * \date 2016-05-12
+ */
+
+/*
+ * Copyright (C) 2016 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.
+ */
+
+
+/* GDB monitor includes */
+#include "cpu_thread_component.h"
+
+
+/* mem-break.c */
+extern "C" int breakpoint_len;
+extern "C" const unsigned char *breakpoint_data;
+extern "C" int set_gdb_breakpoint_at(long long where);
+
+/* genode-low.cc */
+extern "C" int genode_read_memory(long long memaddr, unsigned char *myaddr, int len);
+extern "C" int genode_write_memory (long long memaddr, const unsigned char *myaddr, int len);
+extern void genode_set_initial_breakpoint_at(long long addr);
+
+
+static unsigned long new_lwpid = GENODE_MAIN_LWPID;
+
+
+using namespace Gdb_monitor;
+
+
+bool Cpu_thread_component::_set_breakpoint_at_first_instruction(addr_t ip)
+{
+ _breakpoint_ip = ip;
+
+ if (genode_read_memory(_breakpoint_ip, _original_instructions,
+ breakpoint_len) != 0) {
+ PWRN("%s: could not read memory at thread start address", __PRETTY_FUNCTION__);
+ return false;
+ }
+
+ if (genode_write_memory(_breakpoint_ip, breakpoint_data,
+ breakpoint_len) != 0) {
+ PWRN("%s: could not set breakpoint at thread start address", __PRETTY_FUNCTION__);
+ return false;
+ }
+
+ return true;
+}
+
+
+void Cpu_thread_component::_remove_breakpoint_at_first_instruction()
+{
+ if (genode_write_memory(_breakpoint_ip, _original_instructions,
+ breakpoint_len) != 0)
+ PWRN("%s: could not remove breakpoint at thread start address", __PRETTY_FUNCTION__);
+}
+
+
+Dataspace_capability Cpu_thread_component::utcb()
+{
+ return _parent_cpu_thread.utcb();
+}
+
+
+void Cpu_thread_component::start(addr_t ip, addr_t sp)
+{
+ _lwpid = new_lwpid++;
+ _initial_ip = ip;
+
+ /* register the exception handler */
+ exception_sigh(exception_signal_context_cap());
+
+ /* set breakpoint at first instruction */
+ if (lwpid() == GENODE_MAIN_LWPID)
+ _set_breakpoint_at_first_instruction(ip);
+ else
+ genode_set_initial_breakpoint_at(ip);
+
+ _parent_cpu_thread.start(ip, sp);
+}
+
+
+void Cpu_thread_component::pause()
+{
+ _parent_cpu_thread.pause();
+}
+
+
+void Cpu_thread_component::resume()
+{
+ _parent_cpu_thread.resume();
+}
+
+
+void Cpu_thread_component::single_step(bool enable)
+{
+ _parent_cpu_thread.single_step(enable);
+}
+
+
+void Cpu_thread_component::cancel_blocking()
+{
+ _parent_cpu_thread.cancel_blocking();
+}
+
+
+void Cpu_thread_component::state(Thread_state const &state)
+{
+ _parent_cpu_thread.state(state);
+}
+
+
+Thread_state Cpu_thread_component::state()
+{
+ return _parent_cpu_thread.state();
+}
+
+
+void Cpu_thread_component::exception_sigh(Signal_context_capability handler)
+{
+ _parent_cpu_thread.exception_sigh(handler);
+}
+
+
+void Cpu_thread_component::affinity(Affinity::Location location)
+{
+ _parent_cpu_thread.affinity(location);
+}
+
+
+unsigned Cpu_thread_component::trace_control_index()
+{
+ return _parent_cpu_thread.trace_control_index();
+}
+
+
+Dataspace_capability Cpu_thread_component::trace_buffer()
+{
+ return _parent_cpu_thread.trace_buffer();
+}
+
+
+Dataspace_capability Cpu_thread_component::trace_policy()
+{
+ return _parent_cpu_thread.trace_policy();
+}
diff --git a/repos/ports/src/app/gdb_monitor/cpu_thread_component.h b/repos/ports/src/app/gdb_monitor/cpu_thread_component.h
new file mode 100644
index 0000000000..7462c4c2a5
--- /dev/null
+++ b/repos/ports/src/app/gdb_monitor/cpu_thread_component.h
@@ -0,0 +1,260 @@
+/*
+ * \brief Cpu_thread_component class for GDB monitor
+ * \author Christian Prochaska
+ * \date 2016-05-12
+ */
+
+/*
+ * Copyright (C) 2016 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 _CPU_THREAD_COMPONENT_H_
+#define _CPU_THREAD_COMPONENT_H_
+
+/* Genode includes */
+#include
+#include
+#include
+
+/* libc includes */
+#include
+#include
+
+#include "config.h"
+#include "append_list.h"
+#include "cpu_session_component.h"
+
+extern "C" int delete_gdb_breakpoint_at(long long where);
+
+namespace Gdb_monitor { class Cpu_thread_component; }
+
+class Gdb_monitor::Cpu_thread_component : public Rpc_object,
+ public Append_list::Element
+{
+ private:
+
+ static constexpr bool _verbose = false;
+
+ Cpu_session_component &_cpu_session_component;
+ Cpu_thread_client _parent_cpu_thread;
+ unsigned long _lwpid;
+ addr_t _initial_ip;
+
+ /*
+ * SIGTRAP, SIGSTOP and SIGINT must get delivered to the gdbserver code
+ * in the same order that they were generated. Since these signals are
+ * generated by different threads, the exception signal receiver is
+ * used as synchronization point.
+ */
+ Signal_dispatcher _exception_dispatcher;
+ Signal_dispatcher _sigstop_dispatcher;
+ Signal_dispatcher _sigint_dispatcher;
+
+ int _pipefd[2];
+ bool _initial_sigtrap_pending = true;
+ bool _initial_breakpoint_handled = false;
+
+ /* data for breakpoint at first instruction */
+ enum { MAX_BREAKPOINT_LEN = 8 }; /* value from mem-break.c */
+ unsigned char _original_instructions[MAX_BREAKPOINT_LEN];
+ addr_t _breakpoint_ip;
+
+ bool _set_breakpoint_at_first_instruction(addr_t ip);
+ void _remove_breakpoint_at_first_instruction();
+
+ void _dispatch_exception(unsigned)
+ {
+ deliver_signal(SIGTRAP);
+ }
+
+ void _dispatch_sigstop(unsigned)
+ {
+ deliver_signal(SIGSTOP);
+ }
+
+ void _dispatch_sigint(unsigned)
+ {
+ deliver_signal(SIGINT);
+ }
+
+ public:
+
+ Cpu_thread_component(Cpu_session_component &cpu_session_component,
+ Capability pd,
+ Cpu_session::Name const &name,
+ Affinity::Location affinity,
+ Cpu_session::Weight weight,
+ addr_t utcb)
+ : _cpu_session_component(cpu_session_component),
+ _parent_cpu_thread(
+ _cpu_session_component.parent_cpu_session().create_thread(pd,
+ name,
+ affinity,
+ weight,
+ utcb)),
+ _exception_dispatcher(
+ *_cpu_session_component.exception_signal_receiver(),
+ *this,
+ &Cpu_thread_component::_dispatch_exception),
+ _sigstop_dispatcher(
+ *_cpu_session_component.exception_signal_receiver(),
+ *this,
+ &Cpu_thread_component::_dispatch_sigstop),
+ _sigint_dispatcher(
+ *_cpu_session_component.exception_signal_receiver(),
+ *this,
+ &Cpu_thread_component::_dispatch_sigint)
+ {
+ _cpu_session_component.thread_ep().manage(this);
+
+ if (pipe(_pipefd) != 0)
+ PERR("could not create pipe");
+ }
+
+ ~Cpu_thread_component()
+ {
+ close(_pipefd[0]);
+ close(_pipefd[1]);
+
+ _cpu_session_component.thread_ep().dissolve(this);
+ }
+
+ Signal_context_capability exception_signal_context_cap()
+ {
+ return _exception_dispatcher;
+ }
+
+ Signal_context_capability sigstop_signal_context_cap()
+ {
+ return _sigstop_dispatcher;
+ }
+
+ Signal_context_capability sigint_signal_context_cap()
+ {
+ return _sigint_dispatcher;
+ }
+
+ Thread_capability thread_cap() { return cap(); }
+ unsigned long lwpid() { return _lwpid; }
+
+ Thread_capability parent_thread_cap() { return _parent_cpu_thread; }
+
+ int signal_pipe_read_fd() { return _pipefd[0]; }
+
+ int handle_initial_breakpoint()
+ {
+ if (!_initial_breakpoint_handled) {
+ _initial_breakpoint_handled = true;
+ return 1;
+ }
+
+ return 0;
+ }
+
+ int send_signal(int signo)
+ {
+ pause();
+
+ switch (signo) {
+ case SIGSTOP:
+ Signal_transmitter(sigstop_signal_context_cap()).submit();
+ return 1;
+ case SIGINT:
+ Signal_transmitter(sigint_signal_context_cap()).submit();
+ return 1;
+ default:
+ PERR("unexpected signal %d", signo);
+ return 0;
+ }
+ }
+
+ int deliver_signal(int signo)
+ {
+ if ((signo == SIGTRAP) && _initial_sigtrap_pending) {
+
+ _initial_sigtrap_pending = false;
+
+ if (_verbose)
+ PDBG("received initial SIGTRAP for lwpid %lu", _lwpid);
+
+ if (_lwpid == GENODE_MAIN_LWPID) {
+ _remove_breakpoint_at_first_instruction();
+ _initial_breakpoint_handled = true;
+ }
+
+ /*
+ * The lock guard prevents an interruption by
+ * 'genode_stop_all_threads()', which could cause
+ * the new thread to be resumed when it should be
+ * stopped.
+ */
+
+ Lock::Guard stop_new_threads_lock_guard(
+ _cpu_session_component.stop_new_threads_lock());
+
+ if (!_cpu_session_component.stop_new_threads())
+ resume();
+
+ /*
+ * gdbserver expects SIGSTOP as first signal of a new thread,
+ * but we cannot write SIGSTOP here, because waitpid() would
+ * detect that the thread is in an exception state and wait
+ * for the SIGTRAP. So SIGINFO ist used for this purpose.
+ */
+ signo = SIGINFO;
+ }
+
+ switch (signo) {
+ case SIGSTOP:
+ if (_verbose)
+ PDBG("delivering SIGSTOP to thread %lu", _lwpid);
+ break;
+ case SIGTRAP:
+ if (_verbose)
+ PDBG("delivering SIGTRAP to thread %lu", _lwpid);
+ break;
+ case SIGSEGV:
+ if (_verbose)
+ PDBG("delivering SIGSEGV to thread %lu", _lwpid);
+ break;
+ case SIGINT:
+ if (_verbose)
+ PDBG("delivering SIGINT to thread %lu", _lwpid);
+ break;
+ case SIGINFO:
+ if (_verbose)
+ PDBG("delivering initial SIGSTOP to thread %lu", _lwpid);
+ break;
+ default:
+ PERR("unexpected signal %d", signo);
+ }
+
+ write(_pipefd[1], &signo, sizeof(signo));
+
+ return 0;
+ }
+
+
+ /**************************
+ ** CPU thread interface **
+ *************************/
+
+ Dataspace_capability utcb() override;
+ void start(addr_t, addr_t) override;
+ void pause() override;
+ void resume() override;
+ void single_step(bool) override;
+ void cancel_blocking() override;
+ Thread_state state() override;
+ void state(Thread_state const &) override;
+ void exception_sigh(Signal_context_capability) override;
+ void affinity(Affinity::Location) override;
+ unsigned trace_control_index() override;
+ Dataspace_capability trace_buffer() override;
+ Dataspace_capability trace_policy() override;
+};
+
+#endif /* _CPU_THREAD_COMPONENT_H_ */
diff --git a/repos/ports/src/app/gdb_monitor/dataspace_object.h b/repos/ports/src/app/gdb_monitor/dataspace_object.h
index af239e7f61..e44f3480b0 100644
--- a/repos/ports/src/app/gdb_monitor/dataspace_object.h
+++ b/repos/ports/src/app/gdb_monitor/dataspace_object.h
@@ -41,6 +41,7 @@ namespace Gdb_monitor {
Region_map_component *region_map_component() { return _region_map_component; }
};
+
}
#endif /* _DATASPACE_OBJECT_H_ */
diff --git a/repos/ports/src/app/gdb_monitor/gdb_stub_thread.cc b/repos/ports/src/app/gdb_monitor/gdb_stub_thread.cc
deleted file mode 100644
index f4c2fd7cf9..0000000000
--- a/repos/ports/src/app/gdb_monitor/gdb_stub_thread.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * \brief GDB stub thread implementation
- * \author Christian Prochaska
- * \date 2011-03-10
- */
-
-/*
- * Copyright (C) 2011-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.
- */
-
-#include
-
-#include "gdb_stub_thread.h"
-
-using namespace Genode;
-using namespace Gdb_monitor;
-
-Gdb_stub_thread::Gdb_stub_thread()
-:
- Thread_deprecated("GDB server thread"),
- _cpu_session_component(0),
- _region_map_component(0),
- _signal_handler_thread(&_exception_signal_receiver)
-{
- _signal_handler_thread.start();
-}
-
-
-extern "C" int gdbserver_main(const char *port, void *gdb_stub_thread);
-
-
-void Gdb_stub_thread::entry()
-{
- gdbserver_main("/dev/terminal", this);
-
- sleep_forever();
-};
diff --git a/repos/ports/src/app/gdb_monitor/gdb_stub_thread.h b/repos/ports/src/app/gdb_monitor/gdb_stub_thread.h
deleted file mode 100644
index 3aa4de2b79..0000000000
--- a/repos/ports/src/app/gdb_monitor/gdb_stub_thread.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * \brief GDB stub thread
- * \author Christian Prochaska
- * \date 2011-03-10
- */
-
-/*
- * Copyright (C) 2011-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_STUB_THREAD_H_
-#define _GDB_STUB_THREAD_H_
-
-#include
-
-#include "cpu_session_component.h"
-#include "dataspace_object.h"
-#include "region_map_component.h"
-#include "signal_handler_thread.h"
-
-namespace Gdb_monitor {
-
- using namespace Genode;
-
- enum { GDB_STUB_STACK_SIZE = 4*4096 };
-
- class Gdb_stub_thread : public Thread_deprecated
- {
- private:
-
- Cpu_session_component *_cpu_session_component;
- Region_map_component *_region_map_component;
- Signal_receiver _exception_signal_receiver;
- Gdb_monitor::Signal_handler_thread _signal_handler_thread;
-
- public:
-
- Gdb_stub_thread();
- void entry();
-
- void set_cpu_session_component(Cpu_session_component *cpu_session_component)
- {
- _cpu_session_component = cpu_session_component;
- }
-
- void set_region_map_component(Region_map_component *region_map_component)
- {
- _region_map_component = region_map_component;
- }
-
- Cpu_session_component *cpu_session_component() { return _cpu_session_component; }
- Region_map_component *region_map_component() { return _region_map_component; }
- Signal_receiver *exception_signal_receiver() { return &_exception_signal_receiver; }
- int signal_fd() { return _signal_handler_thread.pipe_read_fd(); }
- };
-}
-
-#endif /* _GDB_STUB_THREAD_H_ */
diff --git a/repos/ports/src/app/gdb_monitor/gdbserver/config.h b/repos/ports/src/app/gdb_monitor/gdbserver/config.h
index 11e191e8a4..8f92aec9c3 100644
--- a/repos/ports/src/app/gdb_monitor/gdbserver/config.h
+++ b/repos/ports/src/app/gdb_monitor/gdbserver/config.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -28,4 +28,4 @@
#define __GENODE__
/* first process id */
-#define GENODE_LWP_BASE 1
+#define GENODE_MAIN_LWPID 1
diff --git a/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.cc b/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.cc
index 3bc1421c5b..2b6f9a3b57 100644
--- a/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.cc
+++ b/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.cc
@@ -6,137 +6,423 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
*/
+#include
+#include
+#include
+#include
+
extern "C" {
#define private _private
#include "genode-low.h"
+#include "server.h"
#include "linux-low.h"
#define _private private
int linux_detach_one_lwp (struct inferior_list_entry *entry, void *args);
}
-#include
#include
-#include
+#include
+#include
#include
+#include
+#include
+#include
+#include
+#include
+#include "app_child.h"
#include "cpu_session_component.h"
-
-#include "gdb_stub_thread.h"
+#include "cpu_thread_component.h"
+#include "genode_child_resources.h"
+#include "rom.h"
+#include "signal_handler_thread.h"
static bool verbose = false;
+static int _new_thread_pipe[2];
+
+/*
+ * When 'waitpid()' reports a SIGTRAP, this variable stores the lwpid of the
+ * corresponding thread. This information is used in the initial breakpoint
+ * handler to let the correct thread handle the event.
+ */
+static unsigned long sigtrap_lwpid;
+
using namespace Genode;
using namespace Gdb_monitor;
+static Genode_child_resources *_genode_child_resources = 0;
-static Lock &main_thread_ready_lock()
+
+Genode_child_resources *genode_child_resources()
{
- static Lock _main_thread_ready_lock(Lock::LOCKED);
- return _main_thread_ready_lock;
+ return _genode_child_resources;
}
-static Lock &gdbserver_ready_lock()
+static void genode_stop_thread(unsigned long lwpid)
{
- static Lock _gdbserver_ready_lock(Lock::LOCKED);
- return _gdbserver_ready_lock;
-}
+ Cpu_session_component *csc = genode_child_resources()->cpu_session_component();
+ Cpu_thread_component *cpu_thread = csc->lookup_cpu_thread(lwpid);
-Gdb_stub_thread *gdb_stub_thread()
-{
- return (Gdb_stub_thread*)(current_process()->_private->gdb_stub_thread);
-}
-
-
-extern "C" int genode_signal_fd()
-{
- return gdb_stub_thread()->signal_fd();
-}
-
-
-void genode_add_thread(unsigned long lwpid)
-{
- if (lwpid == GENODE_LWP_BASE) {
- main_thread_ready_lock().unlock();
- } else {
- if (lwpid == GENODE_LWP_BASE + 1) {
- /* make sure gdbserver is ready to attach new threads */
- gdbserver_ready_lock().lock();
- }
- linux_attach_lwp(lwpid);
+ if (!cpu_thread) {
+ PERR("%s: could not find CPU thread object for lwpid %lu",
+ __PRETTY_FUNCTION__, lwpid);
+ return;
}
+
+ cpu_thread->pause();
+}
+
+
+extern "C" pid_t waitpid(pid_t pid, int *status, int flags)
+{
+ extern int remote_desc;
+
+ fd_set readset;
+
+ Cpu_session_component *csc = genode_child_resources()->cpu_session_component();
+
+ while(1) {
+
+ FD_ZERO (&readset);
+
+ if (remote_desc != -1)
+ FD_SET (remote_desc, &readset);
+
+ if (pid == -1) {
+
+ FD_SET(_new_thread_pipe[0], &readset);
+
+ Thread_capability thread_cap = csc->first();
+
+ while (thread_cap.valid()) {
+ FD_SET(csc->signal_pipe_read_fd(thread_cap), &readset);
+ thread_cap = csc->next(thread_cap);
+ }
+
+ } else {
+
+ FD_SET(csc->signal_pipe_read_fd(csc->thread_cap(pid)), &readset);
+ }
+
+ struct timeval wnohang_timeout = {0, 0};
+ struct timeval *timeout = (flags & WNOHANG) ? &wnohang_timeout : NULL;
+
+ /* TODO: determine the highest fd in the set for optimization */
+ int res = select(FD_SETSIZE, &readset, 0, 0, timeout);
+
+ if (res > 0) {
+
+ if ((remote_desc != -1) && FD_ISSET(remote_desc, &readset)) {
+
+ /* received input from GDB */
+
+ int cc;
+ char c = 0;
+
+ cc = read (remote_desc, &c, 1);
+
+ if (cc == 1 && c == '\003' && current_inferior != NULL) {
+ /* this causes a SIGINT to be delivered to one of the threads */
+ (*the_target->request_interrupt)();
+ continue;
+ } else {
+ if (verbose)
+ PDBG("input_interrupt, count = %d c = %d ('%c')", cc, c, c);
+ }
+
+ } else if (FD_ISSET(_new_thread_pipe[0], &readset)) {
+
+ unsigned long lwpid = GENODE_MAIN_LWPID;
+
+ genode_stop_thread(lwpid);
+
+ *status = W_STOPCODE(SIGTRAP) | (PTRACE_EVENT_CLONE << 16);
+
+ return lwpid;
+
+ } else {
+
+ /* received a signal */
+
+ Thread_capability thread_cap = csc->first();
+
+ while (thread_cap.valid()) {
+ if (FD_ISSET(csc->signal_pipe_read_fd(thread_cap), &readset))
+ break;
+ thread_cap = csc->next(thread_cap);
+ }
+
+ if (!thread_cap.valid())
+ continue;
+
+ int signal;
+ read(csc->signal_pipe_read_fd(thread_cap), &signal, sizeof(signal));
+
+ unsigned long lwpid = csc->lwpid(thread_cap);
+
+ if (verbose)
+ PDBG("thread %lu received signal %d", lwpid, signal);
+
+ if (signal == SIGTRAP) {
+
+ sigtrap_lwpid = lwpid;
+
+ } else if (signal == SIGSTOP) {
+
+ /*
+ * Check if a SIGTRAP is pending
+ *
+ * This can happen if a single-stepped thread gets paused while gdbserver
+ * handles a signal of a different thread and the exception signal after
+ * the single step has not arrived yet. In this case, the SIGTRAP must be
+ * delivered first, otherwise gdbserver would single-step the thread again.
+ */
+
+ Cpu_thread_component *cpu_thread = csc->lookup_cpu_thread(lwpid);
+
+ Thread_state thread_state = cpu_thread->state();
+
+ if (thread_state.exception) {
+ /* resend the SIGSTOP signal */
+ csc->send_signal(cpu_thread->cap(), SIGSTOP);
+ continue;
+ }
+
+ } else if (signal == SIGINFO) {
+
+ if (verbose)
+ PDBG("received SIGINFO for new lwpid %lu", lwpid);
+
+ if (lwpid != GENODE_MAIN_LWPID)
+ write(_new_thread_pipe[1], &lwpid, sizeof(lwpid));
+
+ /*
+ * First signal of a new thread. On Genode originally a
+ * SIGTRAP, but gdbserver expects SIGSTOP.
+ */
+
+ signal = SIGSTOP;
+ }
+
+ *status = W_STOPCODE(signal);
+
+ return lwpid;
+ }
+
+ } else {
+
+ return res;
+
+ }
+ }
+}
+
+
+extern "C" long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data)
+{
+ const char *request_str = 0;
+
+ switch (request) {
+ case PTRACE_TRACEME: request_str = "PTRACE_TRACEME"; break;
+ case PTRACE_PEEKTEXT: request_str = "PTRACE_PEEKTEXT"; break;
+ case PTRACE_PEEKUSER: request_str = "PTRACE_PEEKUSER"; break;
+ case PTRACE_POKETEXT: request_str = "PTRACE_POKETEXT"; break;
+ case PTRACE_POKEUSER: request_str = "PTRACE_POKEUSER"; break;
+ case PTRACE_CONT: request_str = "PTRACE_CONT"; break;
+ case PTRACE_KILL: request_str = "PTRACE_KILL"; break;
+ case PTRACE_SINGLESTEP: request_str = "PTRACE_SINGLESTEP"; break;
+ case PTRACE_GETREGS: request_str = "PTRACE_GETREGS"; break;
+ case PTRACE_SETREGS: request_str = "PTRACE_SETREGS"; break;
+ case PTRACE_ATTACH: request_str = "PTRACE_ATTACH"; break;
+ case PTRACE_DETACH: request_str = "PTRACE_DETACH"; break;
+ case PTRACE_GETEVENTMSG:
+ /*
+ * Only PTRACE_EVENT_CLONE is currently supported.
+ *
+ * Read the lwpid of the new thread from the pipe.
+ */
+ read(_new_thread_pipe[0], data, sizeof(unsigned long));
+ return 0;
+ case PTRACE_GETREGSET: request_str = "PTRACE_GETREGSET"; break;
+ }
+
+ PWRN("ptrace(%s (0x%x)) called - not implemented!", request_str, request);
+
+ errno = EINVAL;
+ return -1;
+}
+
+
+extern "C" int fork()
+{
+ /* create the thread announcement pipe */
+
+ if (pipe(_new_thread_pipe) != 0) {
+ PERR("could not create the 'new thread' pipe");
+ return -1;
+ }
+
+ /* look for dynamic linker */
+
+ Dataspace_capability ldso_cap;
+ try {
+ Rom_connection ldso_rom("ld.lib.so");
+ ldso_cap = clone_rom(ldso_rom.dataspace());
+ } catch (...) {
+ PDBG("ld.lib.so not found");
+ }
+
+ /* extract target filename from config file */
+
+ static char filename[32] = "";
+
+ try {
+ config()->xml_node().sub_node("target").attribute("name").value(filename, sizeof(filename));
+ } catch (Xml_node::Nonexistent_sub_node) {
+ PERR("Error: Missing '' sub node.");
+ return -1;
+ } catch (Xml_node::Nonexistent_attribute) {
+ PERR("Error: Missing 'name' attribute of '' sub node.");
+ return -1;
+ }
+
+ /* extract target node from config file */
+ Xml_node target_node = config()->xml_node().sub_node("target");
+
+ /*
+ * preserve the configured amount of memory for gdb_monitor and give the
+ * remainder to the child
+ */
+ Number_of_bytes preserved_ram_quota = 0;
+ try {
+ Xml_node preserve_node = config()->xml_node().sub_node("preserve");
+ if (preserve_node.attribute("name").has_value("RAM"))
+ preserve_node.attribute("quantum").value(&preserved_ram_quota);
+ else
+ throw Xml_node::Exception();
+ } catch (...) {
+ PERR("Error: could not find a valid config node");
+ return -1;
+ }
+
+ Number_of_bytes ram_quota = env()->ram_session()->avail() - preserved_ram_quota;
+
+ /* start the application */
+ char *unique_name = filename;
+ Capability file_cap;
+ try {
+ static Rom_connection rom(filename, unique_name);
+ file_cap = rom.dataspace();
+ } catch (Rom_connection::Rom_connection_failed) {
+ Genode::printf("Error: Could not access file \"%s\" from ROM service.\n", filename);
+ return -1;
+ }
+
+ /* copy ELF image to writable dataspace */
+ Genode::size_t elf_size = Dataspace_client(file_cap).size();
+ Dataspace_capability elf_cap = clone_rom(file_cap);
+
+ /* create ram session for child with some of our own quota */
+ static Ram_connection ram;
+ ram.ref_account(env()->ram_session_cap());
+ env()->ram_session()->transfer_quota(ram.cap(), (Genode::size_t)ram_quota - elf_size);
+
+ /* cap session for allocating capabilities for parent interfaces */
+ static Cap_connection cap_session;
+
+ static Service_registry parent_services;
+
+ enum { CHILD_ROOT_EP_STACK = 1024*sizeof(addr_t) };
+ static Rpc_entrypoint child_root_ep(&cap_session, CHILD_ROOT_EP_STACK,
+ "child_root_ep");
+
+ static Signal_receiver signal_receiver;
+
+ static Gdb_monitor::Signal_handler_thread
+ signal_handler_thread(&signal_receiver);
+ signal_handler_thread.start();
+
+ App_child *child = new (env()->heap()) App_child(unique_name,
+ elf_cap,
+ ldso_cap,
+ ram.cap(),
+ &cap_session,
+ &parent_services,
+ &child_root_ep,
+ &signal_receiver,
+ target_node);
+
+ _genode_child_resources = child->genode_child_resources();
+
+ child->start();
+
+ return GENODE_MAIN_LWPID;
+}
+
+
+extern "C" int kill(pid_t pid, int sig)
+{
+ Cpu_session_component *csc = genode_child_resources()->cpu_session_component();
+
+ Thread_capability thread_cap = csc->thread_cap(pid);
+
+ if (!thread_cap.valid()) {
+ PERR("%s: could not find thread capability for lwpid %d",
+ __PRETTY_FUNCTION__, pid);
+ return -1;
+ }
+
+ return csc->send_signal(thread_cap, sig);
+}
+
+
+extern "C" int initial_breakpoint_handler(CORE_ADDR addr)
+{
+ Cpu_session_component *csc = genode_child_resources()->cpu_session_component();
+ return csc->handle_initial_breakpoint(sigtrap_lwpid);
+}
+
+
+void genode_set_initial_breakpoint_at(CORE_ADDR addr)
+{
+ set_breakpoint_at(addr, initial_breakpoint_handler);
}
void genode_remove_thread(unsigned long lwpid)
{
- int pid = GENODE_LWP_BASE;
+ int pid = GENODE_MAIN_LWPID;
linux_detach_one_lwp((struct inferior_list_entry *)
- find_thread_ptid(ptid_build(GENODE_LWP_BASE, lwpid, 0)), &pid);
-}
-
-
-void genode_wait_for_target_main_thread()
-{
- /* gdbserver is now ready to attach new threads */
- gdbserver_ready_lock().unlock();
-
- /* wait until the target's main thread has been created */
- main_thread_ready_lock().lock();
-}
-
-
-extern "C" void genode_detect_all_threads()
-{
- Cpu_session_component *csc = gdb_stub_thread()->cpu_session_component();
-
- Thread_capability thread_cap = csc->next(csc->first()); /* second thread */
-
- while (thread_cap.valid()) {
- linux_attach_lwp(csc->lwpid(thread_cap));
- thread_cap = csc->next(thread_cap);
- }
+ find_thread_ptid(ptid_build(GENODE_MAIN_LWPID, lwpid, 0)), &pid);
}
extern "C" void genode_stop_all_threads()
{
- Cpu_session_component *csc = gdb_stub_thread()->cpu_session_component();
-
- Thread_capability thread_cap = csc->first();
-
- while (thread_cap.valid()) {
- Cpu_thread_client(thread_cap).pause();
- thread_cap = csc->next(thread_cap);
- }
+ Cpu_session_component *csc = genode_child_resources()->cpu_session_component();
+ csc->pause_all_threads();
}
-extern "C" void genode_resume_all_threads()
+void genode_resume_all_threads()
{
- Cpu_session_component *csc = gdb_stub_thread()->cpu_session_component();
-
- Thread_capability thread_cap = csc->first();
-
- while (thread_cap.valid()) {
- Cpu_thread_client(thread_cap).resume();
- thread_cap = csc->next(thread_cap);
- }
+ Cpu_session_component *csc = genode_child_resources()->cpu_session_component();
+ csc->resume_all_threads();
}
int genode_detach(int pid)
{
- find_inferior (&all_threads, linux_detach_one_lwp, &pid);
-
genode_resume_all_threads();
return 0;
@@ -146,86 +432,67 @@ int genode_detach(int pid)
int genode_kill(int pid)
{
/* TODO */
- if (verbose) PDBG("genode_kill() called - not implemented\n");
+ if (verbose) PDBG("not implemented, just detaching instead...");
return genode_detach(pid);
}
-void genode_interrupt_thread(unsigned long lwpid)
-{
- Cpu_session_component *csc = gdb_stub_thread()->cpu_session_component();
-
- Thread_capability thread_cap = csc->thread_cap(lwpid);
-
- if (!thread_cap.valid()) {
- PERR("could not find thread capability for lwpid %lu", lwpid);
- return;
- }
-
- Cpu_thread_client(thread_cap).pause();
-}
-
-
void genode_continue_thread(unsigned long lwpid, int single_step)
{
- Cpu_session_component *csc = gdb_stub_thread()->cpu_session_component();
+ Cpu_session_component *csc = genode_child_resources()->cpu_session_component();
- Thread_capability thread_cap = csc->thread_cap(lwpid);
+ Cpu_thread_component *cpu_thread = csc->lookup_cpu_thread(lwpid);
- if (!thread_cap.valid()) {
- PERR("could not find thread capability for lwpid %lu", lwpid);
+ if (!cpu_thread) {
+ PERR("%s: could not find CPU thread object for lwpid %lu",
+ __PRETTY_FUNCTION__, lwpid);
return;
}
- Cpu_thread_client cpu_thread(thread_cap);
- cpu_thread.single_step(single_step);
- cpu_thread.resume();
+ cpu_thread->single_step(single_step);
+ cpu_thread->resume();
}
-/*
- * This function returns the first thread with a page fault that it finds.
- * Multiple page-faulted threads are currently not supported.
- */
-
-unsigned long genode_find_segfault_lwpid()
+void genode_fetch_registers(struct regcache *regcache, int regno)
{
+ unsigned long reg_content = 0;
- Cpu_session_component *csc = gdb_stub_thread()->cpu_session_component();
-
- /*
- * It can happen that the thread state of the thread which caused the
- * page fault is not accessible yet. In that case, we'll retry until
- * it is accessible.
- */
-
- while (1) {
-
- Thread_capability thread_cap = csc->first();
-
- while (thread_cap.valid()) {
-
- try {
-
- Thread_state thread_state = Cpu_thread_client(thread_cap).state();
-
- if (thread_state.unresolved_page_fault) {
-
- /*
- * On base-foc it is necessary to pause the thread before
- * IP and SP are available in the thread state.
- */
- Cpu_thread_client(thread_cap).pause();
-
- return csc->lwpid(thread_cap);
- }
-
- } catch (Cpu_thread::State_access_failed) { }
-
- thread_cap = csc->next(thread_cap);
+ if (regno == -1) {
+ for (regno = 0; regno < the_low_target.num_regs; regno++) {
+ if (genode_fetch_register(regno, ®_content) == 0)
+ supply_register(regcache, regno, ®_content);
+ else
+ supply_register(regcache, regno, 0);
}
+ } else {
+ if (genode_fetch_register(regno, ®_content) == 0)
+ supply_register(regcache, regno, ®_content);
+ else
+ supply_register(regcache, regno, 0);
+ }
+}
+
+void genode_store_registers(struct regcache *regcache, int regno)
+{
+ if (verbose) PDBG("genode_store_registers(): regno = %d", regno);
+
+ unsigned long reg_content = 0;
+
+ if (regno == -1) {
+ for (regno = 0; regno < the_low_target.num_regs; regno++) {
+ if ((size_t)register_size(regno) <= sizeof(reg_content)) {
+ collect_register(regcache, regno, ®_content);
+ genode_store_register(regno, reg_content);
+ }
+ }
+ } else {
+ if ((size_t)register_size(regno) <= sizeof(reg_content)) {
+ collect_register(regcache, regno, ®_content);
+ genode_store_register(regno, reg_content);
+ }
}
}
@@ -335,7 +602,7 @@ class Memory_model
if (!local_base) {
PWRN("Memory model: no memory at address %p", addr);
- return 0;
+ throw No_memory_at_address();
}
unsigned char value =
@@ -350,7 +617,7 @@ class Memory_model
void write(void *addr, unsigned char value)
{
if (verbose)
- Genode::printf("write addr=%p, value=%x\n", addr, value);
+ Genode::printf("write addr=%p, value=%x\n", addr, value);
Lock::Guard guard(_lock);
@@ -363,7 +630,7 @@ class Memory_model
if (!local_base) {
PWRN("Memory model: no memory at address %p", addr);
PWRN("(attempted to write %x)", (int)value);
- return;
+ throw No_memory_at_address();
}
local_base[offset_in_region] = value;
@@ -376,7 +643,7 @@ class Memory_model
*/
static Memory_model *memory_model()
{
- static Memory_model inst(gdb_stub_thread()->region_map_component());
+ static Memory_model inst(genode_child_resources()->region_map_component());
return &inst;
}
@@ -387,7 +654,55 @@ unsigned char genode_read_memory_byte(void *addr)
}
+int genode_read_memory(CORE_ADDR memaddr, unsigned char *myaddr, int len)
+{
+ if (verbose)
+ PDBG("genode_read_memory(%llx, %p, %d)", memaddr, myaddr, len);
+
+ if (myaddr)
+ try {
+ for (int i = 0; i < len; i++)
+ myaddr[i] = genode_read_memory_byte((void*)((unsigned long)memaddr + i));
+ } catch (No_memory_at_address) {
+ return EFAULT;
+ }
+
+ return 0;
+}
+
+
void genode_write_memory_byte(void *addr, unsigned char value)
{
- return memory_model()->write(addr, value);
+ memory_model()->write(addr, value);
+}
+
+
+int genode_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
+{
+ if (verbose)
+ PDBG("genode_write_memory(%llx, %p, %d)", memaddr, myaddr, len);
+
+ if (myaddr && (len > 0)) {
+ if (debug_threads) {
+ /* Dump up to four bytes. */
+ unsigned int val = * (unsigned int *) myaddr;
+ if (len == 1)
+ val = val & 0xff;
+ else if (len == 2)
+ val = val & 0xffff;
+ else if (len == 3)
+ val = val & 0xffffff;
+ fprintf(stderr, "Writing %0*x to 0x%08lx", 2 * ((len < 4) ? len : 4),
+ val, (long)memaddr);
+ }
+
+ for (int i = 0; i < len; i++)
+ try {
+ genode_write_memory_byte((void*)((unsigned long)memaddr + i), myaddr[i]);
+ } catch (No_memory_at_address) {
+ return EFAULT;
+ }
+ }
+
+ return 0;
}
diff --git a/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.h b/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.h
index 19fb10b37f..7d69e9f2c4 100644
--- a/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.h
+++ b/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -18,27 +18,29 @@
#ifndef GENODE_LOW_H
#define GENODE_LOW_H
+#include
+
#include "server.h"
-int genode_signal_fd();
+/* exception type */
+struct No_memory_at_address { };
-void genode_wait_for_target_main_thread();
-void genode_detect_all_threads();
+/* interface for linux-low.c */
void genode_stop_all_threads();
-void genode_resume_all_threads();
-
-ptid_t genode_wait_for_signal_or_gdb_interrupt(struct target_waitstatus *status);
void genode_continue_thread(unsigned long lwpid, int single_step);
-unsigned long genode_find_segfault_lwpid();
+int genode_kill(int pid);
+int genode_detach(int pid);
+void genode_fetch_registers(struct regcache *regcache, int regno);
+void genode_store_registers(struct regcache *regcache, int regno);
+int genode_read_memory(CORE_ADDR memaddr, unsigned char *myaddr, int len);
+int genode_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len);
+
+/* interface for genode-low.cc and low.cc */
int genode_fetch_register(int regno, unsigned long *reg_content);
void genode_store_register(int regno, unsigned long reg_content);
unsigned char genode_read_memory_byte(void *addr);
-void genode_write_memory_byte(void *addr, unsigned char value);
-
-int genode_detach(int pid);
-int genode_kill(int pid);
#endif /* GENODE_LOW_H */
diff --git a/repos/ports/src/app/gdb_monitor/gdbserver_genode.patch b/repos/ports/src/app/gdb_monitor/gdbserver_genode.patch
index 30793a88c3..5ddca3b25a 100644
--- a/repos/ports/src/app/gdb_monitor/gdbserver_genode.patch
+++ b/repos/ports/src/app/gdb_monitor/gdbserver_genode.patch
@@ -4,92 +4,85 @@ From: Christian Prochaska
---
- gdb/gdbserver/linux-arm-low.c | 4 +
- gdb/gdbserver/linux-low.c | 223 ++++++++++++++++++++++++++++++++++-------
- gdb/gdbserver/linux-low.h | 5 +
- gdb/gdbserver/linux-x86-low.c | 43 +++++++-
- gdb/gdbserver/remote-utils.c | 80 +++++++++++++++
- gdb/gdbserver/server.c | 52 ++++++++--
- gdb/gdbserver/server.h | 4 -
- 7 files changed, 356 insertions(+), 55 deletions(-)
+ gdb/gdbserver/linux-arm-low.c | 13 +++++
+ gdb/gdbserver/linux-low.c | 114 +++++++++++++++++++++++++++++++++++++++++
+ gdb/gdbserver/linux-low.h | 2 +
+ gdb/gdbserver/linux-x86-low.c | 53 +++++++++++++++++++
+ gdb/gdbserver/remote-utils.c | 12 ++++
+ gdb/gdbserver/server.c | 30 +++++++++--
+ gdb/gdbserver/server.h | 4 +
+ 7 files changed, 217 insertions(+), 11 deletions(-)
diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
-index babb20c..d14c8cc 100644
+index babb20c..23d9e60 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
-@@ -25,6 +25,7 @@
+@@ -25,6 +25,9 @@
#ifndef ELFMAG0
#include
#endif
++#ifdef __GENODE__
+#include
++#endif
#include
/* Defined in auto-generated files. */
-@@ -306,6 +307,7 @@ static void
+@@ -209,7 +212,11 @@ static const unsigned short thumb2_breakpoint[] = { 0xf7f0, 0xa000 };
+ is used for gdbserver, so single threaded debugging should work
+ OK, but for multi-threaded debugging we only insert the current
+ ABI's breakpoint instruction. For now at least. */
++#ifdef __GENODE__
++static const unsigned long arm_eabi_breakpoint = 0xe7ffdefe;
++#else
+ static const unsigned long arm_eabi_breakpoint = 0xe7f001f0;
++#endif
+
+ static int
+ arm_breakpoint_at (CORE_ADDR where)
+@@ -306,6 +313,11 @@ static void
arm_arch_setup (void)
{
arm_hwcap = 0;
-+#if 0
++
++#ifndef __GENODE__
++
++ /* Genode: 'init_registers_arm_with_*()' functions not generated */
++
if (arm_get_hwcap (&arm_hwcap) == 0)
{
init_registers_arm ();
-@@ -347,7 +349,7 @@ arm_arch_setup (void)
+@@ -347,6 +359,7 @@ arm_arch_setup (void)
return;
}
--
+#endif
+
/* The default configuration uses legacy FPA registers, probably
simulated. */
- init_registers_arm ();
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
-index 81b8540..5b31da5 100644
+index e597e2f..62215fc 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
-@@ -19,6 +19,7 @@
-
+@@ -20,6 +20,10 @@
#include "server.h"
#include "linux-low.h"
-+#include "genode-low.h"
++#ifdef __GENODE__
++#include "genode-low.h"
++#endif
++
#include
#include
-@@ -281,6 +282,7 @@ elf_64_file_p (const char *file)
- static void
- delete_lwp (struct lwp_info *lwp)
- {
-+ if (debug_threads) printf("delete_lwp()\n");
- remove_thread (get_lwp_thread (lwp));
- remove_inferior (&all_lwps, &lwp->head);
- free (lwp->arch_private);
-@@ -535,6 +537,8 @@ get_stop_pc (struct lwp_info *lwp)
- static void *
- add_lwp (ptid_t ptid)
- {
-+ printf("add_lwp(%u, %lu, %lu)\n", ptid.pid, ptid.lwp, ptid.tid);
-+
- struct lwp_info *lwp;
-
- lwp = (struct lwp_info *) xmalloc (sizeof (*lwp));
-@@ -547,6 +551,9 @@ add_lwp (ptid_t ptid)
-
- add_inferior_to_list (&all_lwps, &lwp->head);
-
-+ /* FIXME: this is not always true? */
-+ lwp->stopped = 1;
-+
- return lwp;
- }
-
-@@ -606,6 +613,7 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
+ #include
+@@ -606,6 +610,7 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
ptid_t ptid;
struct lwp_info *new_lwp;
-+#if 0
++#ifndef __GENODE__
if (ptrace (PTRACE_ATTACH, lwpid, 0, 0) != 0)
{
if (!initial)
-@@ -621,6 +629,7 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
+@@ -621,6 +626,7 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
error ("Cannot attach to lwp %ld: %s (%d)\n", lwpid,
strerror (errno), errno);
}
@@ -97,40 +90,41 @@ index 81b8540..5b31da5 100644
if (initial)
/* NOTE/FIXME: This lwp might have not been the tgid. */
-@@ -637,10 +646,11 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
+@@ -637,6 +643,9 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
new_lwp = (struct lwp_info *) add_lwp (ptid);
add_thread (ptid, new_lwp);
-+#if 0
++#ifdef __GENODE__
++ new_lwp->stopped = 1;
++#else
/* We need to wait for SIGSTOP before being able to make the next
ptrace call on this LWP. */
new_lwp->must_set_ptrace_flags = 1;
--
+@@ -675,6 +684,7 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
+ end of the list, and so the new thread has not yet reached
+ wait_for_sigstop (but will). */
+ new_lwp->stop_expected = 1;
+#endif
- /* The next time we wait for this LWP we'll see a SIGSTOP as PTRACE_ATTACH
- brings it to a halt.
+ }
-@@ -689,6 +699,10 @@ linux_attach (unsigned long pid)
+ void
+@@ -689,6 +699,7 @@ linux_attach (unsigned long pid)
linux_attach_lwp_1 (pid, 1);
linux_add_process (pid, 1);
-+ /* must be called after 'add_thread()', because 'current_inferior' must be set */
-+ the_low_target.arch_setup();
-+
-+#if 0
++#ifndef __GENODE__
if (!non_stop)
{
struct thread_info *thread;
-@@ -698,7 +712,7 @@ linux_attach (unsigned long pid)
+@@ -698,6 +709,7 @@ linux_attach (unsigned long pid)
thread = find_thread_ptid (ptid_build (pid, pid, 0));
thread->last_resume_kind = resume_stop;
}
--
+#endif
+
return 0;
}
-
-@@ -812,7 +826,11 @@ linux_kill (int pid)
+@@ -812,7 +824,11 @@ linux_kill (int pid)
return 0;
}
@@ -142,46 +136,53 @@ index 81b8540..5b31da5 100644
linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
{
struct thread_info *thread = (struct thread_info *) entry;
-@@ -822,6 +840,7 @@ linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
+@@ -822,6 +838,7 @@ linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
if (ptid_get_pid (entry->id) != pid)
return 0;
-+#if 0
++#ifndef __GENODE__
/* If this process is stopped but is expecting a SIGSTOP, then make
sure we take care of that now. This isn't absolutely guaranteed
to collect the SIGSTOP, but is fairly likely to. */
-@@ -833,13 +852,15 @@ linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
+@@ -833,13 +850,16 @@ linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
linux_resume_one_lwp (lwp, 0, 0, NULL);
linux_wait_for_event (lwp->head.id, &wstat, __WALL);
}
--
+#endif
+
/* Flush any pending changes to the process's registers. */
regcache_invalidate_one ((struct inferior_list_entry *)
get_lwp_thread (lwp));
-+#if 0
++#ifndef __GENODE__
/* Finally, let it resume. */
ptrace (PTRACE_DETACH, lwpid_of (lwp), 0, 0);
+#endif
delete_lwp (lwp);
return 0;
-@@ -2460,6 +2481,13 @@ async_file_mark (void)
- be awakened anyway. */
- }
+@@ -1071,6 +1091,10 @@ retry:
-+static int mark_as_stopped(struct inferior_list_entry *entry, void *arg)
-+{
-+ struct lwp_info *lwp = (struct lwp_info *) entry;
-+ lwp->stopped = 1;
-+ return 0;
-+}
-+
- static ptid_t
- linux_wait (ptid_t ptid,
- struct target_waitstatus *ourstatus, int target_options)
-@@ -2469,18 +2497,28 @@ linux_wait (ptid_t ptid,
+ if (WIFSTOPPED (*wstatp) && WSTOPSIG (*wstatp) == SIGTRAP)
+ {
++#ifdef __GENODE__
++ /* no watchpoint support yet */
++ child->stopped_by_watchpoint = 0;
++#else
+ if (the_low_target.stopped_by_watchpoint == NULL)
+ {
+ child->stopped_by_watchpoint = 0;
+@@ -1096,7 +1120,8 @@ retry:
+
+ current_inferior = saved_inferior;
+ }
+- }
++#endif
++ }
+
+ /* Store the STOP_PC, with adjustment applied. This depends on the
+ architecture being defined already (so that CHILD has a valid
+@@ -2469,18 +2494,22 @@ linux_wait (ptid_t ptid,
if (debug_threads)
fprintf (stderr, "linux_wait: [%s]\n", target_pid_to_str (ptid));
@@ -191,13 +192,7 @@ index 81b8540..5b31da5 100644
async_file_flush ();
+#endif
-+#ifdef __GENODE__
-+ /* TODO: get some information from wait_for_signal_or_gdb_interrupt() */
-+ event_ptid = genode_wait_for_signal_or_gdb_interrupt(ourstatus);
-+ find_inferior (&all_lwps, mark_as_stopped, NULL);
-+#else
event_ptid = linux_wait_1 (ptid, ourstatus, target_options);
-+#endif
+#ifndef __GENODE__
/* If at least one stop was reported, there may be more. A single
@@ -210,22 +205,23 @@ index 81b8540..5b31da5 100644
return event_ptid;
}
-@@ -2785,6 +2823,8 @@ static void
- linux_resume_one_lwp (struct lwp_info *lwp,
- int step, int signal, siginfo_t *info)
- {
-+ printf("linux_resume_one_lwp(step = %d, signal = %d)\n", step, signal);
-+
- struct thread_info *saved_inferior;
- int fast_tp_collecting;
-
-@@ -2958,10 +2998,15 @@ lwp %ld wants to get out of fast tracepoint jump pad single-stepping\n",
+@@ -2958,10 +2987,25 @@ lwp %ld wants to get out of fast tracepoint jump pad single-stepping\n",
lwp->stopped = 0;
lwp->stopped_by_watchpoint = 0;
lwp->stepping = step;
+
+#ifdef __GENODE__
++
++ /*
++ * On Linux, the thread would get stopped immediately after resuming
++ * if a SIGSTOP is pending. This is not the case on Genode, so we
++ * just keep the thread stopped.
++ */
++ if (lwp->stop_expected)
++ return;
++
+ genode_continue_thread(lwpid_of(lwp), step);
++
+#else
ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, lwpid_of (lwp), 0,
/* Coerce to a uintptr_t first to avoid potential gcc warning
@@ -235,325 +231,170 @@ index 81b8540..5b31da5 100644
current_inferior = saved_inferior;
if (errno)
-@@ -3325,6 +3370,8 @@ finish_step_over (struct lwp_info *lwp)
- static int
- linux_resume_one_thread (struct inferior_list_entry *entry, void *arg)
- {
-+ if (debug_threads) printf("linux_resume_one_thread()\n");
-+
- struct lwp_info *lwp;
- struct thread_info *thread;
- int step;
-@@ -3436,6 +3483,8 @@ linux_resume_one_thread (struct inferior_list_entry *entry, void *arg)
+@@ -5009,6 +5053,13 @@ linux_core_of_thread (ptid_t ptid)
static void
- linux_resume (struct thread_resume *resume_info, size_t n)
+ linux_process_qsupported (const char *query)
{
-+ if (debug_threads) printf("linux_resume(%zd)\n", n);
-+
- struct thread_resume_array array = { resume_info, n };
- struct lwp_info *need_step_over = NULL;
- int any_pending;
-@@ -3484,6 +3533,8 @@ linux_resume (struct thread_resume *resume_info, size_t n)
-
- if (need_step_over)
- start_step_over (need_step_over);
-+
-+ if (debug_threads) printf("linux_resume() finished\n");
- }
-
- /* This function is called once per thread. We check the thread's
-@@ -3958,6 +4009,26 @@ linux_fetch_registers (struct regcache *regcache, int regno)
- #endif
- }
-
-+static void
-+genode_fetch_registers (struct regcache *regcache, int regno)
-+{
-+ unsigned long reg_content = 0;
-+
-+ if (regno == -1) {
-+ for (regno = 0; regno < the_low_target.num_regs; regno++) {
-+ if (genode_fetch_register(regno, ®_content) == 0)
-+ supply_register(regcache, regno, ®_content);
-+ else
-+ supply_register(regcache, regno, 0);
-+ }
-+ } else {
-+ if (genode_fetch_register(regno, ®_content) == 0)
-+ supply_register(regcache, regno, ®_content);
-+ else
-+ supply_register(regcache, regno, 0);
-+ }
-+}
-+
- void
- linux_store_registers (struct regcache *regcache, int regno)
- {
-@@ -3970,6 +4041,28 @@ linux_store_registers (struct regcache *regcache, int regno)
- #endif
- }
-
-+void
-+genode_store_registers (struct regcache *regcache, int regno)
-+{
-+ if (debug_threads) printf("genode_store_registers(): regno = %d\n", regno);
-+
-+ unsigned long reg_content = 0;
-+
-+ if (regno == -1) {
-+ for (regno = 0; regno < the_low_target.num_regs; regno++) {
-+ if (register_size(regno) <= sizeof(reg_content)) {
-+ collect_register(regcache, regno, ®_content);
-+ genode_store_register(regno, reg_content);
-+ }
-+ }
-+ } else {
-+ if (register_size(regno) <= sizeof(reg_content)) {
-+ collect_register(regcache, regno, ®_content);
-+ genode_store_register(regno, reg_content);
-+ }
-+ }
-+}
-+
-
- /* Copy LEN bytes from inferior's memory starting at MEMADDR
- to debugger memory starting at MYADDR. */
-@@ -4040,6 +4133,17 @@ linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
- return 0;
- }
-
-+static int
-+genode_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
-+{
-+ int i;
-+ if (debug_threads) printf("genode_read_memory(%llx, %p, %d)\n", memaddr, myaddr, len);
-+ if (myaddr)
-+ for (i = 0; i < len; i++)
-+ myaddr[i] = genode_read_memory_byte((void*)(unsigned long)memaddr + i);
-+ return 0;
-+}
-+
- /* Copy LEN bytes of data from debugger memory at MYADDR to inferior's
- memory at MEMADDR. On failure (cannot write to the inferior)
- returns the value of errno. */
-@@ -4121,6 +4225,34 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
- return 0;
- }
-
-+static int
-+genode_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
-+{
-+ int i;
-+
-+ if (debug_threads)
-+ printf("genode_write_memory(%llx, %p, %d)\n", memaddr, myaddr, len);
-+
-+ if (myaddr && (len > 0)) {
-+ if (debug_threads)
-+ {
-+ /* Dump up to four bytes. */
-+ unsigned int val = * (unsigned int *) myaddr;
-+ if (len == 1)
-+ val = val & 0xff;
-+ else if (len == 2)
-+ val = val & 0xffff;
-+ else if (len == 3)
-+ val = val & 0xffffff;
-+ fprintf (stderr, "Writing %0*x to 0x%08lx\n", 2 * ((len < 4) ? len : 4),
-+ val, (long)memaddr);
-+ }
-+ for (i = 0; i < len; i++)
-+ genode_write_memory_byte((void*)(unsigned long)memaddr + i, myaddr[i]);
-+ }
-+ return 0;
-+}
-+
- /* Non-zero if the kernel supports PTRACE_O_TRACEFORK. */
- static int linux_supports_tracefork_flag;
-
-@@ -4296,6 +4428,10 @@ linux_look_up_symbols (void)
- static void
- linux_request_interrupt (void)
- {
-+ /* FIXME: currently all threads get interrupted */
++#ifdef __GENODE__
++ /*
++ * 'qSupported' is the first command sent by GDB when attaching to the
++ * server, so when at this location, GDB has just (re-)attached itself.
++ */
+ genode_stop_all_threads();
-+
-+#if 0
- extern unsigned long signal_pid;
-
- if (!ptid_equal (cont_thread, null_ptid)
-@@ -4306,10 +4442,19 @@ linux_request_interrupt (void)
-
- lwp = get_thread_lwp (current_inferior);
- lwpid = lwpid_of (lwp);
-+#ifdef __GENODE__
-+ genode_interrupt_thread(lwpid);
-+#else
- kill_lwp (lwpid, SIGINT);
-+#endif /* __GENODE__ */
- }
- else
-- kill_lwp (signal_pid, SIGINT);
-+#ifdef __GENODE__
-+ genode_interrupt_thread(lwpid);
-+#else
-+ kill_lwp (lwpid, SIGINT);
-+#endif /* __GENODE__ */
+#endif
+ if (the_low_target.process_qsupported != NULL)
+ the_low_target.process_qsupported (query);
}
-
- /* Copy LEN bytes from inferior's auxiliary vector starting at OFFSET
-@@ -5108,28 +5253,28 @@ linux_emit_ops (void)
- }
-
+@@ -5110,26 +5161,56 @@ linux_emit_ops (void)
static struct target_ops linux_target_ops = {
-- linux_create_inferior,
-+ /*linux_create_inferior*/NULL,
+ linux_create_inferior,
linux_attach,
-- linux_kill,
-- linux_detach,
-- linux_mourn,
-- linux_join,
++#ifndef __GENODE__
+ linux_kill,
+ linux_detach,
+ linux_mourn,
+ linux_join,
++#else
+ genode_kill,
+ genode_detach,
-+ /*linux_mourn*/NULL,
-+ /*linux_join*/NULL,
++ NULL,
++ NULL,
++#endif
linux_thread_alive,
linux_resume,
linux_wait,
-- linux_fetch_registers,
-- linux_store_registers,
++#ifndef __GENODE__
+ linux_fetch_registers,
+ linux_store_registers,
++#else
+ genode_fetch_registers,
+ genode_store_registers,
++#endif
linux_prepare_to_access_memory,
linux_done_accessing_memory,
-- linux_read_memory,
-- linux_write_memory,
-- linux_look_up_symbols,
++#ifndef __GENODE__
+ linux_read_memory,
+ linux_write_memory,
++#else
+ genode_read_memory,
+ genode_write_memory,
-+ /*linux_look_up_symbols*/NULL,
++#endif
++#ifndef __GENODE__
+ linux_look_up_symbols,
++#else
++ NULL,
++#endif
linux_request_interrupt,
-- linux_read_auxv,
-+ /*linux_read_auxv*/NULL,
++#ifndef __GENODE__
+ linux_read_auxv,
++#else
++ NULL,
++#endif
linux_insert_point,
linux_remove_point,
-- linux_stopped_by_watchpoint,
-- linux_stopped_data_address,
-+ /*linux_stopped_by_watchpoint*/NULL,
-+ /*linux_stopped_data_address*/NULL,
++#ifndef __GENODE__
+ linux_stopped_by_watchpoint,
+ linux_stopped_data_address,
++#else
++ NULL,
++ NULL,
++#endif
#if defined(__UCLIBC__) && defined(HAS_NOMMU)
linux_read_offsets,
#else
-@@ -5140,32 +5285,32 @@ static struct target_ops linux_target_ops = {
+@@ -5140,6 +5221,7 @@ static struct target_ops linux_target_ops = {
#else
NULL,
#endif
-- linux_qxfer_spu,
-- hostio_last_error_from_errno,
-- linux_qxfer_osdata,
-- linux_xfer_siginfo,
-- linux_supports_non_stop,
-- linux_async,
-- linux_start_non_stop,
-- linux_supports_multi_process,
-+ /*linux_qxfer_spu*/NULL,
-+ /*hostio_last_error_from_errno*/NULL,
-+ /*linux_qxfer_osdata*/NULL,
-+ /*linux_xfer_siginfo*/NULL,
-+ /*linux_supports_non_stop*/NULL,
-+ /*linux_async*/NULL,
-+ /*linux_start_non_stop*/NULL,
-+ /*linux_supports_multi_process*/NULL,
++#ifndef __GENODE__
+ linux_qxfer_spu,
+ hostio_last_error_from_errno,
+ linux_qxfer_osdata,
+@@ -5148,13 +5230,28 @@ static struct target_ops linux_target_ops = {
+ linux_async,
+ linux_start_non_stop,
+ linux_supports_multi_process,
++#else
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++#endif
#ifdef USE_THREAD_DB
thread_db_handle_monitor_command,
#else
NULL,
#endif
-- linux_core_of_thread,
-- linux_process_qsupported,
-- linux_supports_tracepoints,
-- linux_read_pc,
-- linux_write_pc,
-- linux_thread_stopped,
-+ /*linux_core_of_thread*/NULL,
-+ /*linux_process_qsupported*/NULL,
-+ /*linux_supports_tracepoints*/NULL,
-+ /*linux_read_pc*/NULL,
-+ /*linux_write_pc*/NULL,
-+ /*linux_thread_stopped*/NULL,
- NULL,
-- linux_pause_all,
-- linux_unpause_all,
-- linux_cancel_breakpoints,
-- linux_stabilize_threads,
-- linux_install_fast_tracepoint_jump_pad,
-- linux_emit_ops
-+ /*linux_pause_all*/NULL,
-+ /*linux_unpause_all*/NULL,
-+ /*linux_cancel_breakpoints*/NULL,
-+ /*linux_stabilize_threads*/NULL,
-+ /*linux_install_fast_tracepoint_jump_pad*/NULL,
-+ /*linux_emit_ops*/NULL
++#ifndef __GENODE__
+ linux_core_of_thread,
++#else
++ NULL,
++#endif
+ linux_process_qsupported,
++#ifndef __GENODE__
+ linux_supports_tracepoints,
+ linux_read_pc,
+ linux_write_pc,
+@@ -5166,6 +5263,19 @@ static struct target_ops linux_target_ops = {
+ linux_stabilize_threads,
+ linux_install_fast_tracepoint_jump_pad,
+ linux_emit_ops
++#else
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL
++#endif
};
static void
-@@ -5181,11 +5326,14 @@ linux_init_signals ()
- void
- initialize_low (void)
- {
-+#if 0
- struct sigaction sigchld_action;
- memset (&sigchld_action, 0, sizeof (sigchld_action));
-+#endif
- set_target_ops (&linux_target_ops);
+@@ -5187,7 +5297,9 @@ initialize_low (void)
set_breakpoint_data (the_low_target.breakpoint,
the_low_target.breakpoint_len);
-+#if 0
linux_init_signals ();
++#ifndef __GENODE__
linux_test_for_tracefork ();
- #ifdef HAVE_LINUX_REGSETS
-@@ -5198,4 +5346,5 @@ initialize_low (void)
- sigemptyset (&sigchld_action.sa_mask);
- sigchld_action.sa_flags = SA_RESTART;
- sigaction (SIGCHLD, &sigchld_action, NULL);
+#endif
- }
+ #ifdef HAVE_LINUX_REGSETS
+ for (num_regsets = 0; target_regsets[num_regsets].size >= 0; num_regsets++)
+ ;
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
-index 6635bc6..ae172bd 100644
+index d449e1b..0bbcbfd 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
-@@ -21,7 +21,7 @@
- #include
+@@ -22,7 +22,9 @@
#endif
--#include "gdb_proc_service.h"
-+//#include "gdb_proc_service.h"
+ #include
++#ifndef __GENODE__
+ #include "gdb_proc_service.h"
++#endif
#ifdef HAVE_LINUX_REGSETS
typedef void (*regset_fill_func) (struct regcache *, void *);
-@@ -56,6 +56,9 @@ struct process_info_private
- /* libthread_db-specific additions. Not NULL if this process has loaded
- thread_db, and it is active. */
- struct thread_db *thread_db;
-+
-+ /* Genode-specific additions */
-+ void *gdb_stub_thread;
- };
-
- struct lwp_info;
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
-index 69c6b57..cffa803 100644
+index 82dcf83..e98e3bd 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
-@@ -28,8 +28,15 @@
+@@ -28,8 +28,17 @@
#include "i386-xstate.h"
#include "elf/common.h"
--#include "gdb_proc_service.h"
--
-+//#include "gdb_proc_service.h"
-+
++#ifndef __GENODE__
+ #include "gdb_proc_service.h"
++#endif
+
+#ifdef __GENODE__
+/* Defined in auto-generated file i386.c. */
+void init_registers_i386 (void);
@@ -564,7 +405,7 @@ index 69c6b57..cffa803 100644
/* Defined in auto-generated file i386-linux.c. */
void init_registers_i386_linux (void);
/* Defined in auto-generated file amd64-linux.c. */
-@@ -40,11 +47,22 @@ void init_registers_i386_avx_linux (void);
+@@ -40,10 +49,24 @@ void init_registers_i386_avx_linux (void);
void init_registers_amd64_avx_linux (void);
/* Defined in auto-generated file i386-mmx-linux.c. */
void init_registers_i386_mmx_linux (void);
@@ -574,36 +415,38 @@ index 69c6b57..cffa803 100644
/* Backward compatibility for gdb without XML support. */
+#ifdef __GENODE__
++
+static const char *xmltarget_i386_linux_no_xml = "@\
+i386\
+";
-
++
+#ifdef __x86_64__
+static const char *xmltarget_amd64_linux_no_xml = "@\
+i386:x86-64\
+";
+#endif
++
+#else
+
static const char *xmltarget_i386_linux_no_xml = "@\
i386\
- GNU/Linux\
-@@ -56,8 +74,15 @@ static const char *xmltarget_amd64_linux_no_xml = "@\
- GNU/Linux\
+@@ -57,7 +80,15 @@ static const char *xmltarget_amd64_linux_no_xml = "@\
";
#endif
-+#endif /* __GENODE__ */
++#endif /* __GENODE__ */
++
+#ifdef __GENODE__
+#ifndef __x86_64__
+#include "i386.h"
+#endif /* __x86_64__ */
+#else
#include
-+#endif /* __GENODE__ */
++#endif
#include
#include
#include
-@@ -273,8 +298,10 @@ x86_fill_gregset (struct regcache *regcache, void *buf)
+@@ -273,8 +304,10 @@ x86_fill_gregset (struct regcache *regcache, void *buf)
for (i = 0; i < I386_NUM_REGS; i++)
collect_register (regcache, i, ((char *) buf) + i386_regmap[i]);
@@ -614,7 +457,7 @@ index 69c6b57..cffa803 100644
}
static void
-@@ -295,8 +322,10 @@ x86_store_gregset (struct regcache *regcache, const void *buf)
+@@ -295,8 +328,10 @@ x86_store_gregset (struct regcache *regcache, const void *buf)
for (i = 0; i < I386_NUM_REGS; i++)
supply_register (regcache, i, ((char *) buf) + i386_regmap[i]);
@@ -625,7 +468,7 @@ index 69c6b57..cffa803 100644
}
static void
-@@ -414,7 +443,15 @@ x86_set_pc (struct regcache *regcache, CORE_ADDR pc)
+@@ -414,7 +449,15 @@ x86_set_pc (struct regcache *regcache, CORE_ADDR pc)
}
}
@@ -641,180 +484,91 @@ index 69c6b57..cffa803 100644
#define x86_breakpoint_len 1
static int
-@@ -2576,7 +2613,7 @@ struct linux_target_ops the_low_target =
+@@ -423,7 +466,7 @@ x86_breakpoint_at (CORE_ADDR pc)
+ unsigned char c;
+
+ (*the_target->read_memory) (pc, &c, 1);
+- if (c == 0xCC)
++ if (c == x86_breakpoint[0])
+ return 1;
+
+ return 0;
+@@ -2561,7 +2604,11 @@ struct linux_target_ops the_low_target =
+ x86_breakpoint,
+ x86_breakpoint_len,
+ NULL,
++#ifndef __GENODE__
+ 1,
++#else
++ 0, /* With the HLT instruction, the PC does not get incremented */
++#endif
+ x86_breakpoint_at,
+ x86_insert_point,
+ x86_remove_point,
+@@ -2576,7 +2623,11 @@ struct linux_target_ops the_low_target =
x86_siginfo_fixup,
x86_linux_new_process,
x86_linux_new_thread,
-- x86_linux_prepare_to_resume,
-+ /*x86_linux_prepare_to_resume*/NULL,
++#ifndef __GENODE__
+ x86_linux_prepare_to_resume,
++#else
++ NULL,
++#endif
x86_linux_process_qsupported,
x86_supports_tracepoints,
x86_get_thread_area,
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
-index 650ddf8..728da30 100644
+index 650ddf8..7a53e77 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
-@@ -18,11 +18,14 @@
- You should have received a copy of the GNU General Public License
- along with this program. If not, see . */
-
-+#include "genode-low.h"
-+
+@@ -21,6 +21,12 @@
#include "server.h"
#include "terminal.h"
#include "target.h"
- #include
- #include
-+#include
- #if HAVE_SYS_IOCTL_H
- #include
- #endif
-@@ -171,7 +174,6 @@ handle_accept_event (int err, gdb_client_data client_data)
-
- #ifndef USE_WIN32API
- close (listen_desc); /* No longer need this */
--
- signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply
- exits when the remote side dies. */
- #else
-@@ -186,6 +188,12 @@ handle_accept_event (int err, gdb_client_data client_data)
-
- enable_async_notification (remote_desc);
-
-+ /* stop all threads */
-+ genode_stop_all_threads();
-+
-+ /* find all existing threads and tell gdbserver about it */
-+ genode_detect_all_threads();
-+
- /* Register the event loop handler. */
- add_file_handler (remote_desc, handle_serial_event, NULL);
-
-@@ -280,6 +288,14 @@ remote_open (char *name)
-
- /* Register the event loop handler. */
- add_file_handler (remote_desc, handle_serial_event, NULL);
+
+#ifdef __GENODE__
-+ /* FIXME: find better place */
-+ genode_stop_all_threads();
-+ /* find all existing threads and tell gdbserver about it */
-+ genode_detect_all_threads();
++#include
++#include "genode-low.h"
+#endif
+
- #endif /* USE_WIN32API */
- }
- else
-@@ -857,6 +873,68 @@ input_interrupt (int unused)
- }
- }
+ #include
+ #include
+ #if HAVE_SYS_IOCTL_H
+@@ -106,8 +112,10 @@ struct sym_cache
-+
-+ptid_t
-+genode_wait_for_signal_or_gdb_interrupt (struct target_waitstatus *status)
-+{
-+ printf("genode_wait_for_signal_or_gdb_interrupt\n");
-+
-+ ptid_t event_ptid;
-+
-+ fd_set readset;
-+
-+ FD_ZERO (&readset);
-+ FD_SET (remote_desc, &readset);
-+ FD_SET (genode_signal_fd(), &readset);
-+
-+ while(1) {
-+ if (select ((remote_desc > genode_signal_fd() ? remote_desc : genode_signal_fd()) + 1, &readset, 0, 0, NULL) > 0)
-+ {
-+ if (debug_threads) printf("select() returned\n");
-+ int cc;
-+ char c = 0;
-+ if (FD_ISSET(remote_desc, &readset)) {
-+ /* received input from GDB */
-+ cc = read (remote_desc, &c, 1);
-+
-+ if (cc == 1 && c == '\003' && current_inferior != NULL) {
-+ (*the_target->request_interrupt) ();
-+ event_ptid = current_inferior->entry.id;
-+ status->kind = TARGET_WAITKIND_STOPPED;
-+ status->value.sig = TARGET_SIGNAL_INT;
-+ return event_ptid;
-+ } else
-+ {
-+ fprintf (stderr, "input_interrupt, count = %d c = %d ('%c')\n",
-+ cc, c, c);
-+ }
-+ } else {
-+ /* received a signal */
-+ unsigned long sig;
-+ read(genode_signal_fd(), &sig, sizeof(sig));
-+ printf("received signal %ld\n", sig);
-+ if (current_inferior == NULL) continue;
-+
-+ event_ptid.pid = GENODE_LWP_BASE;
-+ event_ptid.tid = 0;
-+ genode_stop_all_threads();
-+
-+ if (sig > 0) {
-+ event_ptid.lwp = sig;
-+ status->kind = TARGET_WAITKIND_STOPPED;
-+ status->value.sig = TARGET_SIGNAL_TRAP;
-+ } else {
-+ event_ptid.lwp = genode_find_segfault_lwpid();
-+ status->kind = TARGET_WAITKIND_STOPPED;
-+ status->value.sig = TARGET_SIGNAL_SEGV;
-+ }
-+ return event_ptid;
-+ }
-+ }
-+ }
-+}
-+
-+
- /* Check if the remote side sent us an interrupt request (^C). */
- void
- check_remote_input_interrupt_request (void)
+ int remote_debug = 0;
+ struct ui_file *gdb_stdlog;
+-
+-static gdb_fildes_t remote_desc = INVALID_DESCRIPTOR;
++#ifndef __GENODE__
++static
++#endif
++gdb_fildes_t remote_desc = INVALID_DESCRIPTOR;
+ static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
+
+ /* FIXME headerize? */
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
-index 2f4484f..79c89d4 100644
+index 2f4484f..124c98d 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
-@@ -18,8 +18,13 @@
- You should have received a copy of the GNU General Public License
- along with this program. If not, see . */
+@@ -20,6 +20,11 @@
-+
-+#include "genode-low.h"
-+
#include "server.h"
++#ifdef __GENODE__
++#include "genode-low.h"
+#include "linux-low.h"
++#endif
+
#if HAVE_UNISTD_H
#include
#endif
-@@ -47,7 +52,7 @@ static char **program_argv, **wrapper_argv;
-
- /* Enable miscellaneous debugging output. The name is historical - it
- was originally used to debug LinuxThreads support. */
--int debug_threads;
-+int debug_threads = 0;
-
- /* Enable debugging of h/w breakpoint/watchpoint support. */
- int debug_hw_points;
-@@ -1740,6 +1745,7 @@ static void gdb_wants_all_threads_stopped (void);
- void
- handle_v_cont (char *own_buf)
- {
-+ if (debug_threads) printf("handle_v_cont()\n");
- char *p, *q;
- int n = 0, i = 0;
- struct thread_resume *resume_info;
-@@ -2055,11 +2061,11 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
+@@ -2055,11 +2060,11 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
return;
}
}
-
-+#if 0
++#ifndef __GENODE__
if (strncmp (own_buf, "vFile:", 6) == 0
&& handle_vFile (own_buf, packet_len, new_packet_len))
return;
@@ -823,120 +577,43 @@ index 2f4484f..79c89d4 100644
if (strncmp (own_buf, "vAttach;", 8) == 0)
{
if (!multi_process && target_running ())
-@@ -2114,6 +2120,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
- static void
- myresume (char *own_buf, int step, int sig)
- {
-+ if (debug_threads) printf("myresume()\n");
- struct thread_resume resume_info[2];
- int n = 0;
- int valid_cont_thread;
-@@ -2250,6 +2257,7 @@ gdb_reattached_process (struct inferior_list_entry *entry)
- static void
- handle_status (char *own_buf)
- {
-+ if (debug_threads) printf("handle_status()\n");
- /* GDB is connected, don't forward events to the target anymore. */
- for_each_inferior (&all_processes, gdb_reattached_process);
-
-@@ -2286,7 +2294,7 @@ handle_status (char *own_buf)
- strcpy (own_buf, "W00");
- }
- }
--
-+#if 0
- static void
- gdbserver_version (void)
- {
-@@ -2328,7 +2336,7 @@ gdbserver_show_disableable (FILE *stream)
- "T stop reply packet\n"
- " threads \tAll of the above\n");
- }
--
-+#endif
-
- #undef require_running
- #define require_running(BUF) \
-@@ -2449,8 +2457,9 @@ join_inferiors_callback (struct inferior_list_entry *entry)
+@@ -2449,7 +2454,11 @@ join_inferiors_callback (struct inferior_list_entry *entry)
}
int
--main (int argc, char *argv[])
-+gdbserver_main(char *port, void *gdb_stub_thread)
++#ifdef __GENODE__
++gdbserver_main (int argc, char *argv[])
++#else
+ main (int argc, char *argv[])
++#endif
{
-+#if 0
int bad_attach;
int pid;
- char *arg_end, *port;
-@@ -2584,7 +2593,7 @@ main (int argc, char *argv[])
- gdbserver_usage (stderr);
- exit (1);
- }
--
-+#endif
- initialize_inferiors ();
- initialize_async_io ();
- initialize_low ();
-@@ -2594,6 +2603,7 @@ main (int argc, char *argv[])
- own_buf = xmalloc (PBUFSIZ + 1);
- mem_buf = xmalloc (PBUFSIZ);
-
-+#if 0
- if (pid == 0 && *next_arg != NULL)
- {
- int i, n;
-@@ -2647,6 +2657,12 @@ main (int argc, char *argv[])
- fprintf (stderr, "No program to debug. GDBserver exiting.\n");
- exit (1);
- }
-+#endif
-+
-+#ifdef __GENODE__
-+ /* wait until the target's main thread is ready */
-+ genode_wait_for_target_main_thread();
-+#endif
-
- while (1)
- {
-@@ -2655,6 +2671,15 @@ main (int argc, char *argv[])
- /* Be sure we're out of tfind mode. */
- current_traceframe = -1;
-
-+#ifdef __GENODE__
-+ /* attach to child */
-+ myattach(GENODE_LWP_BASE);
-+ signal_pid = GENODE_LWP_BASE;
-+ struct process_info *pi = current_process();
-+ struct process_info_private *pip = pi->private;
-+ pip->gdb_stub_thread = gdb_stub_thread;
-+#endif
-+
- remote_open (port);
-
- if (setjmp (toplevel) != 0)
-@@ -2755,6 +2780,7 @@ process_serial_event (void)
+@@ -2754,6 +2763,9 @@ process_serial_event (void)
+ response_needed = 1;
i = 0;
++#ifdef __GENODE
++ if (debug_threads) printf("GDB command = %s\n", own_buf);
++#endif
ch = own_buf[i++];
-+ //if (debug_threads) printf("GDB command = %s\n", own_buf);
switch (ch)
{
- case 'q':
-@@ -2844,7 +2870,9 @@ process_serial_event (void)
+@@ -2844,7 +2856,9 @@ process_serial_event (void)
gone. */
for_each_inferior (&all_processes,
join_inferiors_callback);
-+#if 0
++#ifndef __GENODE__
exit (0);
+#endif
}
}
break;
-@@ -3076,7 +3104,11 @@ process_serial_event (void)
+@@ -3076,7 +3090,11 @@ process_serial_event (void)
return 0;
}
else
-+#if 0
++#ifndef __GENODE__
exit (0);
+#else
+ return 0;
@@ -944,12 +621,14 @@ index 2f4484f..79c89d4 100644
case 'T':
{
-@@ -3140,14 +3172,14 @@ process_serial_event (void)
+@@ -3140,14 +3158,16 @@ process_serial_event (void)
own_buf[0] = '\0';
break;
}
-
++#ifdef __GENODE__
+ if (debug_threads) printf("GDBserver response = %s\n", own_buf);
++#endif
if (new_packet_len != -1)
putpkt_binary (own_buf, new_packet_len);
else
@@ -957,11 +636,11 @@ index 2f4484f..79c89d4 100644
response_needed = 0;
-
-+#if 0
++#ifndef __GENODE__
if (!extended_protocol && have_ran && !target_running ())
{
/* In non-stop, defer exiting until GDB had a chance to query
-@@ -3159,7 +3191,7 @@ process_serial_event (void)
+@@ -3159,7 +3179,7 @@ process_serial_event (void)
exit (0);
}
}
diff --git a/repos/ports/src/app/gdb_monitor/genode_child_resources.h b/repos/ports/src/app/gdb_monitor/genode_child_resources.h
new file mode 100644
index 0000000000..a0da1c84e7
--- /dev/null
+++ b/repos/ports/src/app/gdb_monitor/genode_child_resources.h
@@ -0,0 +1,46 @@
+/*
+ * \brief Genode child resources provided to GDB monitor
+ * \author Christian Prochaska
+ * \date 2011-03-10
+ */
+
+/*
+ * Copyright (C) 2011-2016 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 _GENODE_CHILD_RESOURCES_H_
+#define _GENODE_CHILD_RESOURCES_H_
+
+#include "cpu_session_component.h"
+#include "region_map_component.h"
+
+namespace Gdb_monitor { class Genode_child_resources; }
+
+class Gdb_monitor::Genode_child_resources
+{
+
+ private:
+
+ Cpu_session_component *_cpu_session_component = 0;
+ Region_map_component *_region_map_component = 0;
+
+ public:
+
+ void cpu_session_component(Cpu_session_component *cpu_session_component)
+ {
+ _cpu_session_component = cpu_session_component;
+ }
+
+ void region_map_component(Region_map_component *region_map_component)
+ {
+ _region_map_component = region_map_component;
+ }
+
+ Cpu_session_component *cpu_session_component() { return _cpu_session_component; }
+ Region_map_component *region_map_component() { return _region_map_component; }
+};
+
+#endif /* _GENODE_CHILD_RESOURCES_H_ */
diff --git a/repos/ports/src/app/gdb_monitor/main.cc b/repos/ports/src/app/gdb_monitor/main.cc
index 156b5ad19d..e6bc869c19 100644
--- a/repos/ports/src/app/gdb_monitor/main.cc
+++ b/repos/ports/src/app/gdb_monitor/main.cc
@@ -5,29 +5,12 @@
*/
/*
- * Copyright (C) 2010-2013 Genode Labs GmbH
+ * Copyright (C) 2010-2016 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.
*/
-#include
-#include
-#include
-
-#include
-
-#include
-
-#include
-#include
-#include
-
-#include "app_child.h"
-#include "rom.h"
-
-using namespace Genode;
-using namespace Gdb_monitor;
/*
* Suppress messages of libc dummy functions
@@ -36,92 +19,21 @@ extern "C" int _sigaction() { return -1; }
extern "C" int getpid() { return -1; }
extern "C" int sigprocmask() { return -1; }
extern "C" int _sigprocmask() { return -1; }
+extern "C" int sigsuspend() { return -1; }
+/*
+ * version.c
+ */
+extern "C" const char version[] = "7.3.1";
+extern "C" const char host_name[] = "";
+
+
+extern "C" int gdbserver_main(int argc, const char *argv[]);
int main()
{
- /* look for dynamic linker */
- Dataspace_capability ldso_ds;
- try {
- Rom_connection ldso_rom("ld.lib.so");
- ldso_ds = clone_rom(ldso_rom.dataspace());
- } catch (...) {
- PDBG("ld.lib.so not found");
- }
+ int argc = 3;
+ const char *argv[] = { "gdbserver", "/dev/terminal", "target", 0 };
- /* extract target filename from config file */
-
- static char filename[32] = "";
-
- try {
- config()->xml_node().sub_node("target").attribute("name").value(filename, sizeof(filename));
- } catch (Xml_node::Nonexistent_sub_node) {
- PERR("Error: Missing '' sub node.");
- return -1;
- } catch (Xml_node::Nonexistent_attribute) {
- PERR("Error: Missing 'name' attribute of '' sub node.");
- return -1;
- }
-
- /* extract target node from config file */
- Xml_node target_node = config()->xml_node().sub_node("target");
-
- /*
- * preserve the configured amount of memory for gdb_monitor and give the
- * remainder to the child
- */
- Number_of_bytes preserved_ram_quota = 0;
- try {
- Xml_node preserve_node = config()->xml_node().sub_node("preserve");
- if (preserve_node.attribute("name").has_value("RAM"))
- preserve_node.attribute("quantum").value(&preserved_ram_quota);
- else
- throw Xml_node::Exception();
- } catch (...) {
- PERR("Error: could not find a valid config node");
- return -1;
- }
-
- Number_of_bytes ram_quota = env()->ram_session()->avail() - preserved_ram_quota;
-
- /* start the application */
- char *unique_name = filename;
- Capability file_cap;
- try {
- static Rom_connection rom(filename, unique_name);
- file_cap = rom.dataspace();
- } catch (Rom_connection::Rom_connection_failed) {
- Genode::printf("Error: Could not access file \"%s\" from ROM service.\n", filename);
- return 0;
- }
-
- /* copy ELF image to writable dataspace */
- Genode::size_t elf_size = Dataspace_client(file_cap).size();
- Capability elf_cap = clone_rom(file_cap);
-
- /* create ram session for child with some of our own quota */
- static Ram_connection ram;
- ram.ref_account(env()->ram_session_cap());
- env()->ram_session()->transfer_quota(ram.cap(), (Genode::size_t)ram_quota - elf_size);
-
- /* cap session for allocating capabilities for parent interfaces */
- static Cap_connection cap_session;
-
- static Service_registry parent_services;
-
- enum { CHILD_ROOT_EP_STACK = 4096 };
- static Rpc_entrypoint child_root_ep(&cap_session, CHILD_ROOT_EP_STACK,
- "child_root_ep");
-
- new (env()->heap()) App_child(unique_name,
- elf_cap,
- ldso_ds,
- ram.cap(),
- &cap_session,
- &parent_services,
- &child_root_ep,
- target_node);
- sleep_forever();
-
- return 0;
+ return gdbserver_main(argc, argv);
}
diff --git a/repos/ports/src/app/gdb_monitor/pd_session_component.h b/repos/ports/src/app/gdb_monitor/pd_session_component.h
index e746539657..d62ecc2183 100644
--- a/repos/ports/src/app/gdb_monitor/pd_session_component.h
+++ b/repos/ports/src/app/gdb_monitor/pd_session_component.h
@@ -18,9 +18,15 @@
#include
#include
-using namespace Genode;
+/* GDB monitor includes */
+#include "region_map_component.h"
-class Pd_session_component : public Rpc_object
+namespace Gdb_monitor {
+ class Pd_session_component;
+ using namespace Genode;
+}
+
+class Gdb_monitor::Pd_session_component : public Rpc_object
{
private:
@@ -41,9 +47,9 @@ class Pd_session_component : public Rpc_object
Dataspace_pool &managed_ds_map)
:
_ep(ep), _pd(binary_name),
- _address_space(_ep, managed_ds_map, _pd.address_space()),
- _stack_area (_ep, managed_ds_map, _pd.stack_area()),
- _linker_area (_ep, managed_ds_map, _pd.linker_area())
+ _address_space(_ep, managed_ds_map, _pd, _pd.address_space()),
+ _stack_area (_ep, managed_ds_map, _pd, _pd.stack_area()),
+ _linker_area (_ep, managed_ds_map, _pd, _pd.linker_area())
{
_ep.manage(this);
}
@@ -54,11 +60,12 @@ class Pd_session_component : public Rpc_object
}
/**
- * Accessor used to let the GDB stub thread access the PD's address
+ * Accessor used to let the GDB monitor access the PD's address
* space
*/
Region_map_component ®ion_map() { return _address_space; }
+ Pd_session_capability core_pd_cap() { return _pd.cap(); }
/**************************
** Pd_session interface **
diff --git a/repos/ports/src/app/gdb_monitor/ram_root.h b/repos/ports/src/app/gdb_monitor/ram_root.h
index 30216861bf..2478767a1c 100644
--- a/repos/ports/src/app/gdb_monitor/ram_root.h
+++ b/repos/ports/src/app/gdb_monitor/ram_root.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2006-2013 Genode Labs GmbH
+ * Copyright (C) 2006-2016 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.
@@ -18,31 +18,30 @@
#include "ram_session_component.h"
-namespace Genode {
+namespace Gdb_monitor { class Ram_root; }
- class Ram_root : public Root_component
- {
- protected:
+class Gdb_monitor::Ram_root : public Root_component
+{
+ protected:
- Ram_session_component *_create_session(const char *args)
- {
- return new (md_alloc())
- Ram_session_component(args);
- }
+ Ram_session_component *_create_session(const char *args)
+ {
+ return new (md_alloc())
+ Ram_session_component(args);
+ }
- public:
+ public:
- /**
- * Constructor
- *
- * \param session_ep entry point for managing ram session objects
- * \param md_alloc meta-data allocator to be used by root component
- */
- Ram_root(Rpc_entrypoint *session_ep,
- Allocator *md_alloc)
- : Root_component(session_ep, md_alloc)
- { }
- };
-}
+ /**
+ * Constructor
+ *
+ * \param session_ep entry point for managing ram session objects
+ * \param md_alloc meta-data allocator to be used by root component
+ */
+ Ram_root(Rpc_entrypoint *session_ep,
+ Allocator *md_alloc)
+ : Root_component(session_ep, md_alloc)
+ { }
+};
#endif /* _RAM_ROOT_H_ */
diff --git a/repos/ports/src/app/gdb_monitor/ram_session_component.cc b/repos/ports/src/app/gdb_monitor/ram_session_component.cc
index 538e1a541e..d5c18ab76c 100644
--- a/repos/ports/src/app/gdb_monitor/ram_session_component.cc
+++ b/repos/ports/src/app/gdb_monitor/ram_session_component.cc
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -18,7 +18,7 @@
#include "ram_session_component.h"
using namespace Genode;
-
+using namespace Gdb_monitor;
Ram_session_component::Ram_session_component(const char *args)
: _parent_ram_session(env()->parent()->session(args))
diff --git a/repos/ports/src/app/gdb_monitor/ram_session_component.h b/repos/ports/src/app/gdb_monitor/ram_session_component.h
index b69b6011f6..69fc7002cb 100644
--- a/repos/ports/src/app/gdb_monitor/ram_session_component.h
+++ b/repos/ports/src/app/gdb_monitor/ram_session_component.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2006-2013 Genode Labs GmbH
+ * Copyright (C) 2006-2016 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.
@@ -18,9 +18,13 @@
#include
#include
-using namespace Genode;
+namespace Gdb_monitor
+{
+ class Ram_session_component;
+ using namespace Genode;
+}
-class Ram_session_component : public Rpc_object
+class Gdb_monitor::Ram_session_component : public Rpc_object
{
private:
diff --git a/repos/ports/src/app/gdb_monitor/region_map_component.cc b/repos/ports/src/app/gdb_monitor/region_map_component.cc
index 24948215dc..ccb7eb5256 100644
--- a/repos/ports/src/app/gdb_monitor/region_map_component.cc
+++ b/repos/ports/src/app/gdb_monitor/region_map_component.cc
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -15,19 +15,19 @@
#include
#include
#include
+#include
/* local includes */
#include "region_map_component.h"
static bool const verbose = false;
-using namespace Gdb_monitor;
-using namespace Genode;
-
-/**************************
+/**************************************
** Region map component **
- **************************/
+ **************************************/
+
+using namespace Gdb_monitor;
Region_map_component::Region *Region_map_component::find_region(void *local_addr, addr_t *offset_in_region)
{
@@ -140,13 +140,16 @@ Dataspace_capability Region_map_component::dataspace()
Region_map_component::Region_map_component(Rpc_entrypoint &ep,
Dataspace_pool &managed_ds_map,
+ Pd_session_capability pd,
Capability parent_region_map)
:
_ep(ep),
+ _pd(pd),
_parent_region_map(parent_region_map),
_managed_ds_map(managed_ds_map)
{
_ep.manage(this);
+
if (verbose)
PDBG("Region_map_component()");
}
diff --git a/repos/ports/src/app/gdb_monitor/region_map_component.h b/repos/ports/src/app/gdb_monitor/region_map_component.h
index 7e6c3c1410..7c63127e4d 100644
--- a/repos/ports/src/app/gdb_monitor/region_map_component.h
+++ b/repos/ports/src/app/gdb_monitor/region_map_component.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2013 Genode Labs GmbH
+ * Copyright (C) 2006-2016 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.
@@ -16,8 +16,9 @@
#define _REGION_MAP_COMPONENT_H_
/* Genode includes */
-#include
#include
+#include
+#include
/* GDB monitor includes */
#include "dataspace_object.h"
@@ -32,6 +33,8 @@ namespace Gdb_monitor {
Rpc_entrypoint &_ep;
+ Pd_session_capability _pd;
+
Genode::Region_map_client _parent_region_map;
public:
@@ -75,8 +78,9 @@ namespace Gdb_monitor {
/**
* Constructor
*/
- Region_map_component(Rpc_entrypoint &ep,
- Dataspace_pool &managed_ds_map,
+ Region_map_component(Rpc_entrypoint &ep,
+ Dataspace_pool &managed_ds_map,
+ Pd_session_capability pd,
Capability parent_region_map);
~Region_map_component();
diff --git a/repos/ports/src/app/gdb_monitor/rom.h b/repos/ports/src/app/gdb_monitor/rom.h
index 1df8a60226..1a489aada9 100644
--- a/repos/ports/src/app/gdb_monitor/rom.h
+++ b/repos/ports/src/app/gdb_monitor/rom.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -16,111 +16,118 @@
/* Genode includes */
#include
+#include
#include
-#include
+#include
#include
-namespace Gdb_monitor {
-
+namespace Gdb_monitor
+{
+ class Rom_session_component;
+ class Rom_root;
+ class Rom_service;
using namespace Genode;
-
- /**
- * Clone a ROM dataspace in RAM
- */
- Capability clone_rom(Capability rom_cap)
- {
- Genode::size_t rom_size = Dataspace_client(rom_cap).size();
- Capability clone_cap = env()->ram_session()->alloc(rom_size);
-
- if (!clone_cap.valid()) {
- PERR("%s: memory allocation for cloned dataspace failed", __func__);
- return Capability();
- }
-
- void *rom = env()->rm_session()->attach(rom_cap);
- void *clone = env()->rm_session()->attach(clone_cap);
-
- memcpy(clone, rom, rom_size);
-
- env()->rm_session()->detach(rom);
- env()->rm_session()->detach(clone);
-
- return clone_cap;
- }
-
-
- /**
- * ROM session backed by RAM dataspace copy of original ROM
- */
- class Rom_session_component : public Rpc_object
- {
- private:
-
- Capability _clone_cap;
-
- public:
-
- Rom_session_component(char const *filename)
- : _clone_cap(clone_rom(Rom_connection(filename).dataspace()))
- { }
-
- ~Rom_session_component() { env()->ram_session()->free(_clone_cap); }
-
- Capability dataspace()
- {
- return static_cap_cast(
- static_cap_cast(_clone_cap));
- }
-
- void release() { }
-
- void sigh(Genode::Signal_context_capability) { }
- };
-
-
- class Rom_root : public Root_component
- {
- protected:
-
- Rom_session_component *_create_session(char const *args)
- {
- enum { FILENAME_MAX_LEN = 128 };
- char filename[FILENAME_MAX_LEN];
- Arg_string::find_arg(args, "filename").string(filename, sizeof(filename), "");
-
- return new (md_alloc()) Rom_session_component(filename);
- }
-
- public:
-
- Rom_root(Rpc_entrypoint *session_ep,
- Allocator *md_alloc)
- : Root_component(session_ep, md_alloc)
- { }
- };
-
-
- class Rom_service : public Service
- {
- private:
-
- Rom_root _root;
-
- public:
-
- Rom_service(Rpc_entrypoint *entrypoint,
- Allocator *md_alloc)
- : Service("ROM"), _root(entrypoint, md_alloc)
- { }
-
- Capability session(char const *args, Affinity const &affinity) {
- return _root.session(args, affinity); }
-
- void upgrade(Capability, char const *) { }
-
- void close(Capability cap) { _root.close(cap); }
- };
}
+/**
+ * Clone a ROM dataspace in RAM
+ */
+static Genode::Capability
+clone_rom(Genode::Capability rom_cap)
+{
+ using namespace Genode;
+
+ Genode::size_t rom_size = Dataspace_client(rom_cap).size();
+ Capability clone_cap = env()->ram_session()->alloc(rom_size);
+
+ if (!clone_cap.valid()) {
+ PERR("%s: memory allocation for cloned dataspace failed", __func__);
+ return Capability();
+ }
+
+ void *rom = env()->rm_session()->attach(rom_cap);
+ void *clone = env()->rm_session()->attach(clone_cap);
+
+ Genode::memcpy(clone, rom, rom_size);
+
+ env()->rm_session()->detach(rom);
+ env()->rm_session()->detach(clone);
+
+ return clone_cap;
+}
+
+
+/**
+ * ROM session backed by RAM dataspace copy of original ROM
+ */
+class Gdb_monitor::Rom_session_component : public Rpc_object
+{
+ private:
+
+ Capability _clone_cap;
+
+ public:
+
+ Rom_session_component(char const *filename)
+ : _clone_cap(clone_rom(Rom_connection(filename).dataspace()))
+ { }
+
+ ~Rom_session_component() { env()->ram_session()->free(_clone_cap); }
+
+ Capability dataspace()
+ {
+ return static_cap_cast(
+ static_cap_cast(_clone_cap));
+ }
+
+ void release() { }
+
+ void sigh(Genode::Signal_context_capability) { }
+};
+
+
+class Gdb_monitor::Rom_root : public Root_component
+{
+ protected:
+
+ Rom_session_component *_create_session(char const *args)
+ {
+ enum { FILENAME_MAX_LEN = 128 };
+ char filename[FILENAME_MAX_LEN];
+ Arg_string::find_arg(args, "filename").string(filename, sizeof(filename), "");
+
+ return new (md_alloc()) Rom_session_component(filename);
+ }
+
+ public:
+
+ Rom_root(Rpc_entrypoint *session_ep,
+ Allocator *md_alloc)
+ : Root_component(session_ep, md_alloc)
+ { }
+};
+
+
+class Gdb_monitor::Rom_service : public Service
+{
+ private:
+
+ Rom_root _root;
+
+ public:
+
+ Rom_service(Rpc_entrypoint *entrypoint,
+ Allocator *md_alloc)
+ : Service("ROM"), _root(entrypoint, md_alloc)
+ { }
+
+ Capability session(char const *args, Affinity const &affinity) {
+ return _root.session(args, affinity); }
+
+ void upgrade(Capability, char const *) { }
+
+ void close(Capability cap) { _root.close(cap); }
+};
+
#endif /* _ROM_H_ */
diff --git a/repos/ports/src/app/gdb_monitor/siginfo.patch b/repos/ports/src/app/gdb_monitor/siginfo.patch
new file mode 100644
index 0000000000..673b841850
--- /dev/null
+++ b/repos/ports/src/app/gdb_monitor/siginfo.patch
@@ -0,0 +1,279 @@
+From 0bcbef9314d6679d1fbbb0114683d06de0196623 Mon Sep 17 00:00:00 2001
+
+From: Christian Prochaska
+
+Message-Id: <0bcbef9314d6679d1fbbb0114683d06de0196623.1341578007.git.chris@arachsys.com>
+From: Chris Webb
+Date: Fri, 6 Jul 2012 13:18:58 +0100
+Subject: [PATCH] Replace struct siginfo with siginfo_t
+
+Glibc 2.16.0 removes the undocumented definition of 'struct siginfo' from
+. This struct is also available as the POSIX-defined
+siginfo_t, so replace all uses of struct siginfo with siginfo_t.
+
+Signed-off-by: Chris Webb
+---
+ gdb/amd64-linux-nat.c | 4 ++--
+ gdb/arm-linux-nat.c | 2 +-
+ gdb/gdbserver/linux-low.c | 10 +++++-----
+ gdb/gdbserver/linux-low.h | 5 ++---
+ gdb/gdbserver/linux-x86-low.c | 4 ++--
+ gdb/ia64-linux-nat.c | 2 +-
+ gdb/linux-nat.c | 16 ++++++++--------
+ gdb/linux-nat.h | 6 +++---
+ gdb/ppc-linux-nat.c | 2 +-
+ gdb/procfs.c | 2 +-
+ 10 files changed, 26 insertions(+), 27 deletions(-)
+
+diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
+index a869f85..7bae36d 100644
+--- a/gdb/amd64-linux-nat.c
++++ b/gdb/amd64-linux-nat.c
+@@ -684,13 +684,13 @@ siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
+ INF. */
+
+ static int
+-amd64_linux_siginfo_fixup (struct siginfo *native, gdb_byte *inf, int direction)
++amd64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction)
+ {
+ /* Is the inferior 32-bit? If so, then do fixup the siginfo
+ object. */
+ if (gdbarch_addr_bit (get_frame_arch (get_current_frame ())) == 32)
+ {
+- gdb_assert (sizeof (struct siginfo) == sizeof (compat_siginfo_t));
++ gdb_assert (sizeof (siginfo_t) == sizeof (compat_siginfo_t));
+
+ if (direction == 0)
+ compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native);
+diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
+index 43f4fde..3ec2bfc 100644
+--- a/gdb/arm-linux-nat.c
++++ b/gdb/arm-linux-nat.c
+@@ -1203,7 +1203,7 @@ arm_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw,
+ static int
+ arm_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
+ {
+- struct siginfo *siginfo_p = linux_nat_get_siginfo (inferior_ptid);
++ siginfo_t *siginfo_p = linux_nat_get_siginfo (inferior_ptid);
+ int slot = siginfo_p->si_errno;
+
+ /* This must be a hardware breakpoint. */
+diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
+index 81b8540..e597e2f 100644
+--- a/gdb/gdbserver/linux-low.c
++++ b/gdb/gdbserver/linux-low.c
+@@ -4693,7 +4693,7 @@ linux_qxfer_osdata (const char *annex,
+ layout of the inferiors' architecture. */
+
+ static void
+-siginfo_fixup (struct siginfo *siginfo, void *inf_siginfo, int direction)
++siginfo_fixup (siginfo_t *siginfo, void *inf_siginfo, int direction)
+ {
+ int done = 0;
+
+@@ -4705,9 +4705,9 @@ siginfo_fixup (struct siginfo *siginfo, void *inf_siginfo, int direction)
+ if (!done)
+ {
+ if (direction == 1)
+- memcpy (siginfo, inf_siginfo, sizeof (struct siginfo));
++ memcpy (siginfo, inf_siginfo, sizeof (siginfo_t));
+ else
+- memcpy (inf_siginfo, siginfo, sizeof (struct siginfo));
++ memcpy (inf_siginfo, siginfo, sizeof (siginfo_t));
+ }
+ }
+
+@@ -4716,8 +4716,8 @@ linux_xfer_siginfo (const char *annex, unsigned char *readbuf,
+ unsigned const char *writebuf, CORE_ADDR offset, int len)
+ {
+ int pid;
+- struct siginfo siginfo;
+- char inf_siginfo[sizeof (struct siginfo)];
++ siginfo_t siginfo;
++ char inf_siginfo[sizeof (siginfo_t)];
+
+ if (current_inferior == NULL)
+ return -1;
+diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
+index 6635bc6..d449e1b 100644
+--- a/gdb/gdbserver/linux-low.h
++++ b/gdb/gdbserver/linux-low.h
+@@ -21,6 +21,7 @@
+ #include
+ #endif
+
++#include
+ #include "gdb_proc_service.h"
+
+ #ifdef HAVE_LINUX_REGSETS
+@@ -46,8 +47,6 @@ struct regset_info
+ extern struct regset_info target_regsets[];
+ #endif
+
+-struct siginfo;
+-
+ struct process_info_private
+ {
+ /* Arch-specific additions. */
+@@ -100,7 +99,7 @@ struct linux_target_ops
+ Returns true if any conversion was done; false otherwise.
+ If DIRECTION is 1, then copy from INF to NATIVE.
+ If DIRECTION is 0, copy from NATIVE to INF. */
+- int (*siginfo_fixup) (struct siginfo *native, void *inf, int direction);
++ int (*siginfo_fixup) (siginfo_t *native, void *inf, int direction);
+
+ /* Hook to call when a new process is created or attached to.
+ If extra per-process architecture-specific data is needed,
+diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
+index 69c6b57..82dcf83 100644
+--- a/gdb/gdbserver/linux-x86-low.c
++++ b/gdb/gdbserver/linux-x86-low.c
+@@ -906,13 +906,13 @@ siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
+ INF. */
+
+ static int
+-x86_siginfo_fixup (struct siginfo *native, void *inf, int direction)
++x86_siginfo_fixup (siginfo_t *native, void *inf, int direction)
+ {
+ #ifdef __x86_64__
+ /* Is the inferior 32-bit? If so, then fixup the siginfo object. */
+ if (register_size (0) == 4)
+ {
+- if (sizeof (struct siginfo) != sizeof (compat_siginfo_t))
++ if (sizeof (siginfo_t) != sizeof (compat_siginfo_t))
+ fatal ("unexpected difference in siginfo");
+
+ if (direction == 0)
+diff --git a/gdb/ia64-linux-nat.c b/gdb/ia64-linux-nat.c
+index 0f88e14..02482b2 100644
+--- a/gdb/ia64-linux-nat.c
++++ b/gdb/ia64-linux-nat.c
+@@ -640,7 +640,7 @@ static int
+ ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
+ {
+ CORE_ADDR psr;
+- struct siginfo *siginfo_p;
++ siginfo_t *siginfo_p;
+ struct regcache *regcache = get_current_regcache ();
+
+ siginfo_p = linux_nat_get_siginfo (inferior_ptid);
+diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
+index 44a2a21..791d7b2 100644
+--- a/gdb/linux-nat.c
++++ b/gdb/linux-nat.c
+@@ -214,7 +214,7 @@ static void (*linux_nat_new_thread) (ptid_t);
+ /* The method to call, if any, when the siginfo object needs to be
+ converted between the layout returned by ptrace, and the layout in
+ the architecture of the inferior. */
+-static int (*linux_nat_siginfo_fixup) (struct siginfo *,
++static int (*linux_nat_siginfo_fixup) (siginfo_t *,
+ gdb_byte *,
+ int);
+
+@@ -3945,7 +3945,7 @@ linux_nat_mourn_inferior (struct target_ops *ops)
+ layout of the inferiors' architecture. */
+
+ static void
+-siginfo_fixup (struct siginfo *siginfo, gdb_byte *inf_siginfo, int direction)
++siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction)
+ {
+ int done = 0;
+
+@@ -3957,9 +3957,9 @@ siginfo_fixup (struct siginfo *siginfo, gdb_byte *inf_siginfo, int direction)
+ if (!done)
+ {
+ if (direction == 1)
+- memcpy (siginfo, inf_siginfo, sizeof (struct siginfo));
++ memcpy (siginfo, inf_siginfo, sizeof (siginfo_t));
+ else
+- memcpy (inf_siginfo, siginfo, sizeof (struct siginfo));
++ memcpy (inf_siginfo, siginfo, sizeof (siginfo_t));
+ }
+ }
+
+@@ -3969,8 +3969,8 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
+ const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+ {
+ int pid;
+- struct siginfo siginfo;
+- gdb_byte inf_siginfo[sizeof (struct siginfo)];
++ siginfo_t siginfo;
++ gdb_byte inf_siginfo[sizeof (siginfo_t)];
+
+ gdb_assert (object == TARGET_OBJECT_SIGNAL_INFO);
+ gdb_assert (readbuf || writebuf);
+@@ -5784,7 +5784,7 @@ linux_nat_set_new_thread (struct target_ops *t, void (*new_thread) (ptid_t))
+ inferior. */
+ void
+ linux_nat_set_siginfo_fixup (struct target_ops *t,
+- int (*siginfo_fixup) (struct siginfo *,
++ int (*siginfo_fixup) (siginfo_t *,
+ gdb_byte *,
+ int))
+ {
+@@ -5793,7 +5793,7 @@ linux_nat_set_siginfo_fixup (struct target_ops *t,
+ }
+
+ /* Return the saved siginfo associated with PTID. */
+-struct siginfo *
++siginfo_t *
+ linux_nat_get_siginfo (ptid_t ptid)
+ {
+ struct lwp_info *lp = find_lwp_pid (ptid);
+diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h
+index 42cb2fc..422db28 100644
+--- a/gdb/linux-nat.h
++++ b/gdb/linux-nat.h
+@@ -60,7 +60,7 @@ struct lwp_info
+
+ /* Non-zero si_signo if this LWP stopped with a trap. si_addr may
+ be the address of a hardware watchpoint. */
+- struct siginfo siginfo;
++ siginfo_t siginfo;
+
+ /* STOPPED_BY_WATCHPOINT is non-zero if this LWP stopped with a data
+ watchpoint trap. */
+@@ -160,7 +160,7 @@ void linux_nat_set_new_thread (struct target_ops *, void (*) (ptid_t));
+ that ptrace returns, and the layout in the architecture of the
+ inferior. */
+ void linux_nat_set_siginfo_fixup (struct target_ops *,
+- int (*) (struct siginfo *,
++ int (*) (siginfo_t *,
+ gdb_byte *,
+ int));
+
+@@ -169,7 +169,7 @@ void linux_nat_set_siginfo_fixup (struct target_ops *,
+ void linux_nat_switch_fork (ptid_t new_ptid);
+
+ /* Return the saved siginfo associated with PTID. */
+-struct siginfo *linux_nat_get_siginfo (ptid_t ptid);
++siginfo_t *linux_nat_get_siginfo (ptid_t ptid);
+
+ /* Compute and return the processor core of a given thread. */
+ int linux_nat_core_of_thread_1 (ptid_t ptid);
+diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
+index 6f11715..3a3de07 100644
+--- a/gdb/ppc-linux-nat.c
++++ b/gdb/ppc-linux-nat.c
+@@ -2161,7 +2161,7 @@ ppc_linux_thread_exit (struct thread_info *tp, int silent)
+ static int
+ ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
+ {
+- struct siginfo *siginfo_p;
++ siginfo_t *siginfo_p;
+
+ siginfo_p = linux_nat_get_siginfo (inferior_ptid);
+
+diff --git a/gdb/procfs.c b/gdb/procfs.c
+index 5d7cb23..ea52d97 100644
+--- a/gdb/procfs.c
++++ b/gdb/procfs.c
+@@ -263,7 +263,7 @@ typedef struct sigaction gdb_sigaction_t;
+ #ifdef HAVE_PR_SIGINFO64_T
+ typedef pr_siginfo64_t gdb_siginfo_t;
+ #else
+-typedef struct siginfo gdb_siginfo_t;
++typedef siginfo_t gdb_siginfo_t;
+ #endif
+
+ /* On mips-irix, praddset and prdelset are defined in such a way that
diff --git a/repos/ports/src/app/gdb_monitor/signal_handler_thread.cc b/repos/ports/src/app/gdb_monitor/signal_handler_thread.cc
index 5e8af7b656..0389269cc1 100644
--- a/repos/ports/src/app/gdb_monitor/signal_handler_thread.cc
+++ b/repos/ports/src/app/gdb_monitor/signal_handler_thread.cc
@@ -5,36 +5,21 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
*/
-/* Genode includes */
-#include
-
-/* libc includes */
-#include
-
-/* GDB monitor includes */
-#include "thread_info.h"
#include "signal_handler_thread.h"
using namespace Genode;
using namespace Gdb_monitor;
-static bool const verbose = false;
-
Signal_handler_thread::Signal_handler_thread(Signal_receiver *receiver)
:
- Thread_deprecated<2*4096>("sig_handler"),
- _signal_receiver(receiver)
-{
- if (pipe(_pipefd))
- PERR("could not create pipe");
-
-}
+ Thread_deprecated("sig_handler"),
+ _signal_receiver(receiver) { }
void Signal_handler_thread::entry()
@@ -42,18 +27,9 @@ void Signal_handler_thread::entry()
while(1) {
Signal s = _signal_receiver->wait_for_signal();
- if (verbose)
- PDBG("received exception signal");
+ Signal_dispatcher_base *signal_dispatcher =
+ dynamic_cast(s.context());
- /* default is segmentation fault */
- unsigned long sig = 0;
-
- if (Thread_info *thread_info = dynamic_cast(s.context()))
- /* thread trapped */
- sig = thread_info->lwpid();
-
- write(_pipefd[1], &sig, sizeof(sig));
+ signal_dispatcher->dispatch(s.num());
}
-
- sleep_forever();
};
diff --git a/repos/ports/src/app/gdb_monitor/signal_handler_thread.h b/repos/ports/src/app/gdb_monitor/signal_handler_thread.h
index 247085b88f..06b3c00770 100644
--- a/repos/ports/src/app/gdb_monitor/signal_handler_thread.h
+++ b/repos/ports/src/app/gdb_monitor/signal_handler_thread.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -21,18 +21,19 @@ using namespace Genode;
namespace Gdb_monitor {
- class Signal_handler_thread : public Thread_deprecated<2*4096>
+ enum { SIGNAL_HANDLER_THREAD_STACK_SIZE = 2*1024*sizeof(addr_t) };
+
+ class Signal_handler_thread
+ : public Thread_deprecated
{
private:
- int _pipefd[2];
Signal_receiver *_signal_receiver;
public:
Signal_handler_thread(Signal_receiver *receiver);
void entry();
- int pipe_read_fd() { return _pipefd[0]; }
};
}
diff --git a/repos/ports/src/app/gdb_monitor/target.mk b/repos/ports/src/app/gdb_monitor/target.mk
index 2b96f90235..47197bf628 100644
--- a/repos/ports/src/app/gdb_monitor/target.mk
+++ b/repos/ports/src/app/gdb_monitor/target.mk
@@ -28,13 +28,13 @@ SRC_C = event-loop.c \
SRC_C += linux-low.c
-CC_OPT += -DGDBSERVER
+CC_OPT += -DGDBSERVER -DPKGVERSION="\"7.3.1\"" -DREPORT_BUGS_TO="\"\""
CC_OPT_linux-low += -Wno-unused-function
SRC_CC = genode-low.cc \
- gdb_stub_thread.cc \
cpu_session_component.cc \
+ cpu_thread_component.cc \
ram_session_component.cc \
region_map_component.cc \
signal_handler_thread.cc \
diff --git a/repos/ports/src/app/gdb_monitor/thread_info.h b/repos/ports/src/app/gdb_monitor/thread_info.h
deleted file mode 100644
index 6e54ac1f1f..0000000000
--- a/repos/ports/src/app/gdb_monitor/thread_info.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * \brief Thread info class for GDB monitor
- * \author Christian Prochaska
- * \date 2011-09-09
- */
-
-/*
- * Copyright (C) 2011-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 _THREAD_INFO_H_
-#define _THREAD_INFO_H_
-
-#include
-
-#include "append_list.h"
-
-namespace Gdb_monitor {
-
- using namespace Genode;
-
- class Thread_info : public Signal_context, public Append_list::Element
- {
- private:
-
- Thread_capability _thread_cap;
- unsigned long _lwpid;
-
- public:
-
- Thread_info(Thread_capability thread_cap, unsigned long lwpid)
- : _thread_cap(thread_cap),
- _lwpid(lwpid) { }
-
- Thread_capability thread_cap() { return _thread_cap; }
- unsigned long lwpid() { return _lwpid; }
- };
-}
-
-#endif /* _THREAD_INFO_H_ */
diff --git a/repos/ports/src/lib/gdbserver_libc_support/gdbserver_libc_support.c b/repos/ports/src/lib/gdbserver_libc_support/gdbserver_libc_support.c
deleted file mode 100644
index 796b5c15f2..0000000000
--- a/repos/ports/src/lib/gdbserver_libc_support/gdbserver_libc_support.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * \brief Dummy implementations of Linux-specific libc functions
- * needed to build gdbserver
- * \author Christian Prochaska
- * \date 2011-09-01
- */
-
-/*
- * Copyright (C) 2011-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.
- */
-
-#include
-#include
-
-#include
-
-long ptrace(enum __ptrace_request request, ...)
-{
- char *request_str = 0;
-
- switch (request) {
- case PTRACE_TRACEME: request_str = "PTRACE_TRACEME"; break;
- case PTRACE_ATTACH: request_str = "PTRACE_ATTACH"; break;
- case PTRACE_KILL: request_str = "PTRACE_KILL"; break;
- case PTRACE_DETACH: request_str = "PTRACE_DETACH"; break;
- case PTRACE_SINGLESTEP: request_str = "PTRACE_SINGLESTEP"; break;
- case PTRACE_CONT: request_str = "PTRACE_CONT"; break;
- case PTRACE_PEEKTEXT: request_str = "PTRACE_PEEKTEXT"; break;
- case PTRACE_POKETEXT: request_str = "PTRACE_POKETEXT"; break;
- case PTRACE_PEEKUSER: request_str = "PTRACE_PEEKUSER"; break;
- case PTRACE_POKEUSER: request_str = "PTRACE_POKEUSER"; break;
- case PTRACE_GETREGS: request_str = "PTRACE_GETREGS"; break;
- case PTRACE_SETREGS: request_str = "PTRACE_SETREGS"; break;
- }
-
- printf("ptrace(%s) called - not implemented!\n", request_str);
-
- errno = EINVAL;
- return -1;
-}
diff --git a/repos/ports/src/lib/gdbserver_libc_support/gdbserver_libc_support.h b/repos/ports/src/lib/gdbserver_libc_support/gdbserver_libc_support.h
index 553a7e7fc2..1ea3d07073 100644
--- a/repos/ports/src/lib/gdbserver_libc_support/gdbserver_libc_support.h
+++ b/repos/ports/src/lib/gdbserver_libc_support/gdbserver_libc_support.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -29,8 +29,4 @@ struct user {
unsigned long int u_debugreg [8];
};
-/* Missing in libc's sys/wait.h */
-
-#define __WCLONE 0
-
#endif /* GDBSERVER_LIBC_DUMMIES_H */
diff --git a/repos/ports/src/lib/gdbserver_libc_support/sys/ptrace.h b/repos/ports/src/lib/gdbserver_libc_support/sys/ptrace.h
index 129d049eb6..7f12ade6b6 100644
--- a/repos/ports/src/lib/gdbserver_libc_support/sys/ptrace.h
+++ b/repos/ports/src/lib/gdbserver_libc_support/sys/ptrace.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -20,18 +20,23 @@
#include
enum __ptrace_request {
- PTRACE_TRACEME,
- PTRACE_ATTACH,
- PTRACE_KILL,
- PTRACE_DETACH,
- PTRACE_SINGLESTEP,
- PTRACE_CONT,
- PTRACE_PEEKTEXT,
- PTRACE_POKETEXT,
- PTRACE_PEEKUSER,
- PTRACE_POKEUSER,
- PTRACE_GETREGS,
- PTRACE_SETREGS,
+ PTRACE_TRACEME = 0,
+ PTRACE_PEEKTEXT = 1,
+ PTRACE_PEEKUSER = 3,
+ PTRACE_POKETEXT = 4,
+ PTRACE_POKEUSER = 6,
+ PTRACE_CONT = 7,
+ PTRACE_KILL = 8,
+ PTRACE_SINGLESTEP = 9,
+ PTRACE_GETREGS = 12,
+ PTRACE_SETREGS = 13,
+ PTRACE_ATTACH = 16,
+ PTRACE_DETACH = 17,
+
+ PTRACE_EVENT_CLONE = 3,
+
+ PTRACE_GETEVENTMSG = 0x4201,
+ PTRACE_GETREGSET = 0x4204,
};
extern long ptrace(enum __ptrace_request request, ...);
diff --git a/repos/ports/src/lib/gdbserver_libc_support/sys/wait.h b/repos/ports/src/lib/gdbserver_libc_support/sys/wait.h
new file mode 100644
index 0000000000..609cbe90ea
--- /dev/null
+++ b/repos/ports/src/lib/gdbserver_libc_support/sys/wait.h
@@ -0,0 +1,37 @@
+/*
+ * \brief Linux-specific types for gdbserver
+ * \author Christian Prochaska
+ * \date 2016-03-16
+ */
+
+/*
+ * Copyright (C) 2016 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 SYS_WAIT_H
+#define SYS_WAIT_H
+
+#define WNOHANG 1
+
+#define __WCLONE 0x80000000
+
+#define WIFEXITED(status) (status == 0)
+#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
+#define WIFSIGNALED(status) (!WIFEXITED(status) && !WIFSTOPPED(status))
+
+#define WEXITSTATUS(status) ((status >> 8) & 0xff)
+#define WSTOPSIG(status) ((status >> 8) & 0xff)
+#define WTERMSIG(status) (status & 0x7f)
+
+#define W_STOPCODE(sig) ((sig) << 8 | 0x7f)
+
+__BEGIN_DECLS
+
+pid_t waitpid(pid_t pid, int *status, int flags);
+
+__END_DECLS
+
+#endif /* SYS_WAIT_H */
diff --git a/repos/ports/src/lib/gdbserver_platform/gdbserver_platform_helper.cc b/repos/ports/src/lib/gdbserver_platform/gdbserver_platform_helper.cc
index c9c6aac666..27140720a7 100644
--- a/repos/ports/src/lib/gdbserver_platform/gdbserver_platform_helper.cc
+++ b/repos/ports/src/lib/gdbserver_platform/gdbserver_platform_helper.cc
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -22,16 +22,20 @@ extern "C" {
#include
#include "cpu_session_component.h"
-#include "gdb_stub_thread.h"
+#include "genode_child_resources.h"
using namespace Genode;
using namespace Gdb_monitor;
-extern Gdb_stub_thread *gdb_stub_thread();
+extern Genode_child_resources *genode_child_resources();
+
+
+static constexpr bool verbose = false;
+
Thread_state get_current_thread_state()
{
- Cpu_session_component *csc = gdb_stub_thread()->cpu_session_component();
+ Cpu_session_component *csc = genode_child_resources()->cpu_session_component();
ptid_t ptid = ((struct inferior_list_entry*)current_inferior)->id;
@@ -40,9 +44,10 @@ Thread_state get_current_thread_state()
return cpu_thread.state();
}
+
void set_current_thread_state(Thread_state thread_state)
{
- Cpu_session_component *csc = gdb_stub_thread()->cpu_session_component();
+ Cpu_session_component *csc = genode_child_resources()->cpu_session_component();
ptid_t ptid = ((struct inferior_list_entry*)current_inferior)->id;
@@ -51,3 +56,43 @@ void set_current_thread_state(Thread_state thread_state)
cpu_thread.state(thread_state);
}
+
+void fetch_register(const char *reg_name,
+ addr_t thread_state_reg,
+ unsigned long &value)
+{
+ value = thread_state_reg;
+
+ if (verbose)
+ PDBG("%s = %8lx", reg_name, value);
+}
+
+
+void cannot_fetch_register(const char *reg_name)
+{
+ if (verbose)
+ PDBG("cannot fetch register %s", reg_name);
+}
+
+
+bool store_register(const char *reg_name,
+ addr_t &thread_state_reg,
+ unsigned long value)
+{
+ if (verbose)
+ PDBG("%s = %8lx", reg_name, value);
+
+ if (thread_state_reg == value)
+ return false;
+
+ thread_state_reg = value;
+
+ return true;
+}
+
+
+void cannot_store_register(const char *reg_name, unsigned long value)
+{
+ if (verbose)
+ PDBG("cannot set contents of register %s (%8lx)", reg_name, value);
+}
diff --git a/repos/ports/src/lib/gdbserver_platform/gdbserver_platform_helper.h b/repos/ports/src/lib/gdbserver_platform/gdbserver_platform_helper.h
index abda7c6f0c..3dab14f0c8 100644
--- a/repos/ports/src/lib/gdbserver_platform/gdbserver_platform_helper.h
+++ b/repos/ports/src/lib/gdbserver_platform/gdbserver_platform_helper.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -21,4 +21,16 @@ Genode::Thread_state get_current_thread_state();
void set_current_thread_state(Genode::Thread_state thread_state);
+void fetch_register(const char *reg_name,
+ Genode::addr_t thread_state_reg,
+ unsigned long &value);
+
+void cannot_fetch_register(const char *reg_name);
+
+bool store_register(const char *reg_name,
+ Genode::addr_t &thread_state_reg,
+ unsigned long value);
+
+void cannot_store_register(const char *reg_name, unsigned long value);
+
#endif /* GDBSERVER_PLATFORM_HELPER_H */
diff --git a/repos/ports/src/lib/gdbserver_platform/spec/fiasco_x86/low.cc b/repos/ports/src/lib/gdbserver_platform/spec/fiasco_x86/low.cc
deleted file mode 100644
index 03a7192030..0000000000
--- a/repos/ports/src/lib/gdbserver_platform/spec/fiasco_x86/low.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * \brief Fiasco(x86)-specific helper functions for GDB server
- * \author Christian Prochaska
- * \date 2011-05-06
- */
-
-/*
- * Copyright (C) 2011-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.
- */
-
-extern "C" {
-#define private _private
-#include "genode-low.h"
-#define _private private
-}
-
-#include
-#include "i386.h"
-#include "cpu_session_component.h"
-#include "gdbserver_platform_helper.h"
-#include "gdb_stub_thread.h"
-
-using namespace Genode;
-
-extern "C" int genode_fetch_register(int regno, unsigned long *reg_content)
-{
- Thread_state thread_state;
-
- try { thread_state = get_current_thread_state(); }
- catch (...) { return 0; }
-
- switch((enum reg_index)regno)
- {
- /* TODO: implement the backend function that tells gdbserver that these registers cannot be fetched */
- case EAX: PDBG("cannot determine contents of register EAX"); return -1;
- case ECX: PDBG("cannot determine contents of register ECX"); return -1;
- case EDX: PDBG("cannot determine contents of register EDX"); return -1;
- case EBX: PDBG("cannot determine contents of register EBX"); return -1;
- case UESP: *reg_content = thread_state.sp; PDBG("ESP = %8lx", *reg_content); return 0;
- case EBP:
-
- /*
- * When in a syscall, the user EBP has been pushed onto the stack at address ESP+0
- *
- * looking for syscall pattern:
- * EIP-2: cd 30 int $30
- */
- if ((genode_read_memory_byte((void*)(thread_state.ip - 1)) == 0x30) &&
- (genode_read_memory_byte((void*)(thread_state.ip - 2)) == 0xcd)) {
- *reg_content = genode_read_memory_byte((void*)(thread_state.sp + 0)) +
- (genode_read_memory_byte((void*)(thread_state.sp + 1)) << 8) +
- (genode_read_memory_byte((void*)(thread_state.sp + 2)) << 16) +
- (genode_read_memory_byte((void*)(thread_state.sp + 3)) << 24);
- PDBG("ESP = %8lx", *reg_content);
- return 0;
- } else {
- PDBG("cannot determine contents of register EBP"); return -1;
- }
- case ESI: PDBG("cannot determine contents of register ESI"); return -1;
- case EDI: PDBG("cannot determine contents of register EDI"); return -1;
- case EIP: *reg_content = thread_state.ip; PDBG("EIP = %8lx", *reg_content); return 0;
- case EFL: PDBG("cannot determine contents of register EFLAGS"); return -1;
- case CS: PDBG("cannot determine contents of register CS"); return -1;
- case SS: PDBG("cannot determine contents of register SS"); return -1;
- case DS: PDBG("cannot determine contents of register DS"); return -1;
- case ES: PDBG("cannot determine contents of register ES"); return -1;
- case FS: PDBG("cannot determine contents of register FS"); return -1;
- case GS: PDBG("cannot determine contents of register GS"); return -1;
- }
-
- return -1;
-}
-
-
-extern "C" void genode_store_register(int regno, unsigned long reg_content)
-{
- PDBG("not implemented yet for this platform");
-}
-
diff --git a/repos/ports/src/lib/gdbserver_platform/spec/foc/native_cpu.cc b/repos/ports/src/lib/gdbserver_platform/spec/foc/native_cpu.cc
new file mode 100644
index 0000000000..fb512ee015
--- /dev/null
+++ b/repos/ports/src/lib/gdbserver_platform/spec/foc/native_cpu.cc
@@ -0,0 +1,90 @@
+/*
+ * \brief Fiasco.OC-specific 'Native_cpu' setup
+ * \author Christian Prochaska
+ * \date 2016-05-13
+ */
+
+/*
+ * Copyright (C) 2016 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.
+ */
+
+
+/* Genode includes */
+#include
+
+/* GDB monitor includes */
+#include "cpu_session_component.h"
+#include "cpu_thread_component.h"
+
+
+namespace Gdb_monitor {
+ class Native_cpu_component;
+}
+
+
+using namespace Genode;
+
+
+class Gdb_monitor::Native_cpu_component : public Rpc_object
+{
+ private:
+
+ Cpu_session_component &_cpu_session_component;
+ Foc_native_cpu_client _foc_native_cpu;
+
+ public:
+
+ Native_cpu_component(Cpu_session_component &cpu_session_component)
+ : _cpu_session_component(cpu_session_component),
+ _foc_native_cpu(_cpu_session_component.parent_cpu_session().native_cpu())
+ {
+ _cpu_session_component.thread_ep().manage(this);
+ }
+
+ ~Native_cpu_component()
+ {
+ _cpu_session_component.thread_ep().dissolve(this);
+ }
+
+ void enable_vcpu(Thread_capability thread_cap, addr_t vcpu_state) override
+ {
+ Cpu_thread_component *cpu_thread = _cpu_session_component.lookup_cpu_thread(thread_cap);
+ _foc_native_cpu.enable_vcpu(cpu_thread->parent_thread_cap(), vcpu_state);
+ }
+
+ Native_capability native_cap(Thread_capability thread_cap) override
+ {
+ Cpu_thread_component *cpu_thread = _cpu_session_component.lookup_cpu_thread(thread_cap);
+ return _foc_native_cpu.native_cap(cpu_thread->parent_thread_cap());
+ }
+
+ Native_capability alloc_irq() override
+ {
+ return _foc_native_cpu.alloc_irq();
+ }
+};
+
+
+Capability
+Gdb_monitor::Cpu_session_component::_setup_native_cpu()
+{
+ Native_cpu_component *native_cpu_component =
+ new (_md_alloc) Native_cpu_component(*this);
+
+ return native_cpu_component->cap();
+}
+
+
+void Gdb_monitor::Cpu_session_component::_cleanup_native_cpu()
+{
+ Native_cpu_component *native_cpu_component = nullptr;
+ _thread_ep->apply(_native_cpu_cap, [&] (Native_cpu_component *c) { native_cpu_component = c; });
+
+ if (!native_cpu_component) return;
+
+ destroy(_md_alloc, native_cpu_component);
+}
diff --git a/repos/ports/src/lib/gdbserver_platform/spec/foc_arm/low.cc b/repos/ports/src/lib/gdbserver_platform/spec/foc_arm/low.cc
index a6a9081e1f..ea12b93746 100644
--- a/repos/ports/src/lib/gdbserver_platform/spec/foc_arm/low.cc
+++ b/repos/ports/src/lib/gdbserver_platform/spec/foc_arm/low.cc
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -22,107 +22,124 @@ extern "C" {
#include "reg-arm.h"
#include "gdbserver_platform_helper.h"
-#include "gdb_stub_thread.h"
-
-#undef PDBG
-#define PDBG(...)
+#include "genode_child_resources.h"
using namespace Genode;
-static bool in_syscall(Thread_state const &thread_state)
+static bool in_syscall(Thread_state const &ts)
{
- /* looking for syscall pattern:
- * (PC-8: e1a0e00f mov lr, pc)
- * PC-4: e3e0f00b mvn pc, #11
- * (PC: e1a02004 mov r2, r4)
- */
- if ((genode_read_memory_byte((void*)(thread_state.ip - 1)) == 0xe3) &&
- (genode_read_memory_byte((void*)(thread_state.ip - 2)) == 0xe0) &&
- (genode_read_memory_byte((void*)(thread_state.ip - 3)) == 0xf0) &&
- (genode_read_memory_byte((void*)(thread_state.ip - 4)) == 0x0b))
- return true;
-
+ try {
+ /* looking for syscall pattern:
+ * (PC-8: e1a0e00f mov lr, pc)
+ * PC-4: e3e0f00b mvn pc, #11
+ * (PC: e1a02004 mov r2, r4)
+ */
+ if ((genode_read_memory_byte((void*)(ts.ip - 1)) == 0xe3) &&
+ (genode_read_memory_byte((void*)(ts.ip - 2)) == 0xe0) &&
+ (genode_read_memory_byte((void*)(ts.ip - 3)) == 0xf0) &&
+ (genode_read_memory_byte((void*)(ts.ip - 4)) == 0x0b))
+ return true;
+ } catch (No_memory_at_address) {
+ return false;
+ }
return false;
}
-extern "C" int genode_fetch_register(int regno, unsigned long *reg_content)
+extern "C" int genode_fetch_register(int regno, unsigned long *value)
{
- Thread_state thread_state;
+ Thread_state ts;
- try { thread_state = get_current_thread_state(); }
- catch (...) { return 0; }
+ try { ts = get_current_thread_state(); }
+ catch (...) {
+ PERR("%s: could not get current thread state", __PRETTY_FUNCTION__);
+ return -1;
+ }
+
+ if (in_syscall(ts) || ts.unresolved_page_fault) {
- if (in_syscall(thread_state) || thread_state.unresolved_page_fault) {
switch((enum reg_index)regno)
{
- case R0: PDBG("cannot determine contents of register R0"); return -1;
- case R1: PDBG("cannot determine contents of register R1"); return -1;
- case R2: PDBG("cannot determine contents of register R2"); return -1;
- case R3: PDBG("cannot determine contents of register R3"); return -1;
- case R4: PDBG("cannot determine contents of register R4"); return -1;
- case R5: PDBG("cannot determine contents of register R5"); return -1;
- case R6: PDBG("cannot determine contents of register R6"); return -1;
- case R7: PDBG("cannot determine contents of register R7"); return -1;
- case R8: PDBG("cannot determine contents of register R8"); return -1;
- case R9: PDBG("cannot determine contents of register R9"); return -1;
- case R10: PDBG("cannot determine contents of register R10"); return -1;
+ case R0: cannot_fetch_register("R0"); return -1;
+ case R1: cannot_fetch_register("R1"); return -1;
+ case R2: cannot_fetch_register("R2"); return -1;
+ case R3: cannot_fetch_register("R3"); return -1;
+ case R4: cannot_fetch_register("R4"); return -1;
+ case R5: cannot_fetch_register("R5"); return -1;
+ case R6: cannot_fetch_register("R6"); return -1;
+ case R7: cannot_fetch_register("R7"); return -1;
+ case R8: cannot_fetch_register("R8"); return -1;
+ case R9: cannot_fetch_register("R9"); return -1;
+ case R10: cannot_fetch_register("R10"); return -1;
+
case R11:
- if (in_syscall(thread_state)) {
+
+ if (in_syscall(ts)) {
/* R11 can be calculated from SP. The offset can be found in
* the disassembled 'Fiasco::l4_ipc()' function:
* add r11, sp, #8 -> r11 = sp + 8
* sub sp, sp, #20 -> r11 = (sp + 20) + 8
*/
- *reg_content = (thread_state.sp + 20) + 8;
- PDBG("FP = %8lx", *reg_content);
+ *value = (ts.sp + 20) + 8;
+
+ /* for the debug output, if enabled */
+ fetch_register("R11", *value, *value);
+
return 0;
} else {
- PDBG("cannot determine contents of register R11"); return -1;
+
+ cannot_fetch_register("R11");
+
+ return -1;
}
- case R12: PDBG("cannot determine contents of register R12"); return -1;
- case SP: *reg_content = thread_state.sp; PDBG("SP = %8lx", *reg_content); return 0;
- case LR: PDBG("cannot determine contents of register LR"); return -1;
- case PC: *reg_content = thread_state.ip; PDBG("PC = %8lx", *reg_content); return 0;
- case F0: PDBG("cannot determine contents of register F0"); return -1;
- case F1: PDBG("cannot determine contents of register F1"); return -1;
- case F2: PDBG("cannot determine contents of register F2"); return -1;
- case F3: PDBG("cannot determine contents of register F3"); return -1;
- case F4: PDBG("cannot determine contents of register F4"); return -1;
- case F5: PDBG("cannot determine contents of register F5"); return -1;
- case F6: PDBG("cannot determine contents of register F6"); return -1;
- case F7: PDBG("cannot determine contents of register F7"); return -1;
- case FPS: PDBG("cannot determine contents of register FPS"); return -1;
- case CPSR: PDBG("cannot determine contents of register CPSR"); return -1;
+
+ case R12: cannot_fetch_register("R12"); return -1;
+ case SP: fetch_register("SP ", ts.sp, *value); return 0;
+ case LR: cannot_fetch_register("LR"); return -1;
+ case PC: fetch_register("PC ", ts.ip, *value); return 0;
+ case F0: cannot_fetch_register("F0"); return -1;
+ case F1: cannot_fetch_register("F1"); return -1;
+ case F2: cannot_fetch_register("F2"); return -1;
+ case F3: cannot_fetch_register("F3"); return -1;
+ case F4: cannot_fetch_register("F4"); return -1;
+ case F5: cannot_fetch_register("F5"); return -1;
+ case F6: cannot_fetch_register("F6"); return -1;
+ case F7: cannot_fetch_register("F7"); return -1;
+ case FPS: cannot_fetch_register("FPS"); return -1;
+ case CPSR: cannot_fetch_register("CPSR"); return -1;
+ default: PERR("unhandled register %d", regno); return -1;
}
+
} else {
+
switch((enum reg_index)regno)
{
- case R0: *reg_content = thread_state.r0; PDBG("R0 = %8lx", *reg_content); return 0;
- case R1: *reg_content = thread_state.r1; PDBG("R1 = %8lx", *reg_content); return 0;
- case R2: *reg_content = thread_state.r2; PDBG("R2 = %8lx", *reg_content); return 0;
- case R3: *reg_content = thread_state.r3; PDBG("R3 = %8lx", *reg_content); return 0;
- case R4: *reg_content = thread_state.r4; PDBG("R4 = %8lx", *reg_content); return 0;
- case R5: *reg_content = thread_state.r5; PDBG("R5 = %8lx", *reg_content); return 0;
- case R6: *reg_content = thread_state.r6; PDBG("R6 = %8lx", *reg_content); return 0;
- case R7: *reg_content = thread_state.r7; PDBG("R7 = %8lx", *reg_content); return 0;
- case R8: *reg_content = thread_state.r8; PDBG("R8 = %8lx", *reg_content); return 0;
- case R9: *reg_content = thread_state.r9; PDBG("R9 = %8lx", *reg_content); return 0;
- case R10: *reg_content = thread_state.r10; PDBG("R10 = %8lx", *reg_content); return 0;
- case R11: *reg_content = thread_state.r11; PDBG("FP = %8lx", *reg_content); return 0;
- case R12: *reg_content = thread_state.r12; PDBG("R12 = %8lx", *reg_content); return 0;
- case SP: *reg_content = thread_state.sp; PDBG("SP = %8lx", *reg_content); return 0;
- case LR: *reg_content = thread_state.lr; PDBG("LR = %8lx", *reg_content); return 0;
- case PC: *reg_content = thread_state.ip; PDBG("PC = %8lx", *reg_content); return 0;
- case F0: PDBG("cannot determine contents of register F0"); return -1;
- case F1: PDBG("cannot determine contents of register F1"); return -1;
- case F2: PDBG("cannot determine contents of register F2"); return -1;
- case F3: PDBG("cannot determine contents of register F3"); return -1;
- case F4: PDBG("cannot determine contents of register F4"); return -1;
- case F5: PDBG("cannot determine contents of register F5"); return -1;
- case F6: PDBG("cannot determine contents of register F6"); return -1;
- case F7: PDBG("cannot determine contents of register F7"); return -1;
- case FPS: PDBG("cannot determine contents of register FPS"); return -1;
- case CPSR: *reg_content = thread_state.cpsr; PDBG("CPSR = %8lx", *reg_content); return 0;
+ case R0: fetch_register("R0 ", ts.r0, *value); return 0;
+ case R1: fetch_register("R1 ", ts.r1, *value); return 0;
+ case R2: fetch_register("R2 ", ts.r2, *value); return 0;
+ case R3: fetch_register("R3 ", ts.r3, *value); return 0;
+ case R4: fetch_register("R4 ", ts.r4, *value); return 0;
+ case R5: fetch_register("R5 ", ts.r5, *value); return 0;
+ case R6: fetch_register("R6 ", ts.r6, *value); return 0;
+ case R7: fetch_register("R7 ", ts.r7, *value); return 0;
+ case R8: fetch_register("R8 ", ts.r8, *value); return 0;
+ case R9: fetch_register("R9 ", ts.r9, *value); return 0;
+ case R10: fetch_register("R10 ", ts.r10, *value); return 0;
+ case R11: fetch_register("R11 ", ts.r11, *value); return 0;
+ case R12: fetch_register("R12 ", ts.r12, *value); return 0;
+ case SP: fetch_register("SP ", ts.sp, *value); return 0;
+ case LR: fetch_register("LR ", ts.lr, *value); return 0;
+ case PC: fetch_register("PC ", ts.ip, *value); return 0;
+ case F0: cannot_fetch_register("F0"); return -1;
+ case F1: cannot_fetch_register("F1"); return -1;
+ case F2: cannot_fetch_register("F2"); return -1;
+ case F3: cannot_fetch_register("F3"); return -1;
+ case F4: cannot_fetch_register("F4"); return -1;
+ case F5: cannot_fetch_register("F5"); return -1;
+ case F6: cannot_fetch_register("F6"); return -1;
+ case F7: cannot_fetch_register("F7"); return -1;
+ case FPS: cannot_fetch_register("FPS"); return -1;
+ case CPSR: fetch_register("CPSR", ts.cpsr, *value); return 0;
+ default: PERR("unhandled register %d", regno); return -1;
}
}
@@ -130,48 +147,51 @@ extern "C" int genode_fetch_register(int regno, unsigned long *reg_content)
}
-extern "C" void genode_store_register(int regno, unsigned long reg_content)
+extern "C" void genode_store_register(int regno, unsigned long value)
{
- Thread_state thread_state;
+ Thread_state ts;
- try { thread_state = get_current_thread_state(); }
- catch (...) { return; }
+ try { ts = get_current_thread_state(); }
+ catch (...) {
+ PERR("%s: could not get current thread state", __PRETTY_FUNCTION__);
+ return;
+ }
- if (in_syscall(thread_state)) {
+ if (in_syscall(ts)) {
PDBG("cannot set registers while thread is in syscall");
return;
}
switch((enum reg_index)regno)
{
- case R0: thread_state.r0 = reg_content; PDBG("R0 = %8lx", reg_content); break;
- case R1: thread_state.r1 = reg_content; PDBG("R1 = %8lx", reg_content); break;
- case R2: thread_state.r2 = reg_content; PDBG("R2 = %8lx", reg_content); break;
- case R3: thread_state.r3 = reg_content; PDBG("R3 = %8lx", reg_content); break;
- case R4: thread_state.r4 = reg_content; PDBG("R4 = %8lx", reg_content); break;
- case R5: thread_state.r5 = reg_content; PDBG("R5 = %8lx", reg_content); break;
- case R6: thread_state.r6 = reg_content; PDBG("R6 = %8lx", reg_content); break;
- case R7: thread_state.r7 = reg_content; PDBG("R7 = %8lx", reg_content); break;
- case R8: thread_state.r8 = reg_content; PDBG("R8 = %8lx", reg_content); break;
- case R9: thread_state.r9 = reg_content; PDBG("R9 = %8lx", reg_content); break;
- case R10: thread_state.r10 = reg_content; PDBG("R10 = %8lx", reg_content); break;
- case R11: thread_state.r11 = reg_content; PDBG("FP = %8lx", reg_content); break;
- case R12: thread_state.r12 = reg_content; PDBG("R12 = %8lx", reg_content); break;
- case SP: thread_state.sp = reg_content; PDBG("SP = %8lx", reg_content); break;
- case LR: thread_state.lr = reg_content; PDBG("LR = %8lx", reg_content); break;
- case PC: thread_state.ip = reg_content; PDBG("PC = %8lx", reg_content); break;
- case F0: PDBG("cannot set contents of register F0"); break;
- case F1: PDBG("cannot set contents of register F1"); break;
- case F2: PDBG("cannot set contents of register F2"); break;
- case F3: PDBG("cannot set contents of register F3"); break;
- case F4: PDBG("cannot set contents of register F4"); break;
- case F5: PDBG("cannot set contents of register F5"); break;
- case F6: PDBG("cannot set contents of register F6"); break;
- case F7: PDBG("cannot set contents of register F7"); break;
- case FPS: PDBG("cannot set contents of register FPS"); break;
- case CPSR: thread_state.cpsr = reg_content; PDBG("CPSR = %8lx", reg_content); break;
+ case R0: if (!store_register("R0 ", ts.r0, value)) return; break;
+ case R1: if (!store_register("R1 ", ts.r1, value)) return; break;
+ case R2: if (!store_register("R2 ", ts.r2, value)) return; break;
+ case R3: if (!store_register("R3 ", ts.r3, value)) return; break;
+ case R4: if (!store_register("R4 ", ts.r4, value)) return; break;
+ case R5: if (!store_register("R5 ", ts.r5, value)) return; break;
+ case R6: if (!store_register("R6 ", ts.r6, value)) return; break;
+ case R7: if (!store_register("R7 ", ts.r7, value)) return; break;
+ case R8: if (!store_register("R8 ", ts.r8, value)) return; break;
+ case R9: if (!store_register("R9 ", ts.r9, value)) return; break;
+ case R10: if (!store_register("R10 ", ts.r10, value)) return; break;
+ case R11: if (!store_register("R11 ", ts.r11, value)) return; break;
+ case R12: if (!store_register("R12 ", ts.r12, value)) return; break;
+ case SP: if (!store_register("SP ", ts.sp, value)) return; break;
+ case LR: if (!store_register("LR ", ts.lr, value)) return; break;
+ case PC: if (!store_register("PC ", ts.ip, value)) return; break;
+ case F0: cannot_store_register("F0 ", value); return;
+ case F1: cannot_store_register("F1 ", value); return;
+ case F2: cannot_store_register("F2 ", value); return;
+ case F3: cannot_store_register("F3 ", value); return;
+ case F4: cannot_store_register("F4 ", value); return;
+ case F5: cannot_store_register("F5 ", value); return;
+ case F6: cannot_store_register("F6 ", value); return;
+ case F7: cannot_store_register("F7 ", value); return;
+ case FPS: cannot_store_register("FPS", value); return;
+ case CPSR: if (!store_register("CPSR", ts.cpsr, value)) return; break;
}
- set_current_thread_state(thread_state);
+ set_current_thread_state(ts);
}
diff --git a/repos/ports/src/lib/gdbserver_platform/spec/foc_x86_32/low.cc b/repos/ports/src/lib/gdbserver_platform/spec/foc_x86_32/low.cc
index bd5d700d95..a42c508e2a 100644
--- a/repos/ports/src/lib/gdbserver_platform/spec/foc_x86_32/low.cc
+++ b/repos/ports/src/lib/gdbserver_platform/spec/foc_x86_32/low.cc
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011-2013 Genode Labs GmbH
+ * Copyright (C) 2011-2016 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.
@@ -21,10 +21,7 @@ extern "C" {
#include "i386.h"
#include "cpu_session_component.h"
#include "gdbserver_platform_helper.h"
-#include "gdb_stub_thread.h"
-
-#undef PDBG
-#define PDBG(...)
+#include "genode_child_resources.h"
using namespace Genode;
@@ -44,113 +41,146 @@ static bool in_syscall(Thread_state const &thread_state)
return false;
}
-extern "C" int genode_fetch_register(int regno, unsigned long *reg_content)
+extern "C" int genode_fetch_register(int regno, unsigned long *value)
{
- Thread_state thread_state;
+ Thread_state ts;
- try { thread_state = get_current_thread_state(); }
- catch (...) { return 0; }
+ try { ts = get_current_thread_state(); }
+ catch (...) {
+ PERR("%s: could not get current thread state", __PRETTY_FUNCTION__);
+ return -1;
+ }
+
+ if (in_syscall(ts) || ts.unresolved_page_fault) {
- if (in_syscall(thread_state) || thread_state.unresolved_page_fault) {
switch((enum reg_index)regno)
{
- case EAX: PDBG("cannot determine contents of register EAX"); return -1;
- case ECX: PDBG("cannot determine contents of register ECX"); return -1;
- case EDX: PDBG("cannot determine contents of register EDX"); return -1;
+ case EAX: cannot_fetch_register("EAX"); return -1;
+ case ECX: cannot_fetch_register("ECX"); return -1;
+ case EDX: cannot_fetch_register("EDX"); return -1;
+
case EBX:
- if (in_syscall(thread_state)) {
+
+ if (in_syscall(ts)) {
+
/* When in a syscall, the user EBX has been pushed onto the stack at address ESP+4 */
- *reg_content = genode_read_memory_byte((void*)(thread_state.sp + 4)) +
- (genode_read_memory_byte((void*)(thread_state.sp + 5)) << 8) +
- (genode_read_memory_byte((void*)(thread_state.sp + 6)) << 16) +
- (genode_read_memory_byte((void*)(thread_state.sp + 7)) << 24);
- PDBG("EBX = %8lx", *reg_content);
+ *value = genode_read_memory_byte((void*)(ts.sp + 4))
+ + (genode_read_memory_byte((void*)(ts.sp + 5)) << 8)
+ + (genode_read_memory_byte((void*)(ts.sp + 6)) << 16)
+ + (genode_read_memory_byte((void*)(ts.sp + 7)) << 24);
+
+ /* for the debug output, if enabled */
+ fetch_register("EBX", *value, *value);
+
return 0;
+
} else {
- PDBG("cannot determine contents of register EBX"); return -1;
+
+ cannot_fetch_register("EBX");
+
+ return -1;
}
- case UESP: *reg_content = thread_state.sp; PDBG("ESP = %8lx", *reg_content); return 0;
+
+ case UESP: fetch_register("ESP", ts.sp, *value); return 0;
+
case EBP:
- if (in_syscall(thread_state)) {
+
+ if (in_syscall(ts)) {
+
/* When in a syscall, the user EBP has been pushed onto the stack at address ESP+0 */
- *reg_content = genode_read_memory_byte((void*)(thread_state.sp + 0)) +
- (genode_read_memory_byte((void*)(thread_state.sp + 1)) << 8) +
- (genode_read_memory_byte((void*)(thread_state.sp + 2)) << 16) +
- (genode_read_memory_byte((void*)(thread_state.sp + 3)) << 24);
- PDBG("EBP = %8lx", *reg_content);
+ *value = genode_read_memory_byte((void*)(ts.sp + 0))
+ + (genode_read_memory_byte((void*)(ts.sp + 1)) << 8)
+ + (genode_read_memory_byte((void*)(ts.sp + 2)) << 16)
+ + (genode_read_memory_byte((void*)(ts.sp + 3)) << 24);
+
+ /* for the debug output, if enabled */
+ fetch_register("EBP", *value, *value);
+
return 0;
+
} else {
- PDBG("cannot determine contents of register EBP"); return -1;
+
+ cannot_fetch_register("EBP");
+
+ return -1;
}
- case ESI: PDBG("cannot determine contents of register ESI"); return -1;
- case EDI: PDBG("cannot determine contents of register EDI"); return -1;
- case EIP: *reg_content = thread_state.ip; PDBG("EIP = %8lx", *reg_content); return 0;
- case EFL: PDBG("cannot determine contents of register EFLAGS"); return -1;
- case CS: PDBG("cannot determine contents of register CS"); return -1;
- case SS: PDBG("cannot determine contents of register SS"); return -1;
- case DS: PDBG("cannot determine contents of register DS"); return -1;
- case ES: PDBG("cannot determine contents of register ES"); return -1;
- case FS: PDBG("cannot determine contents of register FS"); return -1;
- case GS: PDBG("cannot determine contents of register GS"); return -1;
+
+ case ESI: cannot_fetch_register("ESI"); return -1;
+ case EDI: cannot_fetch_register("EDI"); return -1;
+ case EIP: fetch_register("EIP", ts.ip, *value); return 0;
+ case EFL: cannot_fetch_register("EFL"); return -1;
+ case CS: cannot_fetch_register("CS"); return -1;
+ case SS: cannot_fetch_register("SS"); return -1;
+ case DS: cannot_fetch_register("DS"); return -1;
+ case ES: cannot_fetch_register("ES"); return -1;
+ case FS: cannot_fetch_register("FS"); return -1;
+ case GS: cannot_fetch_register("GS"); return -1;
+ default: PERR("unhandled register %d", regno); return -1;
}
+
} else {
+
switch((enum reg_index)regno)
{
- case EAX: *reg_content = thread_state.eax; PDBG("EAX = %8lx", *reg_content); return 0;
- case ECX: *reg_content = thread_state.ecx; PDBG("ECX = %8lx", *reg_content); return 0;
- case EDX: *reg_content = thread_state.edx; PDBG("EDX = %8lx", *reg_content); return 0;
- case EBX: *reg_content = thread_state.ebx; PDBG("EBX = %8lx", *reg_content); return 0;
- case UESP: *reg_content = thread_state.sp; PDBG("ESP = %8lx", *reg_content); return 0;
- case EBP: *reg_content = thread_state.ebp; PDBG("EBP = %8lx", *reg_content); return 0;
- case ESI: *reg_content = thread_state.esi; PDBG("ESI = %8lx", *reg_content); return 0;
- case EDI: *reg_content = thread_state.edi; PDBG("EDI = %8lx", *reg_content); return 0;
- case EIP: *reg_content = thread_state.ip; PDBG("EIP = %8lx", *reg_content); return 0;
- case EFL: *reg_content = thread_state.eflags; PDBG("EFLAGS = %8lx", *reg_content); return 0;
- case CS: PDBG("cannot determine contents of register CS"); return -1;
- case SS: PDBG("cannot determine contents of register SS"); return -1;
- case DS: PDBG("cannot determine contents of register DS"); return -1;
- case ES: PDBG("cannot determine contents of register ES"); return -1;
- case FS: *reg_content = thread_state.fs; PDBG("FS = %8lx", *reg_content); return 0;
- case GS: *reg_content = thread_state.gs; PDBG("GS = %8lx", *reg_content); return 0;
+ case EAX: fetch_register("EAX", ts.eax, *value); return 0;
+ case ECX: fetch_register("ECX", ts.ecx, *value); return 0;
+ case EDX: fetch_register("EDX", ts.edx, *value); return 0;
+ case EBX: fetch_register("EBX", ts.ebx, *value); return 0;
+ case UESP: fetch_register("ESP", ts.sp, *value); return 0;
+ case EBP: fetch_register("EBP", ts.ebp, *value); return 0;
+ case ESI: fetch_register("ESI", ts.esi, *value); return 0;
+ case EDI: fetch_register("EDI", ts.edi, *value); return 0;
+ case EIP: fetch_register("EIP", ts.ip, *value); return 0;
+ case EFL: fetch_register("EFL", ts.eflags, *value); return 0;
+ case CS: cannot_fetch_register("CS"); return -1;
+ case SS: cannot_fetch_register("SS"); return -1;
+ case DS: cannot_fetch_register("DS"); return -1;
+ case ES: cannot_fetch_register("ES"); return -1;
+ case FS: fetch_register("FS", ts.fs, *value); return 0;
+ case GS: fetch_register("GS", ts.gs, *value); return 0;
+ default: PERR("unhandled register %d", regno); return -1;
}
}
return -1;
}
-extern "C" void genode_store_register(int regno, unsigned long reg_content)
+extern "C" void genode_store_register(int regno, unsigned long value)
{
- Thread_state thread_state;
+ Thread_state ts;
- try { thread_state = get_current_thread_state(); }
- catch (...) { return; }
+ try { ts = get_current_thread_state(); }
+ catch (...) {
+ PERR("%s: could not get current thread state", __PRETTY_FUNCTION__);
+ return;
+ }
- if (in_syscall(thread_state)) {
+ if (in_syscall(ts)) {
PDBG("cannot set registers while thread is in syscall");
return;
}
switch((enum reg_index)regno)
{
- case EAX: thread_state.eax = reg_content; PDBG("EAX = %8lx", reg_content); break;
- case ECX: thread_state.ecx = reg_content; PDBG("ECX = %8lx", reg_content); break;
- case EDX: thread_state.edx = reg_content; PDBG("EDX = %8lx", reg_content); break;
- case EBX: thread_state.ebx = reg_content; PDBG("EBX = %8lx", reg_content); break;
- case UESP: thread_state.sp = reg_content; PDBG("ESP = %8lx", reg_content); break;
- case EBP: thread_state.ebp = reg_content; PDBG("EBP = %8lx", reg_content); break;
- case ESI: thread_state.esi = reg_content; PDBG("ESI = %8lx", reg_content); break;
- case EDI: thread_state.edi = reg_content; PDBG("EDI = %8lx", reg_content); break;
- case EIP: thread_state.ip = reg_content; PDBG("EIP = %8lx", reg_content); break;
- case EFL: thread_state.eflags = reg_content; PDBG("EFL = %8lx", reg_content); break;
- case CS: PDBG("cannot set contents of register CS"); PDBG(" CS = %8lx", reg_content); break;
- case SS: PDBG("cannot set contents of register SS"); PDBG(" SS = %8lx", reg_content); break;
- case DS: PDBG("cannot set contents of register DS"); PDBG(" DS = %8lx", reg_content); break;
- case ES: PDBG("cannot set contents of register ES"); PDBG(" ES = %8lx", reg_content); break;
- case FS: thread_state.fs = reg_content; PDBG(" FS = %8lx", reg_content); break;
- case GS: thread_state.gs = reg_content; PDBG(" GS = %8lx", reg_content); break;
-
+ case EAX: if (!store_register("EAX", ts.eax, value)) return; break;
+ case ECX: if (!store_register("ECX", ts.ecx, value)) return; break;
+ case EDX: if (!store_register("EDX", ts.edx, value)) return; break;
+ case EBX: if (!store_register("EBX", ts.ebx, value)) return; break;
+ case UESP: if (!store_register("ESP", ts.sp, value)) return; break;
+ case EBP: if (!store_register("EBP", ts.ebp, value)) return; break;
+ case ESI: if (!store_register("ESI", ts.esi, value)) return; break;
+ case EDI: if (!store_register("EDI", ts.edi, value)) return; break;
+ case EIP: if (!store_register("EIP", ts.ip, value)) return; break;
+ case EFL: if (!store_register("EFL", ts.eflags, value)) return; break;
+ case CS: cannot_store_register("CS", value); return;
+ case SS: cannot_store_register("SS", value); return;
+ case DS: cannot_store_register("DS", value); return;
+ case ES: cannot_store_register("ES", value); return;
+ case FS: if (!store_register("FS ", ts.fs, value)) return; break;
+ case GS: if (!store_register("GS ", ts.gs, value)) return; break;
+ default: PERR("unhandled register %d", regno); return;
}
- set_current_thread_state(thread_state);
+ set_current_thread_state(ts);
}
diff --git a/repos/ports/src/lib/gdbserver_platform/spec/linux_x86_32/low.cc b/repos/ports/src/lib/gdbserver_platform/spec/linux_x86_32/low.cc
deleted file mode 100644
index ada2ce068e..0000000000
--- a/repos/ports/src/lib/gdbserver_platform/spec/linux_x86_32/low.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * \brief Linux(x86_32)-specific helper functions for GDB server
- * \author Christian Prochaska
- * \date 2011-05-06
- */
-
-/*
- * Copyright (C) 2011-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.
- */
-
-extern "C" {
-#define private _private
-#include "genode-low.h"
-#define _private private
-}
-
-#include
-#include "i386.h"
-#include "cpu_session_component.h"
-#include "gdbserver_platform_helper.h"
-#include "gdb_stub_thread.h"
-
-using namespace Genode;
-
-extern "C" int genode_fetch_register(int regno, unsigned long *reg_content)
-{
- Thread_state thread_state;
-
- try { thread_state = get_current_thread_state(); }
- catch (...) { return 0; }
-
- switch((enum reg_index)regno)
- {
- case EAX: PDBG("cannot determine contents of register EAX"); return -1;
- case ECX: PDBG("cannot determine contents of register ECX"); return -1;
- case EDX: PDBG("cannot determine contents of register EDX"); return -1;
- case EBX: PDBG("cannot determine contents of register EBX"); return -1;
- case UESP: *reg_content = thread_state.sp; PDBG("ESP = %8lx", *reg_content); return 0;
- case EBP: PDBG("cannot determine contents of register EBP"); return -1;
- case ESI: PDBG("cannot determine contents of register ESI"); return -1;
- case EDI: PDBG("cannot determine contents of register EDI"); return -1;
- case EIP: *reg_content = thread_state.ip; PDBG("EIP = %8lx", *reg_content); return 0;
- case EFL: PDBG("cannot determine contents of register EFLAGS"); return -1;
- case CS: PDBG("cannot determine contents of register CS"); return -1;
- case SS: PDBG("cannot determine contents of register SS"); return -1;
- case DS: PDBG("cannot determine contents of register DS"); return -1;
- case ES: PDBG("cannot determine contents of register ES"); return -1;
- case FS: PDBG("cannot determine contents of register FS"); return -1;
- case GS: PDBG("cannot determine contents of register GS"); return -1;
- }
-
- return -1;
-}
-
-
-extern "C" void genode_store_register(int regno, unsigned long reg_content)
-{
- PDBG("not implemented yet for this platform");
-}
-
diff --git a/repos/ports/src/lib/gdbserver_platform/spec/nova/native_cpu.cc b/repos/ports/src/lib/gdbserver_platform/spec/nova/native_cpu.cc
new file mode 100644
index 0000000000..d5caf0d7bc
--- /dev/null
+++ b/repos/ports/src/lib/gdbserver_platform/spec/nova/native_cpu.cc
@@ -0,0 +1,79 @@
+/*
+ * \brief NOVA-specific 'Native_cpu' setup
+ * \author Christian Prochaska
+ * \date 2016-05-13
+ */
+
+/*
+ * Copyright (C) 2016 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.
+ */
+
+
+/* Genode includes */
+#include
+
+/* GDB monitor includes */
+#include "cpu_session_component.h"
+#include "cpu_thread_component.h"
+
+
+namespace Gdb_monitor {
+ class Native_cpu_component;
+}
+
+
+using namespace Genode;
+
+
+class Gdb_monitor::Native_cpu_component : public Rpc_object
+{
+ private:
+
+ Cpu_session_component &_cpu_session_component;
+ Nova_native_cpu_client _nova_native_cpu;
+
+ public:
+
+ Native_cpu_component(Cpu_session_component &cpu_session_component)
+ : _cpu_session_component(cpu_session_component),
+ _nova_native_cpu(_cpu_session_component.parent_cpu_session().native_cpu())
+ {
+ _cpu_session_component.thread_ep().manage(this);
+ }
+
+ ~Native_cpu_component()
+ {
+ _cpu_session_component.thread_ep().dissolve(this);
+ }
+
+ Native_capability pager_cap(Thread_capability thread_cap) override
+ {
+ Cpu_thread_component *cpu_thread = _cpu_session_component.lookup_cpu_thread(thread_cap);
+ return _nova_native_cpu.pager_cap(cpu_thread->parent_thread_cap());
+ }
+};
+
+
+Capability
+Gdb_monitor::Cpu_session_component::_setup_native_cpu()
+{
+ Native_cpu_component *native_cpu_component =
+ new (_md_alloc) Native_cpu_component(*this);
+
+ return native_cpu_component->cap();
+}
+
+
+void Gdb_monitor::Cpu_session_component::_cleanup_native_cpu()
+{
+ Native_cpu_component *native_cpu_component = nullptr;
+ _thread_ep->apply(_native_cpu_cap, [&] (Native_cpu_component *c) { native_cpu_component = c; });
+
+ if (!native_cpu_component) return;
+
+ destroy(_md_alloc, native_cpu_component);
+}
diff --git a/repos/ports/src/lib/gdbserver_platform/spec/nova_x86_32/low.cc b/repos/ports/src/lib/gdbserver_platform/spec/nova_x86_32/low.cc
index 53a48cf03c..e8573e4c3a 100644
--- a/repos/ports/src/lib/gdbserver_platform/spec/nova_x86_32/low.cc
+++ b/repos/ports/src/lib/gdbserver_platform/spec/nova_x86_32/low.cc
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2012-2013 Genode Labs GmbH
+ * Copyright (C) 2012-2016 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.
@@ -14,43 +14,75 @@
#include "i386.h"
#include "cpu_session_component.h"
#include "gdbserver_platform_helper.h"
-#include "gdb_stub_thread.h"
+#include "genode_child_resources.h"
using namespace Genode;
-extern "C" int genode_fetch_register(int regno, unsigned long *reg_content)
+extern "C" int genode_fetch_register(int regno, unsigned long *value)
{
- Thread_state thread_state;
+ Thread_state ts;
- try { thread_state = get_current_thread_state(); }
- catch (...) { return -1; }
+ try { ts = get_current_thread_state(); }
+ catch (...) {
+ PERR("%s: could not get current thread state", __PRETTY_FUNCTION__);
+ return -1;
+ }
switch((enum reg_index)regno)
{
- case EAX: *reg_content = thread_state.eax; return 0;
- case ECX: *reg_content = thread_state.ecx; return 0;
- case EDX: *reg_content = thread_state.edx; return 0;
- case EBX: *reg_content = thread_state.ebx; return 0;
- case UESP: *reg_content = thread_state.sp; return 0;
- case EBP: *reg_content = thread_state.ebp; return 0;
- case ESI: *reg_content = thread_state.esi; return 0;
- case EDI: *reg_content = thread_state.edi; return 0;
- case EIP: *reg_content = thread_state.ip; return 0;
- case EFL: *reg_content = thread_state.eflags; return 0;
- case CS: return -1;
- case SS: return -1;
- case DS: return -1;
- case ES: return -1;
- case FS: *reg_content = thread_state.fs; return 0;
- case GS: *reg_content = thread_state.gs; return 0;
+ case EAX: fetch_register("EAX", ts.eax, *value); return 0;
+ case ECX: fetch_register("ECX", ts.ecx, *value); return 0;
+ case EDX: fetch_register("EDX", ts.edx, *value); return 0;
+ case EBX: fetch_register("EBX", ts.ebx, *value); return 0;
+ case UESP: fetch_register("ESP", ts.sp, *value); return 0;
+ case EBP: fetch_register("EBP", ts.ebp, *value); return 0;
+ case ESI: fetch_register("ESI", ts.esi, *value); return 0;
+ case EDI: fetch_register("EDI", ts.edi, *value); return 0;
+ case EIP: fetch_register("EIP", ts.ip, *value); return 0;
+ case EFL: fetch_register("EFL", ts.eflags, *value); return 0;
+ case CS: cannot_fetch_register("CS"); return -1;
+ case SS: cannot_fetch_register("SS"); return -1;
+ case DS: cannot_fetch_register("DS"); return -1;
+ case ES: cannot_fetch_register("ES"); return -1;
+ case FS: cannot_fetch_register("FS"); return -1;
+ case GS: cannot_fetch_register("GS"); return -1;
+ default: PERR("unhandled register %d", regno); return -1;
}
return -1;
}
-extern "C" void genode_store_register(int regno, unsigned long reg_content)
+extern "C" void genode_store_register(int regno, unsigned long value)
{
- PDBG("not implemented yet for this platform");
-}
+ Thread_state ts;
+ try { ts = get_current_thread_state(); }
+ catch (...) {
+ PERR("%s: could not get current thread state", __PRETTY_FUNCTION__);
+ return;
+ }
+
+ switch ((enum reg_index)regno)
+ {
+ case EAX: if (!store_register("EAX", ts.eax, value)) return; break;
+ case ECX: if (!store_register("ECX", ts.ecx, value)) return; break;
+ case EDX: if (!store_register("EDX", ts.edx, value)) return; break;
+ case EBX: if (!store_register("EBX", ts.ebx, value)) return; break;
+ case UESP: if (!store_register("ESP", ts.sp, value)) return; break;
+ case EBP: if (!store_register("EBP", ts.ebp, value)) return; break;
+ case ESI: if (!store_register("ESI", ts.esi, value)) return; break;
+ case EDI: if (!store_register("EDI", ts.edi, value)) return; break;
+ case EIP: if (!store_register("EIP", ts.ip, value)) return; break;
+ case EFL: if (!store_register("EFL", ts.eflags, value)) return; break;
+ case CS: cannot_store_register("CS", value); return;
+ case SS: cannot_store_register("SS", value); return;
+ case DS: cannot_store_register("DS", value); return;
+ case ES: cannot_store_register("ES", value); return;
+ case FS: cannot_store_register("FS", value); return;
+ case GS: cannot_store_register("GS", value); return;
+ default: PERR("unhandled register %d", regno); return;
+ }
+
+ set_current_thread_state(ts);
+}
diff --git a/repos/ports/src/lib/gdbserver_platform/spec/okl4_x86/low.cc b/repos/ports/src/lib/gdbserver_platform/spec/okl4_x86/low.cc
deleted file mode 100644
index e296eb1196..0000000000
--- a/repos/ports/src/lib/gdbserver_platform/spec/okl4_x86/low.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * \brief OKL4(x86)-specific helper functions for GDB server
- * \author Christian Prochaska
- * \date 2011-05-06
- */
-
-/*
- * Copyright (C) 2011-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.
- */
-
-extern "C" {
-#define private _private
-#include "genode-low.h"
-#define _private private
-}
-
-#include
-#include "i386.h"
-#include "cpu_session_component.h"
-#include "gdb_stub_thread.h"
-#include "gdbserver_platform_helper.h"
-
-using namespace Genode;
-
-extern "C" int genode_fetch_register(int regno, unsigned long *reg_content)
-{
- Thread_state thread_state;
-
- try { thread_state = get_current_thread_state(); }
- catch (...) { return 0; }
-
- switch((enum reg_index)regno)
- {
- case EAX: *reg_content = thread_state.eax; PDBG("EAX = %8lx", *reg_content); return 0;
- case ECX: *reg_content = thread_state.ecx; PDBG("ECX = %8lx", *reg_content); return 0;
- case EDX: *reg_content = thread_state.edx; PDBG("EDX = %8lx", *reg_content); return 0;
- case EBX: *reg_content = thread_state.ebx; PDBG("EBX = %8lx", *reg_content); return 0;
- case UESP: *reg_content = thread_state.sp; PDBG("ESP = %8lx", *reg_content); return 0;
- case EBP:
- /*
- * When in a syscall, the user EBP has been pushed onto the stack at address ESP+4
- *
- * looking for syscall pattern:
- * EIP-2: 0f 34 sysenter
- */
- if ((genode_read_memory_byte((void*)(thread_state.ip - 1)) == 0x34) &&
- (genode_read_memory_byte((void*)(thread_state.ip - 2)) == 0x0f)) {
- *reg_content = genode_read_memory_byte((void*)(thread_state.sp + 4)) +
- (genode_read_memory_byte((void*)(thread_state.sp + 5)) << 8) +
- (genode_read_memory_byte((void*)(thread_state.sp + 6)) << 16) +
- (genode_read_memory_byte((void*)(thread_state.sp + 7)) << 24);
- PDBG("EBP = %8lx", *reg_content);
- return 0;
- } else {
- *reg_content = thread_state.ebp;
- PDBG("EBP = %8lx", *reg_content);
- return 0;
- }
- case ESI: *reg_content = thread_state.esi; PDBG("ESI = %8lx", *reg_content); return 0;
- case EDI: *reg_content = thread_state.edi; PDBG("EDI = %8lx", *reg_content); return 0;
- case EIP: *reg_content = thread_state.ip; PDBG("EIP = %8lx", *reg_content); return 0;
- case EFL: *reg_content = thread_state.eflags; PDBG("EFLAGS = %8lx", *reg_content); return 0;
- case CS: PDBG("cannot determine contents of register CS"); return -1;
- case SS: PDBG("cannot determine contents of register SS"); return -1;
- case DS: PDBG("cannot determine contents of register DS"); return -1;
- case ES: PDBG("cannot determine contents of register ES"); return -1;
- case FS: PDBG("cannot determine contents of register FS"); return -1;
- case GS: PDBG("cannot determine contents of register GS"); return -1;
- }
-
- return -1;
-}
-
-
-extern "C" void genode_store_register(int regno, unsigned long reg_content)
-{
- PDBG("not implemented yet for this platform");
-}
-
diff --git a/repos/ports/src/lib/gdbserver_platform/spec/pistachio_x86/low.cc b/repos/ports/src/lib/gdbserver_platform/spec/pistachio_x86/low.cc
deleted file mode 100644
index 6046dd7b3c..0000000000
--- a/repos/ports/src/lib/gdbserver_platform/spec/pistachio_x86/low.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * \brief Pistachio(x86)-specific helper functions for GDB server
-// * \author Christian Prochaska
- * \date 2011-05-06
- */
-
-/*
- * Copyright (C) 2011-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.
- */
-
-extern "C" {
-#define private _private
-#include "genode-low.h"
-#define _private private
-}
-
-#include
-#include "i386.h"
-#include "cpu_session_component.h"
-#include "gdbserver_platform_helper.h"
-#include "gdb_stub_thread.h"
-
-using namespace Genode;
-
-extern "C" int genode_fetch_register(int regno, unsigned long *reg_content)
-{
- Thread_state thread_state;
-
- try { thread_state = get_current_thread_state(); }
- catch (...) { return 0; }
-
- switch((enum reg_index)regno)
- {
- case EAX: PDBG("cannot determine contents of register EAX"); return -1;
- case ECX: PDBG("cannot determine contents of register ECX"); return -1;
- case EDX: PDBG("cannot determine contents of register EDX"); return -1;
- case EBX: PDBG("cannot determine contents of register EBX"); return -1;
- case UESP: *reg_content = thread_state.sp; PDBG("ESP = %8lx", *reg_content); return 0;
- case EBP:
- /*
- * When in a syscall, the user EBP has been pushed onto the stack at address ESP+0
- *
- * looking for syscall pattern:
- * EIP-6: 55 push %ebp
- * EIP-5: e8 .. call ...
- * EIP: 89 e9 mov %ebp, %ecx
- */
- if ((genode_read_memory_byte((void*)(thread_state.ip + 1)) == 0xe9) &&
- (genode_read_memory_byte((void*)(thread_state.ip)) == 0x89) &&
- (genode_read_memory_byte((void*)(thread_state.ip - 5)) == 0xe8) &&
- (genode_read_memory_byte((void*)(thread_state.ip - 6)) == 0x55)) {
- *reg_content = genode_read_memory_byte((void*)(thread_state.sp + 0)) +
- (genode_read_memory_byte((void*)(thread_state.sp + 1)) << 8) +
- (genode_read_memory_byte((void*)(thread_state.sp + 2)) << 16) +
- (genode_read_memory_byte((void*)(thread_state.sp + 3)) << 24);
- PDBG("ESP = %8lx", *reg_content);
- return 0;
- } else {
- PDBG("cannot determine contents of register EBP"); return -1;
- }
- case ESI: PDBG("cannot determine contents of register ESI"); return -1;
- case EDI: PDBG("cannot determine contents of register EDI"); return -1;
- case EIP: *reg_content = thread_state.ip; PDBG("EIP = %8lx", *reg_content); return 0;
- case EFL: PDBG("cannot determine contents of register EFLAGS"); return -1;
- case CS: PDBG("cannot determine contents of register CS"); return -1;
- case SS: PDBG("cannot determine contents of register SS"); return -1;
- case DS: PDBG("cannot determine contents of register DS"); return -1;
- case ES: PDBG("cannot determine contents of register ES"); return -1;
- case FS: PDBG("cannot determine contents of register FS"); return -1;
- case GS: PDBG("cannot determine contents of register GS"); return -1;
- }
-
- return -1;
-}
-
-
-extern "C" void genode_store_register(int regno, unsigned long reg_content)
-{
- PDBG("not implemented yet for this platform");
-}
-
diff --git a/repos/ports/src/test/gdb_monitor/main.cc b/repos/ports/src/test/gdb_monitor/main.cc
index 2f36849aa5..018eea41bf 100644
--- a/repos/ports/src/test/gdb_monitor/main.cc
+++ b/repos/ports/src/test/gdb_monitor/main.cc
@@ -29,7 +29,12 @@ class Test_thread : public Genode::Thread_deprecated<2*4096>
Test_thread() : Thread_deprecated("test") { }
- void func()
+ void step_func()
+ {
+ /* nothing */
+ }
+
+ void sigsegv_func()
{
/*
* make sure that the main thread is sleeping in
@@ -43,7 +48,9 @@ class Test_thread : public Genode::Thread_deprecated<2*4096>
void entry() /* set a breakpoint here to test the 'info threads' command */
{
- func();
+ step_func();
+
+ sigsegv_func();
Genode::sleep_forever();
}
diff --git a/repos/ports/src/test/gdb_monitor/target.mk b/repos/ports/src/test/gdb_monitor/target.mk
index 72a18a09a6..00b7e5909e 100644
--- a/repos/ports/src/test/gdb_monitor/target.mk
+++ b/repos/ports/src/test/gdb_monitor/target.mk
@@ -1,3 +1,5 @@
TARGET = test-gdb_monitor
SRC_CC = main.cc
LIBS = libc
+
+CC_OLEVEL = -O0