From 3faa5f53fa1f239a89d1bda9552332fe5484bd04 Mon Sep 17 00:00:00 2001 From: Shimansky Gregory Date: Thu, 7 Feb 2008 19:28:52 +0300 Subject: [PATCH] Added standalone crash handler header and basic infrastructure implementation --- vm/port/include/port_crash_handler.h | 237 ++++++++++++++++++++++ vm/port/src/crash_handler/port_crash_handler.cpp | 87 ++++++++ 2 files changed, 324 insertions(+), 0 deletions(-) create mode 100644 vm/port/include/port_crash_handler.h create mode 100644 vm/port/src/crash_handler/port_crash_handler.cpp diff --git a/vm/port/include/port_crash_handler.h b/vm/port/include/port_crash_handler.h new file mode 100644 index 0000000..33594b5 --- /dev/null +++ b/vm/port/include/port_crash_handler.h @@ -0,0 +1,237 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef _PORT_CRASH_HANDLER_ +#define _PORT_CRASH_HANDLER_ + + +/** + * @file Interface to signal handling and crash handling functions. + */ + +#include "open/types.h" +// FIXME: needed for Register structure. Should be changed to another +// header when Registers defition is moved to. +#include "vm_core_types.h" + +#ifdef __cplusplus +extern "C" +#endif + +/** + * Signals types handled by the crash handler. + */ +typedef enum +{ + /** + * General protection fault, e.g. SIGSEGV on unix. + */ + PORT_SIGNAL_GPF, + /** + * Special type of GPF when crash happens because of stack + * overflow. It can be handled on the same stack because guard + * page for the handler code is temporarily disabled. + */ + PORT_SIGNAL_STACK_OVERFLOW, + /** + * Process used function abort(). + */ + PORT_SIGNAL_ABORT, + /** + * Process executed a trap, e.g. INT3 on x86. + */ + PORT_SIGNAL_TRAP, + /** + * Process executed a privileged instruction (only on Windows), + * e.g. CLI. + */ + PORT_SIGNAL_PRIV_INSTR, + /** + * Process encountered an arithmeric error, e.g. division by + * zero. + */ + PORT_SIGNAL_ARITHMETIC, + /** + * Maximum identifier for signal type + */ + PORT_SIGNAL_MIN = PORT_SIGNAL_GPF, + /** + * Maximum identifier for signal type + */ + PORT_SIGNAL_MAX = PORT_SIGNAL_ARITHMETIC +} port_sigtype; + +/** + * Function callback type for process signal handlers. These + * callbacks are called by signal handler when some signal occures in + * the process thread. + * + * Callback functions have to be thread safe. + * + * @param signum - signal that in the thread. + * @param regs - platform dependent register context of the process at + * signal point. + * @return TRUE if signal is handled by the process and + * execution should continue. FALSE if signal is not handled + * by the process and crash handler should execute crash sequence. + */ +typedef Boolean (port_signal_handler *)( + port_sigtype signum, + Registers *regs); + +/** + * Signal callback registration information. + */ +typedef struct +{ + /** + * Signal type for callback registration. + */ + port_sigtype signum; + /** + * Callback function to call when signum signal + * occurres. + */ + port_signal_handler callback; +} port_signal_handler_registration; + +/** + * Initialize signals and crash handler and register process signal + * callbacks. + * + * This function should not be called from different threads at the + * same time because it is not thread safe. + * + * @param registrations - Pointer to an array of + * port_signal_handler_registration structures. + * @param count - number of signal registrations. Zero is allowed + * @return TRUE if initalization is successful. + * FALSE if initialization failed. + */ +Boolean port_init_crash_handler( + port_signal_handler_registration *registrations, + unsigned count); + +/** + * Crash handler output flags. + */ +typedef enum +{ + /** + * Crash handler should call debugger instead of exiting the + * process. + */ + PORT_CRASH_CALL_DEBUGGER = 0x0001, + /** + * Crash handler should output all information to stderr. + */ + PORT_CRASH_DUMP_TO_STDERR = 0x0002, + /** + * Crash handler should output all information to a file. + */ + PORT_CRASH_DUMP_TO_FILE = 0x0004, + /** + * Crash handler should show stack dump when crash happens. + */ + PORT_CRASH_STACK_DUMP = 0x0008, + /** + * Crash handler should dump stacks for all threads, not just the + * one that crashed. + */ + PORT_CRASH_DUMP_ALL_THREADS = 0x0010, + /** + * Crash handler should print process command line and working + * directory. + */ + PORT_CRASH_PRINT_COMMAND_LINE = 0x0020, + /** + * Crash handler should print process environment. + */ + PORT_CRASH_PRINT_ENVIRONMENT = 0x0040, + /** + * Crash handler should print modules list. + */ + PORT_CRASH_PRINT_MODULES = 0x0080, + /** + * Crash handler should print thread registers context. + */ + PORT_CRASH_PRINT_REGISTERS = 0x0100, + /** + * Crash handler should print threads list. + */ + PORT_CRASH_PRINT_THREADS_LIST = 0x0200, + /** + * Crash handler should create a core/mini dump of program state. + */ + PORT_CRASH_DUMP_PROCESS_CORE = 0x400 +} port_crash_handler_flags; + +/** + * Set crash handler output flags. Default mode is + * PORT_CRASH_DUMP_TO_STDERR | + * PORT_CRASH_STACK_DUMP | PORT_CRASH_PRINT_COMMAND_LINE | + * PORT_CRASH_PRINT_ENVIRONMENT | PORT_CRASH_PRINT_MODULES | + * PORT_CRASH_PRINT_REGISTERS | PORT_CRASH_PRINT_THREADS_LIST. + * + * @param flags - crash handler output flags. + */ +void port_crash_handler_set_flags(port_crash_handler_flags flags); + +/** + * Callback function that is called at the end of shutdown sequence. + * + * Crash action functions don't have to be thread safe because crash + * sequence is guaranteed to be executed on one thread at a time. + * + * @param signum - signal that in the thread. + * @param regs - platform dependent register context of the process at + * signal point. + */ +typedef void (port_crash_handler_action *)(port_sigtype signum, Registers *regs); + +/** + * Add an action to be done at the end of crash sequence. Actions may + * dump additional information about the state of process specific + * data structures. + * + * This function should not be called from different threads at the + * same time because it is not thread safe. + * + * @param action - action callback pointer + * @return TRUE if action was added successfully, + * FALSE if action was not added because no memory could + * be allocated. + */ +Boolean port_crash_handler_add_action(port_crash_handler_action action); + +/** + * Shutdown signals and crash handler. All signals are assigned their + * default handlers. + * + * This function should not be called from different threads at the + * same time because it is not thread safe. + * + * @return TRUE if shutdown is + * successful. FALSE if shutdown failed. + */ +Boolean port_shutdown_crash_handler(); + +#ifdef __cplusplus +} +#endif + +#endif // _PORT_CRASH_HANDLER_ diff --git a/vm/port/src/crash_handler/port_crash_handler.cpp b/vm/port/src/crash_handler/port_crash_handler.cpp new file mode 100644 index 0000000..0ab94af --- /dev/null +++ b/vm/port/src/crash_handler/port_crash_handler.cpp @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "port_crash_handler.h" + +static port_signal_handler signal_callbacks[PORT_SIGNAL_MAX] = +{ + NULL, // PORT_SIGNAL_GPF + NULL, // PORT_SIGNAL_STACK_OVERFLOW + NULL, // PORT_SIGNAL_ABORT + NULL, // PORT_SIGNAL_TRAP + NULL, // PORT_SIGNAL_PRIV_INSTR + NULL // PORT_SIGNAL_ARITHMETIC +}; + +struct crash_additional_actions +{ + port_crash_handler_action action; + crash_additional_actions *next; +}; + +static crash_additional_actions *crash_actions = NULL; + +static unisigned crash_output_flags; + +Boolean port_init_crash_handler(port_signal_handler_registration *registrations, + unsigned count) +{ + if (initialize_signals() == FALSE) + return FALSE; + + for (int iii = 0; iii < count; iii++) + { + assert(registrations[iii]->signum >= PORT_SIGNAL_MIN); + assert(registrations[iii]->signum <= PORT_SIGNAL_MAX); + signal_callbacks[registrations[iii]->signum] = registrations[iii]->callback; + } + + return TRUE; +} + +void port_crash_handler_set_flags(port_crash_handler_flags flags) +{ + crash_output_flags = flags; +} + +Boolean port_crash_handler_add_action(port_crash_handler_action action) +{ + crash_additional_actions *a = STD_MALLOC(sizeof(crash_additional_actions)); + if (NULL == a) + return FALSE; + + a->action = action; + a->next = crash_actions; + crash_actions = a; + return TRUE; +} + +Boolean port_shutdown_crash_handler() +{ + if (shutdown_signals() == FALSE) + return FALSE; + + for (crash_additional_actions *a = crash_actions; NULL != a;) + { + crash_additional_actions *next = a->next; + STD_FREE(a); + a = next; + } + + return TRUE; +} -- 1.5.3.7