diff --git a/repos/dde_linux/src/lib/lx_emul/debug.cc b/repos/dde_linux/src/lib/lx_emul/debug.cc index 6116fe4e2c..e10eba74a6 100644 --- a/repos/dde_linux/src/lib/lx_emul/debug.cc +++ b/repos/dde_linux/src/lib/lx_emul/debug.cc @@ -23,7 +23,6 @@ using namespace Genode; extern "C" void lx_emul_trace_and_stop(const char * func) { error("Function ", func, " not implemented yet!"); - log("Backtrace follows:"); backtrace(); log("Will sleep forever..."); sleep_forever(); diff --git a/repos/os/include/os/backtrace.h b/repos/os/include/os/backtrace.h new file mode 100644 index 0000000000..9a244d0abf --- /dev/null +++ b/repos/os/include/os/backtrace.h @@ -0,0 +1,91 @@ +/* + * \brief Frame-pointer-based backtrace utility + * \author Christian Helmuth + * \date 2023-12-14 + * + * To use this utility compile your code with the -fno-omit-frame-pointer GCC + * option. + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__OS__BACKTRACE_H_ +#define _INCLUDE__OS__BACKTRACE_H_ + +#include +#include +#include +#include + + +namespace Genode { + void for_each_return_address(auto const &); + void for_each_return_address(Const_byte_range_ptr const &, auto const &); + + struct Backtrace; + + void inline backtrace() __attribute__((always_inline)); +} + +#include /* for_each_return_address(fn, stack) */ + + +/** + * Walk backtrace and call fn() per step + * + * The walk is limited to the memory of the current thread's stack to prevent + * access outside of mapped memory regions. fn() is passed a pointer to the + * stack location of the return address. + */ +void Genode::for_each_return_address(auto const &fn) +{ + Thread::Stack_info const si { Thread::mystack() }; + Const_byte_range_ptr const stack { (char const *)si.base, si.top - si.base }; + + for_each_return_address(stack, fn); +} + + +/** + * Printable backtrace for Genode::log(), Genode::trace(), etc. + */ +struct Genode::Backtrace +{ + void print(Output &out) const + { + using Genode::print; + + print(out, "backtrace \"", Thread::myself()->name(), "\""); + + struct Addr : Hex { Addr(void *v) : Hex((addr_t)v, OMIT_PREFIX) { } }; + + unsigned width = 0; + for_each_return_address([&] (void **p) { + width = max(width, printed_length(Addr(*p))); + }); + if (!width) { + print(out, "\n "); + return; + } + + for_each_return_address([&] (void **p) { + print(out, "\n ", Addr(p), " ", Right_aligned(width, Addr(*p))); + }); + } +}; + + +/** + * Print backtrace via Genode::log() + */ +void inline Genode::backtrace() +{ + Genode::log(Backtrace()); +} + +#endif /* _INCLUDE__OS__BACKTRACE_H_ */ diff --git a/repos/os/include/spec/arm/os/backtrace.h b/repos/os/include/spec/arm/os/backtrace.h deleted file mode 100644 index 99865f384d..0000000000 --- a/repos/os/include/spec/arm/os/backtrace.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * \brief Backtrace helper utility - * \date 2015-09-18 - * \author Christian Prochaska - * \author Stefan Kalkowski - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__SPEC__ARM__OS__BACKTRACE_H_ -#define _INCLUDE__SPEC__ARM__OS__BACKTRACE_H_ - -#include - -namespace Genode { void inline backtrace() __attribute__((always_inline)); } - -/** - * Print frame pointer based backtrace - * - * To use this function compile your code with the -fno-omit-frame-pointer GCC - * option. - */ -void inline Genode::backtrace() -{ - addr_t * fp; - - asm volatile ("mov %0, %%fp" : "=r"(fp) : :); - - while (fp && *fp) { - Genode::log(Hex(*fp)); - fp = (addr_t*)*(fp - 1); - } -} - -#endif /* _INCLUDE__SPEC__ARM__OS__BACKTRACE_H_ */ diff --git a/repos/os/include/spec/arm/os/for_each_return_address.h b/repos/os/include/spec/arm/os/for_each_return_address.h new file mode 100644 index 0000000000..858e6a0f4a --- /dev/null +++ b/repos/os/include/spec/arm/os/for_each_return_address.h @@ -0,0 +1,33 @@ +/* + * \brief Backtrace helper utility (arm_v6/v7a) + * \author Christian Prochaska + * \author Stefan Kalkowski + * \author Christian Helmuth + * \date 2015-09-18 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__ARM__OS__FOR_EACH_RETURN_ADDRESS_H_ +#define _INCLUDE__SPEC__ARM__OS__FOR_EACH_RETURN_ADDRESS_H_ + +/* included from os/backtrace.h */ + +void Genode::for_each_return_address(Const_byte_range_ptr const &stack, auto const &fn) +{ + void **fp; + + asm volatile ("mov %0, %%fp" : "=r"(fp) : :); + + while (stack.contains(fp - 1) && stack.contains(fp) && fp[0]) { + fn(fp); + fp = (void **) fp[-1]; + } +} + +#endif /* _INCLUDE__SPEC__ARM__OS__FOR_EACH_RETURN_ADDRESS_H_ */ diff --git a/repos/os/include/spec/arm_64/os/backtrace.h b/repos/os/include/spec/arm_64/os/backtrace.h deleted file mode 100644 index 2f66a83b2a..0000000000 --- a/repos/os/include/spec/arm_64/os/backtrace.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * \brief Backtrace helper utility - * \date 2020-01-21 - * \author Stefan Kalkowski - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__SPEC__ARM_64__OS__BACKTRACE_H_ -#define _INCLUDE__SPEC__ARM_64__OS__BACKTRACE_H_ - -#include - -namespace Genode { void inline backtrace() __attribute__((always_inline)); } - -/** - * Print frame pointer based backtrace - * - * To use this function compile your code with the -fno-omit-frame-pointer GCC - * option. - */ -void inline Genode::backtrace() -{ - addr_t * fp; - - asm volatile ("mov %0, x29" : "=r"(fp) ::); - - while (fp) { - addr_t ip = fp[1]; - fp = (addr_t*) fp[0]; - Genode::log(Hex(ip)); - } -} - -#endif /* _INCLUDE__SPEC__ARM_64__OS__BACKTRACE_H_ */ - diff --git a/repos/os/include/spec/arm_64/os/for_each_return_address.h b/repos/os/include/spec/arm_64/os/for_each_return_address.h new file mode 100644 index 0000000000..f9e8b159fd --- /dev/null +++ b/repos/os/include/spec/arm_64/os/for_each_return_address.h @@ -0,0 +1,32 @@ +/* + * \brief Backtrace helper utility (arm_v8a) + * \author Stefan Kalkowski + * \author Christian Helmuth + * \date 2020-01-21 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__ARM_64__OS__FOR_EACH_RETURN_ADDRESS_H_ +#define _INCLUDE__SPEC__ARM_64__OS__FOR_EACH_RETURN_ADDRESS_H_ + +/* included from os/backtrace.h */ + +void Genode::for_each_return_address(Const_byte_range_ptr const &stack, auto const &fn) +{ + void **fp; + + asm volatile ("mov %0, x29" : "=r"(fp) ::); + + while (stack.contains(fp) && stack.contains(fp + 1) && fp[1]) { + fn(fp + 1); + fp = (void **) fp[0]; + } +} + +#endif /* _INCLUDE__SPEC__ARM_64__OS__FOR_EACH_RETURN_ADDRESS_H_ */ diff --git a/repos/os/include/spec/x86_32/os/backtrace.h b/repos/os/include/spec/x86_32/os/backtrace.h deleted file mode 100644 index e6c930cbc1..0000000000 --- a/repos/os/include/spec/x86_32/os/backtrace.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * \brief Backtrace helper utility - * \date 2015-09-18 - * \author Christian Prochaska - * \author Stefan Kalkowski - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__SPEC__X86_32__OS__BACKTRACE_H_ -#define _INCLUDE__SPEC__X86_32__OS__BACKTRACE_H_ - -#include -#include - -namespace Genode { void inline backtrace() __attribute__((always_inline)); } - -/** - * Print frame pointer based backtrace - * - * To use this function compile your code with the -fno-omit-frame-pointer GCC - * option. - */ -void inline Genode::backtrace() -{ - Genode::addr_t * fp; - - asm volatile ("movl %%ebp, %0" : "=r"(fp) : :); - - while (fp && *(fp + 1)) { - Genode::log(Hex(*(fp + 1))); - fp = (Genode::addr_t*)*fp; - } -} - -#endif /* _INCLUDE__SPEC__X86_32__OS__BACKTRACE_H_ */ diff --git a/repos/os/include/spec/x86_32/os/for_each_return_address.h b/repos/os/include/spec/x86_32/os/for_each_return_address.h new file mode 100644 index 0000000000..29d6a6eaaa --- /dev/null +++ b/repos/os/include/spec/x86_32/os/for_each_return_address.h @@ -0,0 +1,33 @@ +/* + * \brief Backtrace helper utility (x86_32) + * \author Christian Prochaska + * \author Stefan Kalkowski + * \author Christian Helmuth + * \date 2015-09-18 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__X86_32__OS__FOR_EACH_RETURN_ADDRESS_H_ +#define _INCLUDE__SPEC__X86_32__OS__FOR_EACH_RETURN_ADDRESS_H_ + +/* included from os/backtrace.h */ + +void Genode::for_each_return_address(Const_byte_range_ptr const &stack, auto const &fn) +{ + void **fp; + + asm volatile ("movl %%ebp, %0" : "=r"(fp) : :); + + while (stack.contains(fp) && stack.contains(fp + 1) && fp[1]) { + fn(fp + 1); + fp = (void **) fp[0]; + } +} + +#endif /* _INCLUDE__SPEC__X86_32__OS__FOR_EACH_RETURN_ADDRESS_H_ */ diff --git a/repos/os/include/spec/x86_64/os/backtrace.h b/repos/os/include/spec/x86_64/os/backtrace.h deleted file mode 100644 index 2e6849f39e..0000000000 --- a/repos/os/include/spec/x86_64/os/backtrace.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * \brief Backtrace helper utility - * \date 2015-09-18 - * \author Christian Prochaska - * \author Stefan Kalkowski - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__SPEC__X86_64__OS__BACKTRACE_H_ -#define _INCLUDE__SPEC__X86_64__OS__BACKTRACE_H_ - -#include -#include - -namespace Genode { void inline backtrace() __attribute__((always_inline)); } - -/** - * Print frame pointer based backtrace - * - * To use this function compile your code with the -fno-omit-frame-pointer GCC - * option. - */ -void inline Genode::backtrace() -{ - Genode::addr_t * fp; - - asm volatile ("movq %%rbp, %0" : "=r"(fp) : :); - - while (fp && *(fp + 1)) { - Genode::log(Hex(*(fp + 1))); - fp = (Genode::addr_t*)*fp; - } -} - -#endif /* _INCLUDE__SPEC__X86_64__OS__BACKTRACE_H_ */ diff --git a/repos/os/include/spec/x86_64/os/for_each_return_address.h b/repos/os/include/spec/x86_64/os/for_each_return_address.h new file mode 100644 index 0000000000..5b384bfb52 --- /dev/null +++ b/repos/os/include/spec/x86_64/os/for_each_return_address.h @@ -0,0 +1,33 @@ +/* + * \brief Backtrace helper utility (x86_64) + * \author Christian Prochaska + * \author Stefan Kalkowski + * \author Christian Helmuth + * \date 2015-09-18 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__X86_64__OS__FOR_EACH_RETURN_ADDRESS_H_ +#define _INCLUDE__SPEC__X86_64__OS__FOR_EACH_RETURN_ADDRESS_H_ + +/* included from os/backtrace.h */ + +void Genode::for_each_return_address(Const_byte_range_ptr const &stack, auto const &fn) +{ + void **fp; + + asm volatile ("movq %%rbp, %0" : "=r"(fp) : :); + + while (stack.contains(fp) && stack.contains(fp + 1) && fp[1]) { + fn(fp + 1); + fp = (void **) fp[0]; + } +} + +#endif /* _INCLUDE__SPEC__X86_64__OS__FOR_EACH_RETURN_ADDRESS_H_ */