gdb_monitor: API transition

Issue #1987
This commit is contained in:
Christian Prochaska 2017-01-04 11:38:39 +01:00 committed by Norman Feske
parent 537dde1f40
commit 7a0bcbbccb
35 changed files with 735 additions and 891 deletions

View File

@ -0,0 +1 @@
LIBS += gdbserver_platform_foc

View File

@ -0,0 +1 @@
LIBS += gdbserver_platform_nova

View File

@ -1,3 +0,0 @@
SRC_CC = spec/nova_x86_32/low.cc native_cpu.cc
include $(REP_DIR)/lib/mk/spec/x86_32/gdbserver_platform.inc

View File

@ -1,3 +0,0 @@
SRC_CC = spec/nova_x86_64/low.cc native_cpu.cc
include $(REP_DIR)/lib/mk/spec/x86_64/gdbserver_platform.inc

View File

@ -3,4 +3,4 @@ SRC_CC = spec/foc_x86_32/low.cc \
LIBS += syscall-foc LIBS += syscall-foc
include $(REP_DIR)/lib/mk/spec/x86_32/gdbserver_platform.inc include $(REP_DIR)/lib/mk/spec/x86_32/gdbserver_platform_x86_32.inc

View File

@ -0,0 +1,3 @@
SRC_CC = spec/nova_x86_32/low.cc native_cpu.cc
include $(REP_DIR)/lib/mk/spec/x86_32/gdbserver_platform_x86_32.inc

View File

@ -0,0 +1,3 @@
SRC_CC = spec/nova_x86_64/low.cc native_cpu.cc
include $(REP_DIR)/lib/mk/spec/x86_64/gdbserver_platform_x86_64.inc

View File

@ -149,7 +149,30 @@ run_genode_until {.*\[init -> gdb_monitor\].*} 30
puts "GDB monitor is up, starting GDB in a new terminal" puts "GDB monitor is up, starting GDB in a new terminal"
exec [terminal] -e "[gdb] bin/nitpicker -ex \"target remote localhost:$local_port\"" & source ${genode_dir}/repos/ports/run/gdb_monitor.inc
# GDB loads symbols from 'bin/ld.lib.so'
if { [have_spec nova] } {
exec ln -sf ld-nova.lib.so bin/ld.lib.so
}
if { [have_spec foc] } {
exec ln -sf ld-foc.lib.so bin/ld.lib.so
}
set gdb_target_binary "nitpicker"
# sequence of GDB commands to execute at startup
set gdb_cmds ""
append gdb_cmds "-ex \"target remote localhost:$local_port\" "
append gdb_cmds [gdb_initial_breakpoint_cmds $gdb_target_binary]
# ask the user for confirmations again
append gdb_cmds {-ex "set interactive-mode auto" }
puts "command: [gdb] bin/ld.lib.so $gdb_cmds"
exec [terminal] -e "[gdb] bin/ld.lib.so $gdb_cmds" &
interact -i [output_spawn_id] interact -i [output_spawn_id]

View File

@ -4,14 +4,12 @@
# \date 2013-09-04 # \date 2013-09-04
# #
proc gdb_main_breakpoint_cmds { target_binary_name } { proc gdb_initial_breakpoint_cmds { target_binary_name } {
# #
# We set a break in the 'main()' function of a dynamically linked # We set a break in the 'binary_ready_hook_for_gdb()' function in the
# application by using the following gdb command sequence. It's important that # dynamic linker and load the symbols of the application by using the
# the 'main()' breakpoint gets set before the 'sharedlibrary' command is # following gdb command sequence.
# executed. Otherwise the breakpoint would get set in ld.lib.so's main()
# function.
# #
set gdb_cmds "" set gdb_cmds ""
@ -31,20 +29,11 @@ proc gdb_main_breakpoint_cmds { target_binary_name } {
# load the symbols of the test application # load the symbols of the test application
append gdb_cmds "-ex \"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" }
# set search path for "sharedlibrary" to bin # set search path for "sharedlibrary" to bin
append gdb_cmds {-ex "set solib-search-path bin" } append gdb_cmds {-ex "set solib-search-path bin" }
# load the symbols of loaded shared libraries # load the symbols of loaded shared libraries
append gdb_cmds {-ex "sharedlibrary" } append gdb_cmds {-ex "sharedlibrary" }
# continue execution until the breakpoint triggers
append gdb_cmds {-ex "c" }
# delete the 'main()' breakpoint
append gdb_cmds {-ex "delete 2" }
return $gdb_cmds return $gdb_cmds
} }

View File

@ -90,7 +90,7 @@ install_config $config
# generic modules # generic modules
set boot_modules { set boot_modules {
core init timer core init timer
ld.lib.so libc.lib.so libc_pipe.lib.so libc_terminal.lib.so ld.lib.so libc.lib.so libm.lib.so libc_pipe.lib.so libc_terminal.lib.so
uart_drv uart_drv
gdb_monitor test-gdb_monitor gdb_monitor test-gdb_monitor
} }
@ -120,12 +120,20 @@ puts "GDB monitor is up, starting GDB"
source ${genode_dir}/repos/ports/run/gdb_monitor.inc source ${genode_dir}/repos/ports/run/gdb_monitor.inc
# GDB loads symbols from 'bin/ld.lib.so'
if { [have_spec nova] } {
exec ln -sf ld-nova.lib.so bin/ld.lib.so
}
if { [have_spec foc] } {
exec ln -sf ld-foc.lib.so bin/ld.lib.so
}
set gdb_target_binary "test-gdb_monitor" set gdb_target_binary "test-gdb_monitor"
# sequence of GDB commands to execute at startup # sequence of GDB commands to execute at startup
set gdb_cmds "" set gdb_cmds ""
append gdb_cmds {-ex "target remote localhost:$local_port" } append gdb_cmds {-ex "target remote localhost:$local_port" }
append gdb_cmds [gdb_main_breakpoint_cmds $gdb_target_binary] append gdb_cmds [gdb_initial_breakpoint_cmds $gdb_target_binary]
# run GDB and redirect stderr to stdio to get the relevant output into the expect buffer # 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 eval spawn [gdb] bin/ld.lib.so -n $gdb_cmds 2&>1
@ -137,11 +145,19 @@ puts ""
run_genode_until {\(gdb\)} 60 $gdb_id run_genode_until {\(gdb\)} 60 $gdb_id
send "b main\n"
run_genode_until {\(gdb\)} 20 $gdb_id
send "c\n"
run_genode_until {\(gdb\)} 20 $gdb_id
if {![regexp {Breakpoint 2, main ()} $output]} { if {![regexp {Breakpoint 2, main ()} $output]} {
puts stderr "*** Error: Breakpoint in main() did not trigger" puts stderr "*** Error: Breakpoint in main() did not trigger"
exit -1 exit -1
} }
send "delete 2\n"
run_genode_until {\(gdb\)} 20 $gdb_id
puts "\n" puts "\n"
puts "----- test: breakpoint in shared library -----" puts "----- test: breakpoint in shared library -----"
puts "" puts ""

View File

@ -77,7 +77,7 @@ install_config $config
# generic modules # generic modules
set boot_modules { set boot_modules {
core init timer core init timer
ld.lib.so libc.lib.so libc_pipe.lib.so libc_terminal.lib.so ld.lib.so libc.lib.so libm.lib.so libc_pipe.lib.so libc_terminal.lib.so
uart_drv uart_drv
gdb_monitor test-gdb_monitor gdb_monitor test-gdb_monitor
} }
@ -106,18 +106,26 @@ puts "GDB monitor is up, starting GDB in a new terminal"
source ${genode_dir}/repos/ports/run/gdb_monitor.inc source ${genode_dir}/repos/ports/run/gdb_monitor.inc
# GDB loads symbols from 'bin/ld.lib.so'
if { [have_spec nova] } {
exec ln -sf ld-nova.lib.so bin/ld.lib.so
}
if { [have_spec foc] } {
exec ln -sf ld-foc.lib.so bin/ld.lib.so
}
set gdb_target_binary "test-gdb_monitor" set gdb_target_binary "test-gdb_monitor"
# sequence of GDB commands to execute at startup # sequence of GDB commands to execute at startup
set gdb_cmds "" set gdb_cmds ""
append gdb_cmds "-ex \"target remote localhost:$local_port\" " append gdb_cmds "-ex \"target remote localhost:$local_port\" "
append gdb_cmds [gdb_main_breakpoint_cmds $gdb_target_binary] append gdb_cmds [gdb_initial_breakpoint_cmds $gdb_target_binary]
# ask the user for confirmations again # ask the user for confirmations again
append gdb_cmds {-ex "set interactive-mode auto" } append gdb_cmds {-ex "set interactive-mode auto" }
puts "command: [gdb] bin/$gdb_target_binary $gdb_cmds" puts "command: [gdb] bin/ld.lib.so $gdb_cmds"
exec [terminal] -e "[gdb] bin/ld.lib.so $gdb_cmds" & exec [terminal] -e "[gdb] bin/ld.lib.so $gdb_cmds" &

View File

