From cc04ffcf42aa9b9de32280f17e836048b8a241d2 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Thu, 24 Oct 2013 16:05:31 +0200 Subject: [PATCH] GDB monitor: find out page faulting thread Fixes #898. --- base-foc/include/base/thread_state.h | 4 +-- base-foc/src/base/pager/pager.cc | 2 ++ base-nova/include/base/thread_state.h | 6 ++-- base-nova/src/base/pager/pager.cc | 2 ++ base-okl4/include/base/thread_state.h | 4 +-- base/include/base/thread_state.h | 7 +++-- base/include/base/thread_state_base.h | 31 +++++++++++++++++++ .../app/gdb_monitor/gdbserver/genode-low.cc | 17 ++++++++++ .../app/gdb_monitor/gdbserver/genode-low.h | 2 ++ .../app/gdb_monitor/gdbserver_genode.patch | 6 ++-- 10 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 base/include/base/thread_state_base.h diff --git a/base-foc/include/base/thread_state.h b/base-foc/include/base/thread_state.h index d5ebd4ddcc..31e6c3167e 100644 --- a/base-foc/include/base/thread_state.h +++ b/base-foc/include/base/thread_state.h @@ -18,11 +18,11 @@ #include #include -#include +#include namespace Genode { - struct Thread_state : public Cpu_state + struct Thread_state : Thread_state_base { Native_thread kcap; /* thread's gate cap in its pd */ int id; /* id of gate capability */ diff --git a/base-foc/src/base/pager/pager.cc b/base-foc/src/base/pager/pager.cc index 5121f2738a..075619d7c7 100644 --- a/base-foc/src/base/pager/pager.cc +++ b/base-foc/src/base/pager/pager.cc @@ -81,6 +81,8 @@ void Pager_activation_base::entry() /* handle request */ if (obj->pager(pager)) { /* could not resolv - leave thread in pagefault */ + Lock::Guard guard(obj->state.lock); + obj->state.unresolved_page_fault = true; PDBG("Could not resolve pf=%p ip=%p", (void*)pager.fault_addr(), (void*)pager.fault_ip()); } else { diff --git a/base-nova/include/base/thread_state.h b/base-nova/include/base/thread_state.h index bcfdb3f688..8228199227 100644 --- a/base-nova/include/base/thread_state.h +++ b/base-nova/include/base/thread_state.h @@ -16,16 +16,16 @@ #ifndef _INCLUDE__BASE__THREAD_STATE_H_ #define _INCLUDE__BASE__THREAD_STATE_H_ -#include +#include namespace Genode { - struct Thread_state : public Cpu_state + struct Thread_state : Thread_state_base { bool is_vcpu; addr_t sel_exc_base; - Thread_state() : Cpu_state(), is_vcpu(false), sel_exc_base(~0UL) { } + Thread_state() : is_vcpu(false), sel_exc_base(~0UL) { } Thread_state(bool is_vcpu, addr_t sel_exc_base) : is_vcpu(is_vcpu), sel_exc_base(sel_exc_base) { } diff --git a/base-nova/src/base/pager/pager.cc b/base-nova/src/base/pager/pager.cc index 261f7d016c..fcdd93158d 100644 --- a/base-nova/src/base/pager/pager.cc +++ b/base-nova/src/base/pager/pager.cc @@ -80,6 +80,8 @@ void Pager_object::_page_fault_handler() } if (ret == 1) { + obj->_state.thread.unresolved_page_fault = true; + char client_name[Context::NAME_LEN]; myself->name(client_name, sizeof(client_name)); diff --git a/base-okl4/include/base/thread_state.h b/base-okl4/include/base/thread_state.h index 7148a8f083..ecbe2c0e56 100644 --- a/base-okl4/include/base/thread_state.h +++ b/base-okl4/include/base/thread_state.h @@ -20,11 +20,11 @@ namespace Okl4 { extern "C" { #include } } -#include +#include namespace Genode { - struct Thread_state : public Cpu_state + struct Thread_state : Thread_state_base { Okl4::L4_ThreadId_t tid; /* OKL4 specific thread id */ }; diff --git a/base/include/base/thread_state.h b/base/include/base/thread_state.h index e03b1f000e..37a02a9e61 100644 --- a/base/include/base/thread_state.h +++ b/base/include/base/thread_state.h @@ -3,7 +3,8 @@ * \author Norman Feske * \date 2007-07-30 * - * This file contains the generic part of the thread state. + * This file provides a generic implementation of the 'Thread state' class. + * Base platforms can provide their own version of this file. */ /* @@ -16,11 +17,11 @@ #ifndef _INCLUDE__BASE__THREAD_STATE_H_ #define _INCLUDE__BASE__THREAD_STATE_H_ -#include +#include namespace Genode { - struct Thread_state : public Cpu_state { }; + struct Thread_state : Thread_state_base { }; } #endif /* _INCLUDE__BASE__THREAD_STATE_H_ */ diff --git a/base/include/base/thread_state_base.h b/base/include/base/thread_state_base.h new file mode 100644 index 0000000000..b72b1f3388 --- /dev/null +++ b/base/include/base/thread_state_base.h @@ -0,0 +1,31 @@ +/* + * \brief Thread state base class + * \author Norman Feske + * \date 2007-07-30 + * + * This file contains the generic part of the thread state. + */ + +/* + * Copyright (C) 2007-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 _INCLUDE__BASE__THREAD_STATE_BASE_H_ +#define _INCLUDE__BASE__THREAD_STATE_BASE_H_ + +#include + +namespace Genode { + + struct Thread_state_base : Cpu_state + { + bool unresolved_page_fault; + + Thread_state_base() : unresolved_page_fault(false) { }; + }; +} + +#endif /* _INCLUDE__BASE__THREAD_STATE_BASE_H_ */ diff --git a/ports/src/app/gdb_monitor/gdbserver/genode-low.cc b/ports/src/app/gdb_monitor/gdbserver/genode-low.cc index 5df427c3ef..74f598dc07 100644 --- a/ports/src/app/gdb_monitor/gdbserver/genode-low.cc +++ b/ports/src/app/gdb_monitor/gdbserver/genode-low.cc @@ -181,6 +181,23 @@ void genode_continue_thread(unsigned long lwpid, int single_step) } +unsigned long genode_find_segfault_lwpid() +{ + Cpu_session_component *csc = gdb_stub_thread()->cpu_session_component(); + + Thread_capability thread_cap = csc->first(); + + while (thread_cap.valid()) { + Thread_state thread_state = csc->state(thread_cap); + if (thread_state.unresolved_page_fault) + return csc->lwpid(thread_cap); + thread_cap = csc->next(thread_cap); + } + + PDBG("could not determine thread which caused the page fault"); + return 1; +} + class Memory_model { diff --git a/ports/src/app/gdb_monitor/gdbserver/genode-low.h b/ports/src/app/gdb_monitor/gdbserver/genode-low.h index 4ef0f7c840..19fb10b37f 100644 --- a/ports/src/app/gdb_monitor/gdbserver/genode-low.h +++ b/ports/src/app/gdb_monitor/gdbserver/genode-low.h @@ -31,6 +31,8 @@ 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_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); diff --git a/ports/src/app/gdb_monitor/gdbserver_genode.patch b/ports/src/app/gdb_monitor/gdbserver_genode.patch index 9f02b4844b..30793a88c3 100644 --- a/ports/src/app/gdb_monitor/gdbserver_genode.patch +++ b/ports/src/app/gdb_monitor/gdbserver_genode.patch @@ -651,7 +651,7 @@ index 69c6b57..cffa803 100644 x86_supports_tracepoints, x86_get_thread_area, diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c -index 650ddf8..046dd2e 100644 +index 650ddf8..728da30 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -18,11 +18,14 @@ @@ -756,11 +756,11 @@ index 650ddf8..046dd2e 100644 + genode_stop_all_threads(); + + if (sig > 0) { -+ event_ptid.lwp = sig; ++ event_ptid.lwp = sig; + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_TRAP; + } else { -+ event_ptid.lwp = 1; ++ event_ptid.lwp = genode_find_segfault_lwpid(); + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_SEGV; + }