121 lines
3.8 KiB
C++
121 lines
3.8 KiB
C++
/*
|
|
* \brief Support for exceptions libsupc++
|
|
* \author Norman Feske
|
|
* \author Sebastian Sumpf
|
|
* \date 2006-07-21
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2006-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.
|
|
*/
|
|
|
|
/* libsupc++ includes */
|
|
#include <cxxabi.h>
|
|
#include <exception>
|
|
#include <typeinfo>
|
|
|
|
/* Genode includes */
|
|
#include <base/log.h>
|
|
#include <util/string.h>
|
|
|
|
/* base-internal includes */
|
|
#include <base/internal/globals.h>
|
|
|
|
extern "C" char __eh_frame_start__[]; /* from linker script */
|
|
extern "C" void __register_frame (const void *begin); /* from libgcc_eh */
|
|
extern "C" char *__cxa_demangle(const char *mangled_name,
|
|
char *output_buffer,
|
|
size_t *length,
|
|
int *status);
|
|
extern "C" void free(void *ptr);
|
|
|
|
/*
|
|
* This symbol is overwritten by Genode's dynamic linker (ld.lib.so).
|
|
* After setup, the symbol will point to the actual implementation of
|
|
* 'dl_iterate_phdr', which is located within the linker. 'dl_iterate_phdr'
|
|
* iterates through all (linker loaded) binaries and shared libraries. This
|
|
* function has to be implemented in order to support C++ exceptions within
|
|
* shared libraries.
|
|
* Return values of dl_iterate_phdr (gcc 4.2.4):
|
|
* < 0 = error
|
|
* 0 = continue program header iteration
|
|
* > 0 = stop iteration (no errors occured)
|
|
*
|
|
* See also: man dl_iterate_phdr
|
|
*/
|
|
extern "C" int dl_iterate_phdr(int (*callback) (void *info, unsigned long size,
|
|
void *data), void *data) __attribute__((weak));
|
|
extern "C" int dl_iterate_phdr(int (*) (void *, unsigned long, void *), void *) {
|
|
return -1; }
|
|
|
|
|
|
/*
|
|
* Terminate handler
|
|
*/
|
|
|
|
void terminate_handler()
|
|
{
|
|
std::type_info *t = __cxxabiv1::__cxa_current_exception_type();
|
|
|
|
if (!t)
|
|
return;
|
|
|
|
char *demangled_name = __cxa_demangle(t->name(), nullptr, nullptr, nullptr);
|
|
if (demangled_name) {
|
|
Genode::error("Uncaught exception of type "
|
|
"'", Genode::Cstring(demangled_name), "'");
|
|
free(demangled_name);
|
|
} else {
|
|
Genode::error("Uncaught exception of type '", t->name(), "' "
|
|
"(use 'c++filt -t' to demangle)");
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Init program headers of the dynamic linker
|
|
*
|
|
* The weak function is used for statically linked binaries. The
|
|
* dynamic linker provides an implementation that loads the program
|
|
* headers of the linker. This must be done before the first exception
|
|
* is thrown.
|
|
*/
|
|
void Genode::init_ldso_phdr(Env &) __attribute__((weak));
|
|
void Genode::init_ldso_phdr(Env &) { }
|
|
|
|
|
|
/*
|
|
* Initialization
|
|
*/
|
|
void Genode::init_exception_handling(Env &env)
|
|
{
|
|
init_ldso_phdr(env);
|
|
init_cxx_heap(env);
|
|
|
|
__register_frame(__eh_frame_start__);
|
|
|
|
std::set_terminate(terminate_handler);
|
|
|
|
/*
|
|
* Trigger first exception. This step has two purposes.
|
|
* First, it enables us to detect problems related to exception handling as
|
|
* early as possible. If there are problems with the C++ support library,
|
|
* it is much easier to debug them at this early stage. Otherwise problems
|
|
* with half-working exception handling cause subtle failures that are hard
|
|
* to interpret.
|
|
*
|
|
* Second, the C++ support library allocates data structures lazily on the
|
|
* first occurrence of an exception. In some corner cases, this allocation
|
|
* consumes several KB of stack. This is usually not a problem when the
|
|
* first exception is triggered from the main thread but it becomes an
|
|
* issue when the first exception is thrown from the stack of a thread with
|
|
* a specially tailored (and otherwise sufficient) stack size. By throwing
|
|
* an exception here, we mitigate this issue by eagerly performing those
|
|
* allocations.
|
|
*/
|
|
try { throw 1; } catch (...) { }
|
|
}
|