@ -53,10 +53,16 @@ set config {
<config> <config>
<target name="test-gdb_monitor_target_config"> <target name="test-gdb_monitor_target_config">
<config> <config>
<libc stdout="/dev/log" stderr="/dev/log">
<vfs> <dir name="dev"> <log/> </dir> </vfs>
</libc>
<test_config_subnode/> <test_config_subnode/>
</config> </config>
</target> </target>
<preserve name="RAM" quantum="3M"/> <preserve name="RAM" quantum="3M"/>
<libc stdout="/dev/log" stderr="/dev/log">
<vfs> <dir name="dev"> <log/> </dir> </vfs>
</libc>
</config> </config>
</start> </start>
</config> </config>
@ -98,15 +104,29 @@ run_genode_until {.*Remote debugging using /dev/terminal.*} 30
puts "GDB monitor is up, starting GDB in a new terminal" puts "GDB monitor is up, starting GDB in a new terminal"
source ${genode_dir}/repos/ports/run/gdb_monitor.inc
# GDB loads symbols from 'bin/ld.lib.so'
if { [have_spec nova] } {
exec ln -sf ld-nova.lib.so bin/ld.lib.so
}
if { [have_spec foc] } {
exec ln -sf ld-foc.lib.so bin/ld.lib.so
}
set gdb_target_binary "test-gdb_monitor_target_config"
# sequence of GDB commands to execute at startup # sequence of GDB commands to execute at startup
set gdb_cmds "" set gdb_cmds ""
append gdb_cmds "-ex \"target remote localhost:$local_port\" " append gdb_cmds "-ex \"target remote localhost:$local_port\" "
append gdb_cmds [gdb_initial_breakpoint_cmds $gdb_target_binary]
# continue execution # continue execution
append gdb_cmds {-ex "c" } append gdb_cmds {-ex "c" }
exec [terminal] -e "[gdb] bin/test-gdb_monitor_target_config $gdb_cmds" & exec [terminal] -e "[gdb] bin/ld.lib.so $gdb_cmds" &
interact interact -i [output_spawn_id]
# vi: set ft=tcl : # vi: set ft=tcl :

View File

@ -1,5 +1,5 @@
if {![have_spec foc] && ![have_spec nova]} { if {!([have_spec nova] || ([have_spec foc] && [have_spec 32bit]))} {
puts "\nThe Noux GDB scenario is supported on NOVA and Fiasco.OC only\n" puts "\nThe Noux GDB scenario is only supported for NOVA or 32-bit Fiasco.OC\n"
exit 0 exit 0
} }
@ -26,7 +26,10 @@ set build_components {
app/gdb_monitor app/gdb_monitor
} }
lappend_if [have_spec gpio] build_components drivers/gpio lappend_if [have_spec gpio] build_components drivers/gpio
lappend_if [have_spec nova] build_components lib/ld/nova
lappend_if [have_spec foc] build_components lib/ld/foc
lappend build_components noux-pkg/[noux_gdb_pkg_name] lappend build_components noux-pkg/[noux_gdb_pkg_name]
@ -39,11 +42,20 @@ append_platform_drv_build_components
build $build_components build $build_components
# GDB loads symbols from 'bin/ld.lib.so'
if { [have_spec nova] } {
exec ln -sf ld-nova.lib.so bin/ld.lib.so
}
if { [have_spec foc] } {
exec ln -sf ld-foc.lib.so bin/ld.lib.so
}
# names of the binaries needed for the GDB monitor test # names of the binaries needed for the GDB monitor test
set gdb_target_binaries { set gdb_target_binaries {
test-gdb_monitor test-gdb_monitor
ld.lib.so ld.lib.so
libc.lib.so libc.lib.so
libm.lib.so
} }
lappend gdb_target_binaries ${gdb_target_binary_name} lappend gdb_target_binaries ${gdb_target_binary_name}

View File

@ -1,162 +0,0 @@
if {![have_spec foc] || ![have_spec 32bit]} {
puts "\nThe Noux GDB scenario is supported on 32-bit Fiasco.OC only\n"
exit 0
}
source ${genode_dir}/repos/ports/run/noux_gdb.inc
#
# Uncomment the following line when working on the GDB source code. Otherwise,
# the package may get recompiled, yet it does not get reinstalled into 'bin/'.
#
#exec rm -rf noux-pkg/[noux_gdb_pkg_name]/ bin/[noux_gdb_pkg_name]/
set build_components {
core init drivers/timer noux lib/libc_noux
drivers/uart
server/terminal_mux server/terminal_crosslink
server/terminal_log
app/cli_monitor
app/gdb_monitor
}
lappend build_components noux-pkg/[noux_gdb_pkg_name]
lappend build_components test/gdb_monitor
set gdb_target_binary_name test-gdb_monitor
build $build_components
# names of the binaries needed for the GDB monitor test
set gdb_target_binaries {
ld.lib.so
libc.lib.so
}
lappend gdb_target_binaries ${gdb_target_binary_name}
create_gdb_tar
create_binary_and_source_tars "gdb_target" ${gdb_target_binaries}
create_boot_directory
append config {
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
<service name="LOG"/>
<service name="RAM"/>
<service name="RM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="IRQ"/>
<service name="IO_PORT"/>
<service name="IO_MEM"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
<route> <any-service> <parent/> </any-service> </route>
</start>
<start name="uart_drv">}
# use kernel debugger as UART on Fiasco.OC
append_if [have_spec foc] config {
<binary name="kdb_uart_drv"/>}
append config {
<resource name="RAM" quantum="1M"/>
<provides>
<service name="Uart"/>
<service name="Terminal"/>
</provides>
<config> }
# on Fiasco.OC the kdb_uart_drv is always UART 0
append_if [have_spec foc] config {
<policy label_prefix="terminal_mux" uart="0" detect_size="yes"/> }
# on all other kernels, direct terminal_mux to UART 1 (Qemu stdio, see below)
append_if [expr ![have_spec foc]] config {
<policy label_prefix="terminal_mux" uart="1" detect_size="yes"/> }
append config {
</config>
<route> <any-service> <parent/> <any-child/> </any-service> </route>
</start>
<start name="terminal_mux">
<resource name="RAM" quantum="3M"/>
<provides><service name="Terminal"/></provides>
<route>
<service name="Terminal"><child name="uart_drv"/></service>
<any-service> <parent/> <any-child/> </any-service>
</route>
<config>
<keyboard layout="de"/>
</config>
</start>
<start name="terminal_log">
<resource name="RAM" quantum="2M"/>
<provides>
<service name="LOG"/>
</provides>
<route>
<any-service><child name="terminal_mux"/> <any-child/> <parent/> </any-service>
</route>
</start>
<start name="cli_monitor">
<resource name="RAM" quantum="3G"/>
<config>
<subsystem name="gdb_test" help="GDB test application"> }
append config "
<binary name=\"${gdb_target_binary_name}\"/> "
append config {
<resource name="RAM" quantum="50M"/>
</subsystem>
</config>
<route>
<service name="LOG"><child name="terminal_log"/></service>
<service name="Terminal"><child name="terminal_mux"/></service>
<any-service><parent/><any-child/></any-service>
</route>
</start>
</config>
}
install_config $config
#
# Boot modules
#
exec cp ${genode_dir}/repos/os/src/app/cli_monitor/gdb_command_config bin
# generic modules
set boot_modules {
core init timer ld.lib.so noux terminal_mux terminal_crosslink
libc.lib.so libm.lib.so libc_noux.lib.so ncurses.lib.so expat.lib.so
libc_pipe.lib.so libc_terminal.lib.so
cli_monitor gdb_monitor terminal_log gdb.tar
gdb_command_config
gdb_target.tar
gdb_target-src.tar
}
lappend boot_modules ${gdb_target_binary_name}
# platform-specific modules
lappend_if [expr ![have_spec foc]] boot_modules uart_drv
lappend_if [have_spec foc] boot_modules kdb_uart_drv
set fiasco_serial_esc_arg ""
build_boot_image $boot_modules
append qemu_args " -nographic "
run_genode_until forever
exec rm bin/gdb.tar

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2009-2016 Genode Labs GmbH * Copyright (C) 2009-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -14,9 +14,7 @@
#ifndef _APP_CHILD_H_ #ifndef _APP_CHILD_H_
#define _APP_CHILD_H_ #define _APP_CHILD_H_
#include <stdio.h> /* Genode includes */
#include <sys/stat.h>
#include <base/child.h> #include <base/child.h>
#include <base/service.h> #include <base/service.h>
@ -25,37 +23,43 @@
#include <util/arg_string.h> #include <util/arg_string.h>
/* GDB monitor includes */
#include "genode_child_resources.h" #include "genode_child_resources.h"
#include "cpu_session_component.h" #include "cpu_session_component.h"
#include "pd_session_component.h" #include "pd_session_component.h"
#include "rom.h" #include "rom.h"
namespace Gdb_monitor {
using namespace Genode;
namespace Gdb_monitor { class App_child; } class App_child;
}
class Gdb_monitor::App_child : public Child_policy class Gdb_monitor::App_child : public Child_policy
{ {
public: public:
typedef Genode::Registered<Genode::Parent_service> Parent_service; typedef Registered<Genode::Parent_service> Parent_service;
typedef Genode::Registry<Parent_service> Parent_services; typedef Registry<Parent_service> Parent_services;
private: private:
enum { STACK_SIZE = 4*1024*sizeof(long) }; enum { STACK_SIZE = 4*1024*sizeof(long) };
Genode::Env &_env; Env &_env;
Genode::Ram_session_capability _ref_ram_cap { _env.ram_session_cap() }; Allocator &_alloc;
Genode::Ram_session_client _ref_ram { _ref_ram_cap };
Ram_session_capability _ref_ram_cap { _env.ram_session_cap() };
Ram_session_client _ref_ram { _ref_ram_cap };
const char *_unique_name; const char *_unique_name;
Genode::Dataspace_capability _elf_ds; Dataspace_capability _elf_ds;
Genode::Region_map &_rm; Region_map &_rm;
Genode::size_t _ram_quota; size_t _ram_quota;
Rpc_entrypoint _entrypoint; Rpc_entrypoint _entrypoint;
@ -71,7 +75,7 @@ class Gdb_monitor::App_child : public Child_policy
Dataspace_pool _managed_ds_map; Dataspace_pool _managed_ds_map;
Pd_session_component _pd {_unique_name, _entrypoint, _managed_ds_map}; Pd_session_component _pd { _entrypoint, _env, _alloc, _unique_name, _managed_ds_map };
Pd_service::Single_session_factory _pd_factory { _pd }; Pd_service::Single_session_factory _pd_factory { _pd };
Pd_service _pd_service { _pd_factory }; Pd_service _pd_service { _pd_factory };
@ -83,156 +87,16 @@ class Gdb_monitor::App_child : public Child_policy
Child *_child; Child *_child;
/* FIXME */
#if 0
/**
* Proxy for a service provided by the child
*/
class Child_service_root : public Genode::Rpc_object<Genode::Root>
{
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<Child_session> 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.
*/
_sessions.insert(new (env()->heap())
Child_session(cap, ram_quota));
return cap;
}
void upgrade(Session_capability session_cap,
Upgrade_args const &args)
{
using namespace Genode;
auto lambda = [&] (Child_session *session) {
if (!session) {
error("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) {
error("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);
}
};
#endif
void _dispatch_unresolved_page_fault(unsigned) void _dispatch_unresolved_page_fault(unsigned)
{ {
_genode_child_resources.cpu_session_component()->handle_unresolved_page_fault(); _genode_child_resources.cpu_session_component().handle_unresolved_page_fault();
} }
template <typename T> template <typename T>
static Genode::Service *_find_service(Genode::Registry<T> &services, static Service *_find_service(Registry<T> &services,
Genode::Service::Name const &name) Service::Name const &name)
{ {
Genode::Service *service = nullptr; Service *service = nullptr;
services.for_each([&] (T &s) { services.for_each([&] (T &s) {
if (!service && (s.name() == name)) if (!service && (s.name() == name))
service = &s; }); service = &s; });
@ -244,27 +108,27 @@ class Gdb_monitor::App_child : public Child_policy
/** /**
* Constructor * Constructor
*/ */
App_child(Genode::Env &env, App_child(Env &env,
const char *unique_name, Allocator &alloc,
Genode::Pd_session &pd, char const *unique_name,
Genode::Region_map &rm, size_t ram_quota,
Genode::size_t ram_quota, Signal_receiver &signal_receiver,
Signal_receiver *signal_receiver, Xml_node target_node)
Xml_node target_node)
: :
_env(env), _env(env),
_alloc(alloc),
_unique_name(unique_name), _unique_name(unique_name),
_rm(rm), _rm(_env.rm()),
_ram_quota(ram_quota), _ram_quota(ram_quota),
_entrypoint(&pd, STACK_SIZE, "GDB monitor entrypoint"), _entrypoint(&_env.pd(), STACK_SIZE, "GDB monitor entrypoint"),
_child_config(env.ram(), rm, target_node), _child_config(env.ram(), _rm, target_node),
_config_policy("config", _child_config.dataspace(), &_entrypoint), _config_policy("config", _child_config.dataspace(), &_entrypoint),
_unresolved_page_fault_dispatcher(*signal_receiver, _unresolved_page_fault_dispatcher(signal_receiver,
*this, *this,
&App_child::_dispatch_unresolved_page_fault), &App_child::_dispatch_unresolved_page_fault),
_cpu_factory(_env, _entrypoint, Genode::env()->heap(), _pd.core_pd_cap(), _cpu_factory(_env, _entrypoint, _alloc, _pd.core_pd_cap(),
signal_receiver, &_genode_child_resources), signal_receiver, &_genode_child_resources),
_rom_factory(env, _entrypoint) _rom_factory(env, _entrypoint, _alloc)
{ {
_genode_child_resources.region_map_component(&_pd.region_map()); _genode_child_resources.region_map_component(&_pd.region_map());
_pd.region_map().fault_handler(_unresolved_page_fault_dispatcher); _pd.region_map().fault_handler(_unresolved_page_fault_dispatcher);
@ -272,7 +136,7 @@ class Gdb_monitor::App_child : public Child_policy
~App_child() ~App_child()
{ {
destroy(env()->heap(), _child); destroy(_alloc, _child);
} }
Genode_child_resources *genode_child_resources() Genode_child_resources *genode_child_resources()
@ -282,7 +146,7 @@ class Gdb_monitor::App_child : public Child_policy
void start() void start()
{ {
_child = new (env()->heap()) Child(_rm, _entrypoint, *this); _child = new (_alloc) Child(_rm, _entrypoint, *this);
} }
/**************************** /****************************
@ -291,19 +155,19 @@ class Gdb_monitor::App_child : public Child_policy
Name name() const override { return _unique_name; } Name name() const override { return _unique_name; }
Genode::Ram_session &ref_ram() override { return _ref_ram; } Ram_session &ref_ram() override { return _ref_ram; }
Genode::Ram_session_capability ref_ram_cap() const override { return _ref_ram_cap; } Ram_session_capability ref_ram_cap() const override { return _ref_ram_cap; }
void init(Genode::Ram_session &session, void init(Ram_session &session,
Genode::Ram_session_capability cap) override Ram_session_capability cap) override
{ {
session.ref_account(_ref_ram_cap); session.ref_account(_ref_ram_cap);
_ref_ram.transfer_quota(cap, _ram_quota); _ref_ram.transfer_quota(cap, _ram_quota);
} }
Service &resolve_session_request(Genode::Service::Name const &service_name, Service &resolve_session_request(Service::Name const &service_name,
Genode::Session_state::Args const &args) override Session_state::Args const &args) override
{ {
Service *service = nullptr; Service *service = nullptr;
@ -322,7 +186,7 @@ class Gdb_monitor::App_child : public Child_policy
service = _find_service(_parent_services, service_name); service = _find_service(_parent_services, service_name);
if (!service) if (!service)
service = new (env()->heap()) Parent_service(_parent_services, _env, service_name); service = new (_alloc) Parent_service(_parent_services, _env, service_name);
if (!service) if (!service)
throw Parent::Service_denied(); throw Parent::Service_denied();
@ -334,15 +198,7 @@ class Gdb_monitor::App_child : public Child_policy
// to the child // to the child
void announce_service(Service::Name const &name) override void announce_service(Service::Name const &name) override
{ {
/* FIXME */
#if 0
/* 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));
#else
Genode::warning(__PRETTY_FUNCTION__, ": not implemented"); Genode::warning(__PRETTY_FUNCTION__, ": not implemented");
#endif
} }
}; };

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -21,6 +21,9 @@
/* GDB monitor includes */ /* GDB monitor includes */
#include "cpu_thread_component.h" #include "cpu_thread_component.h"
/* libc includes */
#include <sys/signal.h>
/* genode-low.cc */ /* genode-low.cc */
extern void genode_remove_thread(unsigned long lwpid); extern void genode_remove_thread(unsigned long lwpid);
@ -40,7 +43,7 @@ Rpc_entrypoint &Cpu_session_component::thread_ep()
} }
Signal_receiver *Cpu_session_component::exception_signal_receiver() Signal_receiver &Cpu_session_component::exception_signal_receiver()
{ {
return _exception_signal_receiver; return _exception_signal_receiver;
} }
@ -299,11 +302,11 @@ Capability<Cpu_session::Native_cpu> Cpu_session_component::native_cpu()
} }
Cpu_session_component::Cpu_session_component(Genode::Env &env, Cpu_session_component::Cpu_session_component(Env &env,
Rpc_entrypoint &ep, Rpc_entrypoint &ep,
Allocator *md_alloc, Allocator &md_alloc,
Pd_session_capability core_pd, Pd_session_capability core_pd,
Signal_receiver *exception_signal_receiver, Signal_receiver &exception_signal_receiver,
const char *args, const char *args,
Affinity const &affinity) Affinity const &affinity)
: _env(env), : _env(env),
@ -335,7 +338,7 @@ Cpu_session_component::~Cpu_session_component()
int Cpu_session_component::ref_account(Cpu_session_capability) { return -1; } int Cpu_session_component::ref_account(Cpu_session_capability) { return -1; }
int Cpu_session_component::transfer_quota(Cpu_session_capability, Genode::size_t) { return -1; } int Cpu_session_component::transfer_quota(Cpu_session_capability, size_t) { return -1; }
Cpu_session::Quota Cpu_session_component::quota() { return Quota(); } Cpu_session::Quota Cpu_session_component::quota() { return Quota(); }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2006-2016 Genode Labs GmbH * Copyright (C) 2006-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -31,13 +31,13 @@
namespace Gdb_monitor namespace Gdb_monitor
{ {
using namespace Genode;
class Cpu_session_component; class Cpu_session_component;
class Cpu_thread_component; class Cpu_thread_component;
class Local_cpu_factory; class Local_cpu_factory;
typedef Genode::Local_service<Cpu_session_component> Cpu_service; typedef Local_service<Cpu_session_component> Cpu_service;
using namespace Genode;
} }
@ -46,29 +46,29 @@ class Gdb_monitor::Cpu_session_component : public Rpc_object<Cpu_session>
private: private:
Genode::Env &_env; Env &_env;
Genode::Parent::Client _parent_client; Parent::Client _parent_client;
Id_space<Parent::Client>::Element const _id_space_element Id_space<Parent::Client>::Element const _id_space_element
{ _parent_client, _env.id_space() }; { _parent_client, _env.id_space() };
Rpc_entrypoint &_ep; Rpc_entrypoint &_ep;
Allocator *_md_alloc; Allocator &_md_alloc;
Pd_session_capability _core_pd; Pd_session_capability _core_pd;
Cpu_session_client _parent_cpu_session; Cpu_session_client _parent_cpu_session;
Signal_receiver *_exception_signal_receiver; Signal_receiver &_exception_signal_receiver;
Append_list<Cpu_thread_component> _thread_list; Append_list<Cpu_thread_component> _thread_list;
bool _stop_new_threads = true; bool _stop_new_threads = true;
Lock _stop_new_threads_lock; Lock _stop_new_threads_lock;
Capability<Cpu_session::Native_cpu> _native_cpu_cap; Capability<Cpu_session::Native_cpu> _native_cpu_cap;
Capability<Cpu_session::Native_cpu> _setup_native_cpu(); Capability<Cpu_session::Native_cpu> _setup_native_cpu();
void _cleanup_native_cpu(); void _cleanup_native_cpu();
public: public:
@ -76,11 +76,11 @@ class Gdb_monitor::Cpu_session_component : public Rpc_object<Cpu_session>
/** /**
* Constructor * Constructor
*/ */
Cpu_session_component(Genode::Env &env, Cpu_session_component(Env &env,
Rpc_entrypoint &ep, Rpc_entrypoint &ep,
Allocator *md_alloc, Allocator &md_alloc,
Pd_session_capability core_pd, Pd_session_capability core_pd,
Signal_receiver *exception_signal_receiver, Signal_receiver &exception_signal_receiver,
const char *args, const char *args,
Affinity const &affinity); Affinity const &affinity);
@ -91,7 +91,7 @@ class Gdb_monitor::Cpu_session_component : public Rpc_object<Cpu_session>
Cpu_session &parent_cpu_session(); Cpu_session &parent_cpu_session();
Rpc_entrypoint &thread_ep(); Rpc_entrypoint &thread_ep();
Signal_receiver *exception_signal_receiver(); Signal_receiver &exception_signal_receiver();
Thread_capability thread_cap(unsigned long lwpid); Thread_capability thread_cap(unsigned long lwpid);
unsigned long lwpid(Thread_capability thread_cap); unsigned long lwpid(Thread_capability thread_cap);
Cpu_thread_component *lookup_cpu_thread(unsigned long lwpid); Cpu_thread_component *lookup_cpu_thread(unsigned long lwpid);
@ -122,7 +122,7 @@ class Gdb_monitor::Cpu_session_component : public Rpc_object<Cpu_session>
Affinity::Space affinity_space() const override; Affinity::Space affinity_space() const override;
Dataspace_capability trace_control() override; Dataspace_capability trace_control() override;
int ref_account(Cpu_session_capability c) override; int ref_account(Cpu_session_capability c) override;
int transfer_quota(Cpu_session_capability c, Genode::size_t q) override; int transfer_quota(Cpu_session_capability c, size_t q) override;
Quota quota() override; Quota quota() override;
Capability<Native_cpu> native_cpu() override; Capability<Native_cpu> native_cpu() override;
}; };
@ -132,21 +132,22 @@ class Gdb_monitor::Local_cpu_factory : public Cpu_service::Factory
{ {
private: private:
Genode::Env &_env; Env &_env;
Genode::Rpc_entrypoint &_ep; Rpc_entrypoint &_ep;
Allocator *_md_alloc; Allocator &_md_alloc;
Pd_session_capability _core_pd; Pd_session_capability _core_pd;
Genode::Signal_receiver *_signal_receiver; Signal_receiver &_signal_receiver;
Genode_child_resources *_genode_child_resources; Genode_child_resources *_genode_child_resources;
public: public:
Local_cpu_factory(Genode::Env &env, Genode::Rpc_entrypoint &ep, Local_cpu_factory(Env &env,
Allocator *md_alloc, Rpc_entrypoint &ep,
Pd_session_capability core_pd, Allocator &md_alloc,
Genode::Signal_receiver *signal_receiver, Pd_session_capability core_pd,
Signal_receiver &signal_receiver,
Genode_child_resources *genode_child_resources) Genode_child_resources *genode_child_resources)
: _env(env), _ep(ep), : _env(env), _ep(ep),
_md_alloc(md_alloc), _md_alloc(md_alloc),
@ -178,7 +179,7 @@ class Gdb_monitor::Local_cpu_factory : public Cpu_service::Factory
void destroy(Cpu_session_component &session) override void destroy(Cpu_session_component &session) override
{ {
Genode::destroy(env()->heap(), &session); Genode::destroy(_md_alloc, &session);
} }
}; };

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2016 Genode Labs GmbH * Copyright (C) 2016-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -15,6 +15,9 @@
/* GDB monitor includes */ /* GDB monitor includes */
#include "cpu_thread_component.h" #include "cpu_thread_component.h"
/* libc includes */
#include <signal.h>
#include <unistd.h>
/* mem-break.c */ /* mem-break.c */
extern "C" int breakpoint_len; extern "C" int breakpoint_len;
@ -61,6 +64,150 @@ void Cpu_thread_component::_remove_breakpoint_at_first_instruction()
} }
void Cpu_thread_component::_dispatch_exception(unsigned)
{
deliver_signal(SIGTRAP);
}
void Cpu_thread_component::_dispatch_sigstop(unsigned)
{
deliver_signal(SIGSTOP);
}
void Cpu_thread_component::_dispatch_sigint(unsigned)
{
deliver_signal(SIGINT);
}
Cpu_thread_component::Cpu_thread_component(Cpu_session_component &cpu_session_component,
Capability<Pd_session> 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)
error("could not create pipe");
}
Cpu_thread_component::~Cpu_thread_component()
{
close(_pipefd[0]);
close(_pipefd[1]);
_cpu_session_component.thread_ep().dissolve(this);
}
int Cpu_thread_component::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:
error("unexpected signal ", signo);
return 0;
}
}
int Cpu_thread_component::deliver_signal(int signo)
{
if ((signo == SIGTRAP) && _initial_sigtrap_pending) {
_initial_sigtrap_pending = false;
if (_verbose)
log("received initial SIGTRAP for lwpid ", _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)
log("delivering SIGSTOP to thread ", _lwpid);
break;
case SIGTRAP:
if (_verbose)
log("delivering SIGTRAP to thread ", _lwpid);
break;
case SIGSEGV:
if (_verbose)
log("delivering SIGSEGV to thread ", _lwpid);
break;
case SIGINT:
if (_verbose)
log("delivering SIGINT to thread ", _lwpid);
break;
case SIGINFO:
if (_verbose)
log("delivering initial SIGSTOP to thread ", _lwpid);
break;
default:
error("unexpected signal ", signo);
}
write(_pipefd[1], &signo, sizeof(signo));
return 0;
}
Dataspace_capability Cpu_thread_component::utcb() Dataspace_capability Cpu_thread_component::utcb()
{ {
return _parent_cpu_thread.utcb(); return _parent_cpu_thread.utcb();

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2016 Genode Labs GmbH * Copyright (C) 2016-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -19,10 +19,6 @@
#include <cpu_session/cpu_session.h> #include <cpu_session/cpu_session.h>
#include <cpu_thread/client.h> #include <cpu_thread/client.h>
/* libc includes */
#include <signal.h>
#include <unistd.h>
#include "config.h" #include "config.h"
#include "append_list.h" #include "append_list.h"
#include "cpu_session_component.h" #include "cpu_session_component.h"
@ -65,62 +61,20 @@ class Gdb_monitor::Cpu_thread_component : public Rpc_object<Cpu_thread>,
bool _set_breakpoint_at_first_instruction(addr_t ip); bool _set_breakpoint_at_first_instruction(addr_t ip);
void _remove_breakpoint_at_first_instruction(); void _remove_breakpoint_at_first_instruction();
void _dispatch_exception(unsigned) void _dispatch_exception(unsigned);
{ void _dispatch_sigstop(unsigned);
deliver_signal(SIGTRAP); void _dispatch_sigint(unsigned);
}
void _dispatch_sigstop(unsigned)
{
deliver_signal(SIGSTOP);
}
void _dispatch_sigint(unsigned)
{
deliver_signal(SIGINT);
}
public: public:
Cpu_thread_component(Cpu_session_component &cpu_session_component, Cpu_thread_component(Cpu_session_component &cpu_session_component,
Capability<Pd_session> pd, Capability<Pd_session> pd,
Cpu_session::Name const &name, Cpu_session::Name const &name,
Affinity::Location affinity, Affinity::Location affinity,
Cpu_session::Weight weight, Cpu_session::Weight weight,
addr_t utcb) 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) ~Cpu_thread_component();
error("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() Signal_context_capability exception_signal_context_cap()
{ {
@ -154,89 +108,9 @@ class Gdb_monitor::Cpu_thread_component : public Rpc_object<Cpu_thread>,
return 0; return 0;
} }
int send_signal(int signo) 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:
error("unexpected signal ", signo);
return 0;
}
}
int deliver_signal(int signo)
{
if ((signo == SIGTRAP) && _initial_sigtrap_pending) {
_initial_sigtrap_pending = false;
if (_verbose)
log("received initial SIGTRAP for lwpid ", _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)
log("delivering SIGSTOP to thread ", _lwpid);
break;
case SIGTRAP:
if (_verbose)
log("delivering SIGTRAP to thread ", _lwpid);
break;
case SIGSEGV:
if (_verbose)
log("delivering SIGSEGV to thread ", _lwpid);
break;
case SIGINT:
if (_verbose)
log("delivering SIGINT to thread ", _lwpid);
break;
case SIGINFO:
if (_verbose)
log("delivering initial SIGSTOP to thread ", _lwpid);
break;
default:
error("unexpected signal ", signo);
}
write(_pipefd[1], &signo, sizeof(signo));
return 0;
}
int deliver_signal(int signo);
/************************** /**************************
** CPU thread interface ** ** CPU thread interface **

View File

@ -6,15 +6,26 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
#include <signal.h> /* Genode includes */
#include <sys/wait.h> #include <base/env.h>
#include <os/config.h>
/* GDB monitor includes */
#include "app_child.h"
#include "cpu_thread_component.h"
#include "genode_child_resources.h"
#include "signal_handler_thread.h"
/* libc includes */
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
extern "C" { extern "C" {
@ -27,23 +38,6 @@ extern "C" {
int linux_detach_one_lwp (struct inferior_list_entry *entry, void *args); int linux_detach_one_lwp (struct inferior_list_entry *entry, void *args);
} }
#include <base/log.h>
#include <base/service.h>
#include <cap_session/connection.h>
#include <cpu_thread/client.h>
#include <dataspace/client.h>
#include <os/config.h>
#include <ram_session/connection.h>
#include <rom_session/connection.h>
#include <util/xml_node.h>
#include "app_child.h"
#include "cpu_session_component.h"
#include "cpu_thread_component.h"
#include "genode_child_resources.h"
#include "rom.h"
#include "signal_handler_thread.h"
static bool verbose = false; static bool verbose = false;
Genode::Env *genode_env; Genode::Env *genode_env;
@ -60,20 +54,185 @@ static unsigned long sigtrap_lwpid;
using namespace Genode; using namespace Genode;
using namespace Gdb_monitor; using namespace Gdb_monitor;
static Genode_child_resources *_genode_child_resources = 0; class Memory_model
Genode_child_resources *genode_child_resources()
{ {
return _genode_child_resources; private:
Lock _lock;
Region_map_component &_address_space;
Region_map &_rm;
/**
* Representation of a currently mapped region
*/
struct Mapped_region
{
Region_map_component::Region *_region;
unsigned char *_local_base;
Mapped_region() : _region(0), _local_base(0) { }
bool valid() { return _region != 0; }
bool loaded(Region_map_component::Region const * region)
{
return _region == region;
}
void flush(Region_map &rm)
{
if (!valid()) return;
rm.detach(_local_base);
_local_base = 0;
_region = 0;
}
void load(Region_map_component::Region *region, Region_map &rm)
{
if (region == _region)
return;
if (!region || valid())
flush(rm);
if (!region)
return;
try {
_region = region;
_local_base = rm.attach(_region->ds_cap(),
0, _region->offset());
} catch (Region_map::Attach_failed) {
flush(rm);
error(__func__, ": RM attach failed");
}
}
unsigned char *local_base() { return _local_base; }
};
enum { NUM_MAPPED_REGIONS = 1 };
Mapped_region _mapped_region[NUM_MAPPED_REGIONS];
unsigned _evict_idx = 0;
/**
* Return local address of mapped region
*
* The function returns 0 if the mapping fails
*/
unsigned char *_update_curr_region(Region_map_component::Region *region)
{
for (unsigned i = 0; i < NUM_MAPPED_REGIONS; i++) {
if (_mapped_region[i].loaded(region))
return _mapped_region[i].local_base();
}
/* flush one currently mapped region */
_evict_idx++;
if (_evict_idx == NUM_MAPPED_REGIONS)
_evict_idx = 0;
_mapped_region[_evict_idx].load(region, _rm);
return _mapped_region[_evict_idx].local_base();
}
public:
Memory_model(Region_map_component &address_space,
Region_map &rm)
:
_address_space(address_space),
_rm(rm)
{ }
unsigned char read(void *addr)
{
Lock::Guard guard(_lock);
addr_t offset_in_region = 0;
Region_map_component::Region *region =
_address_space.find_region(addr, &offset_in_region);
unsigned char *local_base = _update_curr_region(region);
if (!local_base) {
warning(__func__, ": no memory at address ", addr);
throw No_memory_at_address();
}
unsigned char value =
local_base[offset_in_region];
if (verbose)
log(__func__, ": read addr=", addr, ", value=", Hex(value));
return value;
}
void write(void *addr, unsigned char value)
{
if (verbose)
log(__func__, ": write addr=", addr, ", value=", Hex(value));
Lock::Guard guard(_lock);
addr_t offset_in_region = 0;
Region_map_component::Region *region =
_address_space.find_region(addr, &offset_in_region);
unsigned char *local_base = _update_curr_region(region);
if (!local_base) {
warning(__func__, ": no memory at address=", addr);
warning("(attempted to write ", Hex(value), ")");
throw No_memory_at_address();
}
local_base[offset_in_region] = value;
}
};
static Genode_child_resources *_genode_child_resources = 0;
static Memory_model *_memory_model = 0;
Genode_child_resources &genode_child_resources()
{
if (!_genode_child_resources) {
Genode::error("_genode_child_resources is not set");
abort();
}
return *_genode_child_resources;
}
/**
* Return singleton instance of memory model
*/
Memory_model &memory_model()
{
if (!_memory_model) {
Genode::error("_memory_model is not set");
abort();
}
return *_memory_model;
} }
static void genode_stop_thread(unsigned long lwpid) static void genode_stop_thread(unsigned long lwpid)
{ {
Cpu_session_component *csc = genode_child_resources()->cpu_session_component(); Cpu_session_component &csc = genode_child_resources().cpu_session_component();
Cpu_thread_component *cpu_thread = csc->lookup_cpu_thread(lwpid); Cpu_thread_component *cpu_thread = csc.lookup_cpu_thread(lwpid);
if (!cpu_thread) { if (!cpu_thread) {
error(__PRETTY_FUNCTION__, ": " error(__PRETTY_FUNCTION__, ": "
@ -91,7 +250,7 @@ extern "C" pid_t waitpid(pid_t pid, int *status, int flags)
fd_set readset; fd_set readset;
Cpu_session_component *csc = genode_child_resources()->cpu_session_component(); Cpu_session_component &csc = genode_child_resources().cpu_session_component();
while(1) { while(1) {
@ -104,16 +263,16 @@ extern "C" pid_t waitpid(pid_t pid, int *status, int flags)
FD_SET(_new_thread_pipe[0], &readset); FD_SET(_new_thread_pipe[0], &readset);
Thread_capability thread_cap = csc->first(); Thread_capability thread_cap = csc.first();
while (thread_cap.valid()) { while (thread_cap.valid()) {
FD_SET(csc->signal_pipe_read_fd(thread_cap), &readset); FD_SET(csc.signal_pipe_read_fd(thread_cap), &readset);
thread_cap = csc->next(thread_cap); thread_cap = csc.next(thread_cap);
} }
} else { } else {
FD_SET(csc->signal_pipe_read_fd(csc->thread_cap(pid)), &readset); FD_SET(csc.signal_pipe_read_fd(csc.thread_cap(pid)), &readset);
} }
struct timeval wnohang_timeout = {0, 0}; struct timeval wnohang_timeout = {0, 0};
@ -157,21 +316,21 @@ extern "C" pid_t waitpid(pid_t pid, int *status, int flags)
/* received a signal */ /* received a signal */
Thread_capability thread_cap = csc->first(); Thread_capability thread_cap = csc.first();
while (thread_cap.valid()) { while (thread_cap.valid()) {
if (FD_ISSET(csc->signal_pipe_read_fd(thread_cap), &readset)) if (FD_ISSET(csc.signal_pipe_read_fd(thread_cap), &readset))
break; break;
thread_cap = csc->next(thread_cap); thread_cap = csc.next(thread_cap);
} }
if (!thread_cap.valid()) if (!thread_cap.valid())
continue; continue;
int signal; int signal;
read(csc->signal_pipe_read_fd(thread_cap), &signal, sizeof(signal)); read(csc.signal_pipe_read_fd(thread_cap), &signal, sizeof(signal));
unsigned long lwpid = csc->lwpid(thread_cap); unsigned long lwpid = csc.lwpid(thread_cap);
if (verbose) if (verbose)
log("thread ", lwpid, " received signal ", signal); log("thread ", lwpid, " received signal ", signal);
@ -191,13 +350,13 @@ extern "C" pid_t waitpid(pid_t pid, int *status, int flags)
* delivered first, otherwise gdbserver would single-step the thread again. * delivered first, otherwise gdbserver would single-step the thread again.
*/ */
Cpu_thread_component *cpu_thread = csc->lookup_cpu_thread(lwpid); Cpu_thread_component *cpu_thread = csc.lookup_cpu_thread(lwpid);
Thread_state thread_state = cpu_thread->state(); Thread_state thread_state = cpu_thread->state();
if (thread_state.exception) { if (thread_state.exception) {
/* resend the SIGSTOP signal */ /* resend the SIGSTOP signal */
csc->send_signal(cpu_thread->cap(), SIGSTOP); csc.send_signal(cpu_thread->cap(), SIGSTOP);
continue; continue;
} }
@ -308,26 +467,31 @@ extern "C" int fork()
return -1; return -1;
} }
Number_of_bytes ram_quota = env()->ram_session()->avail() - preserved_ram_quota; Number_of_bytes ram_quota = genode_env->ram().avail() - preserved_ram_quota;
/* start the application */ /* start the application */
static Heap alloc(genode_env->ram(), genode_env->rm());
static Signal_receiver signal_receiver; static Signal_receiver signal_receiver;
static Gdb_monitor::Signal_handler_thread static Gdb_monitor::Signal_handler_thread
signal_handler_thread(&signal_receiver); signal_handler_thread(*genode_env, signal_receiver);
signal_handler_thread.start(); signal_handler_thread.start();
App_child *child = new (env()->heap()) App_child(*genode_env, App_child *child = new (alloc) App_child(*genode_env,
filename, alloc,
genode_env->pd(), filename,
genode_env->rm(), ram_quota,
ram_quota, signal_receiver,
&signal_receiver, target_node);
target_node);
_genode_child_resources = child->genode_child_resources(); _genode_child_resources = child->genode_child_resources();
static Memory_model memory_model(genode_child_resources().region_map_component(), genode_env->rm());
_memory_model = &memory_model;
try { try {
child->start(); child->start();
} catch (...) { } catch (...) {
@ -341,9 +505,9 @@ extern "C" int fork()
extern "C" int kill(pid_t pid, int sig) extern "C" int kill(pid_t pid, int sig)
{ {
Cpu_session_component *csc = genode_child_resources()->cpu_session_component(); Cpu_session_component &csc = genode_child_resources().cpu_session_component();
Thread_capability thread_cap = csc->thread_cap(pid); Thread_capability thread_cap = csc.thread_cap(pid);
if (!thread_cap.valid()) { if (!thread_cap.valid()) {
error(__PRETTY_FUNCTION__, ": " error(__PRETTY_FUNCTION__, ": "
@ -351,14 +515,14 @@ extern "C" int kill(pid_t pid, int sig)
return -1; return -1;
} }
return csc->send_signal(thread_cap, sig); return csc.send_signal(thread_cap, sig);
} }
extern "C" int initial_breakpoint_handler(CORE_ADDR addr) extern "C" int initial_breakpoint_handler(CORE_ADDR addr)
{ {
Cpu_session_component *csc = genode_child_resources()->cpu_session_component(); Cpu_session_component &csc = genode_child_resources().cpu_session_component();
return csc->handle_initial_breakpoint(sigtrap_lwpid); return csc.handle_initial_breakpoint(sigtrap_lwpid);
} }
@ -378,15 +542,15 @@ void genode_remove_thread(unsigned long lwpid)
extern "C" void genode_stop_all_threads() extern "C" void genode_stop_all_threads()
{ {
Cpu_session_component *csc = genode_child_resources()->cpu_session_component(); Cpu_session_component &csc = genode_child_resources().cpu_session_component();
csc->pause_all_threads(); csc.pause_all_threads();
} }
void genode_resume_all_threads() void genode_resume_all_threads()
{ {
Cpu_session_component *csc = genode_child_resources()->cpu_session_component(); Cpu_session_component &csc = genode_child_resources().cpu_session_component();
csc->resume_all_threads(); csc.resume_all_threads();
} }
@ -409,9 +573,9 @@ int genode_kill(int pid)
void genode_continue_thread(unsigned long lwpid, int single_step) void genode_continue_thread(unsigned long lwpid, int single_step)
{ {
Cpu_session_component *csc = genode_child_resources()->cpu_session_component(); Cpu_session_component &csc = genode_child_resources().cpu_session_component();
Cpu_thread_component *cpu_thread = csc->lookup_cpu_thread(lwpid); Cpu_thread_component *cpu_thread = csc.lookup_cpu_thread(lwpid);
if (!cpu_thread) { if (!cpu_thread) {
error(__func__, ": " "could not find CPU thread object for lwpid ", lwpid); error(__func__, ": " "could not find CPU thread object for lwpid ", lwpid);
@ -465,160 +629,9 @@ void genode_store_registers(struct regcache *regcache, int regno)
} }
class Memory_model
{
private:
Lock _lock;
Region_map_component * const _address_space;
/**
* Representation of a currently mapped region
*/
struct Mapped_region
{
Region_map_component::Region *_region;
unsigned char *_local_base;
Mapped_region() : _region(0), _local_base(0) { }
bool valid() { return _region != 0; }
bool loaded(Region_map_component::Region const * region)
{
return _region == region;
}
void flush()
{
if (!valid()) return;
env()->rm_session()->detach(_local_base);
_local_base = 0;
_region = 0;
}
void load(Region_map_component::Region *region)
{
if (region == _region)
return;
if (!region || valid())
flush();
if (!region)
return;
try {
_region = region;
_local_base = env()->rm_session()->attach(_region->ds_cap(),
0, _region->offset());
} catch (Region_map::Attach_failed) {
flush();
error(__func__, ": RM attach failed");
}
}
unsigned char *local_base() { return _local_base; }
};
enum { NUM_MAPPED_REGIONS = 1 };
Mapped_region _mapped_region[NUM_MAPPED_REGIONS];
unsigned _evict_idx;
/**
* Return local address of mapped region
*
* The function returns 0 if the mapping fails
*/
unsigned char *_update_curr_region(Region_map_component::Region *region)
{
for (unsigned i = 0; i < NUM_MAPPED_REGIONS; i++) {
if (_mapped_region[i].loaded(region))
return _mapped_region[i].local_base();
}
/* flush one currently mapped region */
_evict_idx++;
if (_evict_idx == NUM_MAPPED_REGIONS)
_evict_idx = 0;
_mapped_region[_evict_idx].load(region);
return _mapped_region[_evict_idx].local_base();
}
public:
Memory_model(Region_map_component *address_space)
:
_address_space(address_space), _evict_idx(0)
{ }
unsigned char read(void *addr)
{
Lock::Guard guard(_lock);
addr_t offset_in_region = 0;
Region_map_component::Region *region =
_address_space->find_region(addr, &offset_in_region);
unsigned char *local_base = _update_curr_region(region);
if (!local_base) {
warning(__func__, ": no memory at address ", addr);
throw No_memory_at_address();
}
unsigned char value =
local_base[offset_in_region];
if (verbose)
log(__func__, ": read addr=", addr, ", value=", Hex(value));
return value;
}
void write(void *addr, unsigned char value)
{
if (verbose)
log(__func__, ": write addr=", addr, ", value=", Hex(value));
Lock::Guard guard(_lock);
addr_t offset_in_region = 0;
Region_map_component::Region *region =
_address_space->find_region(addr, &offset_in_region);
unsigned char *local_base = _update_curr_region(region);
if (!local_base) {
warning(__func__, ": no memory at address=", addr);
warning("(attempted to write ", Hex(value), ")");
throw No_memory_at_address();
}
local_base[offset_in_region] = value;
}
};
/**
* Return singleton instance of memory model
*/
static Memory_model *memory_model()
{
static Memory_model inst(genode_child_resources()->region_map_component());
return &inst;
}
unsigned char genode_read_memory_byte(void *addr) unsigned char genode_read_memory_byte(void *addr)
{ {
return memory_model()->read(addr); return memory_model().read(addr);
} }
@ -641,7 +654,7 @@ int genode_read_memory(CORE_ADDR memaddr, unsigned char *myaddr, int len)
void genode_write_memory_byte(void *addr, unsigned char value) void genode_write_memory_byte(void *addr, unsigned char value)
{ {
memory_model()->write(addr, value); memory_model().write(addr, value);
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -16,6 +16,8 @@
#include "region_map_component.h" #include "region_map_component.h"
extern "C" void abort();
namespace Gdb_monitor { namespace Gdb_monitor {
class Cpu_session_component; class Cpu_session_component;
class Genode_child_resources; class Genode_child_resources;
@ -23,7 +25,6 @@ namespace Gdb_monitor {
class Gdb_monitor::Genode_child_resources class Gdb_monitor::Genode_child_resources
{ {
private: private:
Cpu_session_component *_cpu_session_component = 0; Cpu_session_component *_cpu_session_component = 0;
@ -41,8 +42,23 @@ class Gdb_monitor::Genode_child_resources
_region_map_component = region_map_component; _region_map_component = region_map_component;
} }
Cpu_session_component *cpu_session_component() { return _cpu_session_component; } Cpu_session_component &cpu_session_component()
Region_map_component *region_map_component() { return _region_map_component; } {
if (!_cpu_session_component) {
Genode::error("_cpu_session_component is not set");
abort();
}
return *_cpu_session_component;
}
Region_map_component &region_map_component()
{
if (!_region_map_component) {
Genode::error("_region_map_component is not set");
abort();
}
return *_region_map_component;
}
}; };
#endif /* _GENODE_CHILD_RESOURCES_H_ */ #endif /* _GENODE_CHILD_RESOURCES_H_ */

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2016 Genode Labs GmbH * Copyright (C) 2016-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -22,9 +22,10 @@
#include "region_map_component.h" #include "region_map_component.h"
namespace Gdb_monitor { namespace Gdb_monitor {
class Pd_session_component;
typedef Genode::Local_service<Pd_session_component> Pd_service;
using namespace Genode; using namespace Genode;
class Pd_session_component;
typedef Local_service<Pd_session_component> Pd_service;
} }
class Gdb_monitor::Pd_session_component : public Rpc_object<Pd_session> class Gdb_monitor::Pd_session_component : public Rpc_object<Pd_session>
@ -32,6 +33,7 @@ class Gdb_monitor::Pd_session_component : public Rpc_object<Pd_session>
private: private:
Rpc_entrypoint &_ep; Rpc_entrypoint &_ep;
Allocator &_alloc;
Pd_connection _pd; Pd_connection _pd;
@ -44,13 +46,18 @@ class Gdb_monitor::Pd_session_component : public Rpc_object<Pd_session>
/** /**
* Constructor * Constructor
*/ */
Pd_session_component(char const *binary_name, Rpc_entrypoint &ep, Pd_session_component(Rpc_entrypoint &ep,
Env &env,
Allocator &alloc,
char const *binary_name,
Dataspace_pool &managed_ds_map) Dataspace_pool &managed_ds_map)
: :
_ep(ep), _pd(binary_name), _ep(ep),
_address_space(_ep, managed_ds_map, _pd, _pd.address_space()), _alloc(alloc),
_stack_area (_ep, managed_ds_map, _pd, _pd.stack_area()), _pd(env, binary_name),
_linker_area (_ep, managed_ds_map, _pd, _pd.linker_area()) _address_space(_ep, _alloc, managed_ds_map, _pd, _pd.address_space()),
_stack_area (_ep, _alloc, managed_ds_map, _pd, _pd.stack_area()),
_linker_area (_ep, _alloc, managed_ds_map, _pd, _pd.linker_area())
{ {
_ep.manage(this); _ep.manage(this);
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -20,7 +20,7 @@
using namespace Genode; using namespace Genode;
using namespace Gdb_monitor; using namespace Gdb_monitor;
Ram_session_component::Ram_session_component(Genode::Env &env, const char *args, Ram_session_component::Ram_session_component(Env &env, const char *args,
Affinity const &affinity) Affinity const &affinity)
: _env(env), : _env(env),
_parent_ram_session(_env.session<Ram_session>(_id_space_element.id(), args, affinity)) _parent_ram_session(_env.session<Ram_session>(_id_space_element.id(), args, affinity))

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2006-2016 Genode Labs GmbH * Copyright (C) 2006-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -20,29 +20,30 @@
namespace Gdb_monitor namespace Gdb_monitor
{ {
class Ram_session_component;
using namespace Genode; using namespace Genode;
class Ram_session_component;
} }
class Gdb_monitor::Ram_session_component : public Rpc_object<Ram_session> class Gdb_monitor::Ram_session_component : public Rpc_object<Ram_session>
{ {
private: private:
Genode::Env &_env; Env &_env;
Genode::Parent::Client _parent_client; Parent::Client _parent_client;
Id_space<Parent::Client>::Element const _id_space_element Id_space<Parent::Client>::Element const _id_space_element
{ _parent_client, _env.id_space() }; { _parent_client, _env.id_space() };
Genode::Ram_session_client _parent_ram_session; Ram_session_client _parent_ram_session;
public: public:
/** /**
* Constructor * Constructor
*/ */
Ram_session_component(Genode::Env &env, const char *args, Ram_session_component(Env &env, const char *args,
Affinity const &affinity); Affinity const &affinity);
/** /**
@ -55,12 +56,12 @@ class Gdb_monitor::Ram_session_component : public Rpc_object<Ram_session>
** RAM Session interface ** ** RAM Session interface **
***************************/ ***************************/
Ram_dataspace_capability alloc(Genode::size_t, Cache_attribute); Ram_dataspace_capability alloc(size_t, Cache_attribute);
void free(Ram_dataspace_capability); void free(Ram_dataspace_capability);
int ref_account(Ram_session_capability); int ref_account(Ram_session_capability);
int transfer_quota(Ram_session_capability, Genode::size_t); int transfer_quota(Ram_session_capability, size_t);
Genode::size_t quota(); size_t quota();
Genode::size_t used(); size_t used();
}; };
#endif /* _RAM_SESSION_COMPONENT_H_ */ #endif /* _RAM_SESSION_COMPONENT_H_ */

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -75,7 +75,7 @@ Region_map_component::attach(Dataspace_capability ds_cap, size_t size,
executable); executable);
Lock::Guard lock_guard(_region_map_lock); Lock::Guard lock_guard(_region_map_lock);
_region_map.insert(new (env()->heap()) Region(addr, (void*)((addr_t)addr + size - 1), ds_cap, offset)); _region_map.insert(new (_alloc) Region(addr, (void*)((addr_t)addr + size - 1), ds_cap, offset));
return addr; return addr;
} }
@ -92,7 +92,7 @@ void Region_map_component::detach(Region_map::Local_addr local_addr)
return; return;
} }
_region_map.remove(region); _region_map.remove(region);
destroy(env()->heap(), region); destroy(_alloc, region);
} }
@ -111,16 +111,18 @@ Region_map::State Region_map_component::state()
Dataspace_capability Region_map_component::dataspace() Dataspace_capability Region_map_component::dataspace()
{ {
Dataspace_capability ds_cap = _parent_region_map.dataspace(); Dataspace_capability ds_cap = _parent_region_map.dataspace();
_managed_ds_map.insert(new (env()->heap()) Dataspace_object(ds_cap, this)); _managed_ds_map.insert(new (_alloc) Dataspace_object(ds_cap, this));
return ds_cap; return ds_cap;
} }
Region_map_component::Region_map_component(Rpc_entrypoint &ep, Region_map_component::Region_map_component(Rpc_entrypoint &ep,
Allocator &alloc,
Dataspace_pool &managed_ds_map, Dataspace_pool &managed_ds_map,
Pd_session_capability pd, Pd_session_capability pd,
Capability<Region_map> parent_region_map) Capability<Region_map> parent_region_map)
: :
_ep(ep), _ep(ep),
_alloc(alloc),
_pd(pd), _pd(pd),
_parent_region_map(parent_region_map), _parent_region_map(parent_region_map),
_managed_ds_map(managed_ds_map) _managed_ds_map(managed_ds_map)

View File

@ -6,7 +6,7 @@
*/ */
/* /*
* Copyright (C) 2006-2016 Genode Labs GmbH * Copyright (C) 2006-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -31,11 +31,13 @@ namespace Gdb_monitor {
{ {
private: private:
Rpc_entrypoint &_ep; Rpc_entrypoint &_ep;
Pd_session_capability _pd; Allocator &_alloc;
Genode::Region_map_client _parent_region_map; Pd_session_capability _pd;
Region_map_client _parent_region_map;
public: public:
@ -44,7 +46,7 @@ namespace Gdb_monitor {
private: private:
void *_start; void *_start;
void *_end; void *_end;
Genode::off_t _offset; off_t _offset;
Dataspace_capability _ds_cap; Dataspace_capability _ds_cap;
public: public:
@ -63,7 +65,7 @@ namespace Gdb_monitor {
} }
void *start() { return _start; } void *start() { return _start; }
Genode::off_t offset() { return _offset; } off_t offset() { return _offset; }
Dataspace_capability ds_cap() { return _ds_cap; } Dataspace_capability ds_cap() { return _ds_cap; }
}; };
@ -78,9 +80,10 @@ namespace Gdb_monitor {
/** /**
* Constructor * Constructor
*/ */
Region_map_component(Rpc_entrypoint &ep, Region_map_component(Rpc_entrypoint &ep,
Dataspace_pool &managed_ds_map, Allocator &alloc,
Pd_session_capability pd, Dataspace_pool &managed_ds_map,
Pd_session_capability pd,
Capability<Region_map> parent_region_map); Capability<Region_map> parent_region_map);
~Region_map_component(); ~Region_map_component();
@ -98,8 +101,8 @@ namespace Gdb_monitor {
** Region manager session interface ** ** Region manager session interface **
**************************************/ **************************************/
Local_addr attach (Dataspace_capability, Genode::size_t, Local_addr attach (Dataspace_capability, size_t,
Genode::off_t, bool, Local_addr, bool) override; off_t, bool, Local_addr, bool) override;
void detach (Local_addr) override; void detach (Local_addr) override;
void fault_handler (Signal_context_capability) override; void fault_handler (Signal_context_capability) override;
State state () override; State state () override;

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -24,38 +24,11 @@
namespace Gdb_monitor namespace Gdb_monitor
{ {
using namespace Genode;
class Rom_session_component; class Rom_session_component;
class Local_rom_factory; class Local_rom_factory;
typedef Genode::Local_service<Rom_session_component> Rom_service; typedef Local_service<Rom_session_component> Rom_service;
using namespace Genode;
}
/**
* Clone a ROM dataspace in RAM
*/
static Genode::Capability<Genode::Ram_dataspace>
clone_rom(Genode::Capability<Genode::Rom_dataspace> rom_cap)
{
using namespace Genode;
Genode::size_t rom_size = Dataspace_client(rom_cap).size();
Capability<Ram_dataspace> clone_cap = env()->ram_session()->alloc(rom_size);
if (!clone_cap.valid()) {
error(__func__, ": memory allocation for cloned dataspace failed");
return Capability<Ram_dataspace>();
}
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;
} }
@ -66,20 +39,51 @@ class Gdb_monitor::Rom_session_component : public Rpc_object<Rom_session>
{ {
private: private:
Genode::Rpc_entrypoint &_ep; Env &_env;
Rpc_entrypoint &_ep;
Capability<Ram_dataspace> _clone_cap;
/**
* Clone a ROM dataspace in RAM
*/
Capability<Ram_dataspace> _clone_rom(Capability<Rom_dataspace> rom_cap)
{
using namespace Genode;
size_t rom_size = Dataspace_client(rom_cap).size();
Capability<Ram_dataspace> clone_cap = _env.ram().alloc(rom_size);
if (!clone_cap.valid()) {
error(__func__, ": memory allocation for cloned dataspace failed");
return Capability<Ram_dataspace>();
}
void *rom = _env.rm().attach(rom_cap);
void *clone = _env.rm().attach(clone_cap);
memcpy(clone, rom, rom_size);
_env.rm().detach(rom);
_env.rm().detach(clone);
return clone_cap;
}
Capability<Ram_dataspace> _clone_cap;
public: public:
Rom_session_component(Genode::Rpc_entrypoint &ep, char const *filename) Rom_session_component(Env &env,
: _ep(ep), Rpc_entrypoint &ep,
_clone_cap(clone_rom(Rom_connection(filename).dataspace())) char const *filename)
: _env(env),
_ep(ep),
_clone_cap(_clone_rom(Rom_connection(env, filename).dataspace()))
{ _ep.manage(this); } { _ep.manage(this); }
~Rom_session_component() ~Rom_session_component()
{ {
env()->ram_session()->free(_clone_cap); _env.ram().free(_clone_cap);
_ep.dissolve(this); _ep.dissolve(this);
} }
@ -93,7 +97,7 @@ class Gdb_monitor::Rom_session_component : public Rpc_object<Rom_session>
static_cap_cast<Dataspace>(_clone_cap)); static_cap_cast<Dataspace>(_clone_cap));
} }
void sigh(Genode::Signal_context_capability) override { } void sigh(Signal_context_capability) override { }
}; };
@ -101,13 +105,14 @@ class Gdb_monitor::Local_rom_factory : public Rom_service::Factory
{ {
private: private:
Genode::Env &_env; Env &_env;
Genode::Rpc_entrypoint &_ep; Rpc_entrypoint &_ep;
Allocator &_alloc;
public: public:
Local_rom_factory(Genode::Env &env, Genode::Rpc_entrypoint &ep) Local_rom_factory(Env &env, Rpc_entrypoint &ep, Allocator &alloc)
: _env(env), _ep(ep) { } : _env(env), _ep(ep), _alloc(alloc) { }
/*********************** /***********************
** Factory interface ** ** Factory interface **
@ -117,15 +122,17 @@ class Gdb_monitor::Local_rom_factory : public Rom_service::Factory
{ {
Session_label const label = label_from_args(args.string()); Session_label const label = label_from_args(args.string());
return *new (env()->heap()) return *new (_alloc)
Rom_session_component(_ep, label.last_element().string()); Rom_session_component(_env,
_ep,
label.last_element().string());
} }
void upgrade(Rom_session_component &, Args const &) override { } void upgrade(Rom_session_component &, Args const &) override { }
void destroy(Rom_session_component &session) override void destroy(Rom_session_component &session) override
{ {
Genode::destroy(env()->heap(), &session); Genode::destroy(_alloc, &session);
} }
}; };

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -16,16 +16,17 @@
using namespace Genode; using namespace Genode;
using namespace Gdb_monitor; using namespace Gdb_monitor;
Signal_handler_thread::Signal_handler_thread(Signal_receiver *receiver) Signal_handler_thread::Signal_handler_thread(Env &env,
Signal_receiver &receiver)
: :
Thread_deprecated<SIGNAL_HANDLER_THREAD_STACK_SIZE>("sig_handler"), Thread(env, "sig_handler", SIGNAL_HANDLER_THREAD_STACK_SIZE),
_signal_receiver(receiver) { } _signal_receiver(receiver) { }
void Signal_handler_thread::entry() void Signal_handler_thread::entry()
{ {
while(1) { while(1) {
Signal s = _signal_receiver->wait_for_signal(); Signal s = _signal_receiver.wait_for_signal();
Signal_dispatcher_base *signal_dispatcher = Signal_dispatcher_base *signal_dispatcher =
dynamic_cast<Signal_dispatcher_base*>(s.context()); dynamic_cast<Signal_dispatcher_base*>(s.context());

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -17,22 +17,21 @@
#include <base/signal.h> #include <base/signal.h>
#include <base/thread.h> #include <base/thread.h>
using namespace Genode;
namespace Gdb_monitor { namespace Gdb_monitor {
using namespace Genode;
enum { SIGNAL_HANDLER_THREAD_STACK_SIZE = 2*1024*sizeof(addr_t) }; enum { SIGNAL_HANDLER_THREAD_STACK_SIZE = 2*1024*sizeof(addr_t) };
class Signal_handler_thread class Signal_handler_thread : public Thread
: public Thread_deprecated<SIGNAL_HANDLER_THREAD_STACK_SIZE>
{ {
private: private:
Signal_receiver *_signal_receiver; Signal_receiver &_signal_receiver;
public: public:
Signal_handler_thread(Signal_receiver *receiver); Signal_handler_thread(Env &env, Signal_receiver &receiver);
void entry(); void entry();
}; };

View File

@ -5,12 +5,17 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
#include <cpu_thread/client.h>
#include "cpu_session_component.h"
#include "genode_child_resources.h"
extern "C" { extern "C" {
#define private _private #define private _private
#include "server.h" #include "server.h"
@ -19,11 +24,6 @@ extern "C" {
#define _private private #define _private private
} }
#include <cpu_thread/client.h>
#include "cpu_session_component.h"
#include "genode_child_resources.h"
using namespace Genode; using namespace Genode;
using namespace Gdb_monitor; using namespace Gdb_monitor;
@ -35,11 +35,11 @@ static constexpr bool verbose = false;
Thread_state get_current_thread_state() Thread_state get_current_thread_state()
{ {
Cpu_session_component *csc = genode_child_resources()->cpu_session_component(); Cpu_session_component &csc = genode_child_resources()->cpu_session_component();
ptid_t ptid = ((struct inferior_list_entry*)current_inferior)->id; ptid_t ptid = ((struct inferior_list_entry*)current_inferior)->id;
Cpu_thread_client cpu_thread(csc->thread_cap(ptid.lwp)); Cpu_thread_client cpu_thread(csc.thread_cap(ptid.lwp));
return cpu_thread.state(); return cpu_thread.state();
} }
@ -47,11 +47,11 @@ Thread_state get_current_thread_state()
void set_current_thread_state(Thread_state thread_state) void set_current_thread_state(Thread_state thread_state)
{ {
Cpu_session_component *csc = genode_child_resources()->cpu_session_component(); Cpu_session_component &csc = genode_child_resources()->cpu_session_component();
ptid_t ptid = ((struct inferior_list_entry*)current_inferior)->id; ptid_t ptid = ((struct inferior_list_entry*)current_inferior)->id;
Cpu_thread_client cpu_thread(csc->thread_cap(ptid.lwp)); Cpu_thread_client cpu_thread(csc.thread_cap(ptid.lwp));
cpu_thread.state(thread_state); cpu_thread.state(thread_state);
} }

View File

@ -5,25 +5,28 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
/* Genode includes */
#include <base/log.h>
/* GDB monitor includes */
#include "cpu_session_component.h"
#include "reg-arm.h"
#include "gdbserver_platform_helper.h"
#include "genode_child_resources.h"
extern "C" { extern "C" {
#define private _private #define private _private
#include "genode-low.h" #include "genode-low.h"
#define _private private #define _private private
} }
#include <base/log.h>
#include "cpu_session_component.h"
#include "reg-arm.h"
#include "gdbserver_platform_helper.h"
#include "genode_child_resources.h"
using namespace Genode; using namespace Genode;
static bool in_syscall(Thread_state const &ts) static bool in_syscall(Thread_state const &ts)

View File

@ -5,24 +5,27 @@
*/ */
/* /*
* Copyright (C) 2011-2016 Genode Labs GmbH * Copyright (C) 2011-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
/* Genode includes */
#include <base/log.h>
/* GDB monitor includes */
#include "i386.h"
#include "cpu_session_component.h"
#include "gdbserver_platform_helper.h"
#include "genode_child_resources.h"
extern "C" { extern "C" {
#define private _private #define private _private
#include "genode-low.h" #include "genode-low.h"
#define _private private #define _private private
} }
#include <base/log.h>
#include "i386.h"
#include "cpu_session_component.h"
#include "gdbserver_platform_helper.h"
#include "genode_child_resources.h"
using namespace Genode; using namespace Genode;
static bool in_syscall(Thread_state const &thread_state) static bool in_syscall(Thread_state const &thread_state)