diff --git a/include/libpst.h b/include/libpst.h index 84bceb6..00a7850 100644 --- a/include/libpst.h +++ b/include/libpst.h @@ -10,31 +10,39 @@ //system #include -/* -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -*/ +#include -#include "utils/list_head.h" -#include "context.h" +typedef struct pst_handler pst_handler; -typedef struct pst_handler { - pst_context ctx; // context of unwinding - list_head functions; // list of functions in stack frame -} pst_handler; -void pst_handler_init(pst_handler* h, ucontext_t* hctx); -void pst_handler_fini(pst_handler* h); +// allocate and initialize libpst handler. +pst_handler* pst_new_handler(ucontext_t* hctx); -bool pst_handler_handle_dwarf(pst_handler* h); -void pst_handler_print_dwarf(pst_handler* h); -bool pst_handler_unwind(pst_handler* h); +// deallocate libpst handler +void pst_del_handler(pst_handler* h); + + +// +// Base unwind routines. +// Unwinds current stack trace using base information about program (i.e. print out address, function name) +// + +// write stack trace information to provided file descriptor +int pst_unwind_simple(pst_handler* h, FILE* fd); + +// save stack trace information to provided buffer in RAM +int pst_unwind_simple(pst_handler* h, char* buff, uint32_t buff_size); + + +// Advanced unwind routines. +// Unwinds current stack trace using DWARF debug sections in file if they present and print it to provided file descriptor. +// Additionally to pst_unwind_simple(...) provides types of parameters and variables in functions and their values +// + +// write stack trace information to provided file descriptor +int pst_unwind_pretty(pst_handler* h, FILE* fd); + +// save stack trace information to provided buffer in RAM +int pst_unwind_pretty(pst_handler* h, char* buff, uint32_t buff_size); #endif /* PST_HANDLER_H_ */ diff --git a/src/Makefile b/src/Makefile index 75b046a..9366dd5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -31,7 +31,7 @@ SOFT_BUILD = $(shell STR=`cat $(BUILD_DIR)/version.h 2> /dev/null | grep 'SOFT_B DATE_BUILD = $(shell date +"%D %T") #source and header files search path. add here new directories which contains files specified for $(SRC) -VPATH = . dwarf arch utils +VPATH = ./ ./dwarf ./arch ./utils SRC = $(wildcard $(addsuffix /*.cpp,${VPATH})) OBJ = $(patsubst %.cpp,%.o,$(addprefix $(BUILD_DIR)/,$(notdir $(SRC)))) diff --git a/src/context.cpp b/src/context.cpp index e54d2f7..1423df9 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -151,10 +151,6 @@ bool print_expr_block (pst_context* ctx, Dwarf_Op *exprs, int exprlen, Dwarf_Att void pst_context_init(pst_context* ctx, ucontext_t* hctx) { - // global - pst_alloc_init(&allocator); - pst_log_init_console(&logger); - // methods ctx->clean_print = clean_print; ctx->print = print; @@ -184,10 +180,6 @@ void pst_context_fini(pst_context* ctx) ctx->frame = NULL; ctx->dwfl = NULL; ctx->module = NULL; - - // global - pst_log_fini(&logger); - pst_alloc_fini(&allocator); } diff --git a/src/libpst.cpp b/src/libpst.cpp new file mode 100644 index 0000000..4f9b32e --- /dev/null +++ b/src/libpst.cpp @@ -0,0 +1,91 @@ +/* + * libpst.c + * + * Created on: Feb 5, 2020 + * Author: nnosov + */ + +#include +#include +#include + +#include "utils/allocator.h" +#include "dwarf/dwarf_handler.h" + +// allocate and initialize libpst handler. +pst_handler* pst_new_handler(ucontext_t* hctx) +{ + // global + pst_alloc_init(&allocator); + pst_log_init_console(&logger); + + pst_new(pst_handler, handler, hctx); + return handler; +} + +// deallocate libpst handler +void pst_del_handler(pst_handler* h) +{ + pst_free(h); + + // global + pst_log_fini(&logger); + pst_alloc_fini(&allocator); +} + +// write stack trace information to provided file descriptor +int pst_unwind_simple(pst_handler* h, FILE* fd) +{ + int ret = pst_handler_unwind(h); + if(ret) { + fwrite(h->ctx.buff, 1, strlen(h->ctx.buff), fd); + return 0; + } + + return -1; +} + +// save stack trace information to provided buffer in RAM +int pst_unwind_simple(pst_handler* h, char* buff, uint32_t buff_size) +{ + int ret = pst_handler_unwind(h); + if(ret) { + uint32_t cnt = buff_size < sizeof(h->ctx.buff) ? buff_size : sizeof(h->ctx.buff); + memcpy(buff, h->ctx.buff, cnt - 2); + buff[cnt - 1] = 0; + + return 0; + } + + return -1; +} + + +// write stack trace information to provided file descriptor +int pst_unwind_pretty(pst_handler* h, FILE* fd) +{ + int ret = pst_handler_handle_dwarf(h); + if(ret) { + pst_handler_print_dwarf(h); + fwrite(h->ctx.buff, 1, strlen(h->ctx.buff), fd); + return 0; + } + + return -1; +} + +// save stack trace information to provided buffer in RAM +int pst_unwind_pretty(pst_handler* h, char* buff, uint32_t buff_size) +{ + int ret = pst_handler_handle_dwarf(h); + if(ret) { + pst_handler_print_dwarf(h); + uint32_t cnt = buff_size < sizeof(h->ctx.buff) ? buff_size : sizeof(h->ctx.buff); + memcpy(buff, h->ctx.buff, cnt - 2); + buff[cnt - 1] = 0; + + return 0; + } + + return -1; +} diff --git a/tests/main.cpp b/tests/main.cpp index fcb2cb4..ae4542b 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,9 +1,9 @@ //system #include #include +#include -#include "dwarf/dwarf_handler.h" -#include "context.h" +#include "../include/libpst.h" typedef enum { DEF_1 = 1, @@ -35,6 +35,7 @@ uint32_t Fun1(const int arg1, my_int arg2, uint32_t arg3) #include #include #include +#include typedef void (*sig_handler_t)(int sig); @@ -59,23 +60,25 @@ void FatalSignalHandler(int sig, siginfo_t* info, void* context) fatal_error_in_progress = 1; - pst_log(SEVERITY_ERROR, "%s signal handled", strsignal(sig)); - bool ret = false; - pst_decl(pst_handler, handler, (ucontext_t*)context); - + printf("%s signal handled\n", strsignal(sig)); if((context != 0) && (sig == SIGSEGV || sig == SIGABRT || sig == SIGBUS || sig == SIGFPE)) { - ret = pst_handler_unwind(&handler); + pst_handler* handler = pst_new_handler((ucontext_t*)context); + if(!handler) { + printf("Failed to allocate pst handler\n"); + return; + } + + int ret = pst_unwind_simple(handler, stdout); + if(!ret) { + pst_unwind_pretty(handler, stdout); + } else { + printf("No stack trace obtained\n"); + } + + pst_del_handler(handler); } - if(ret) { - pst_log(SEVERITY_INFO, "%s", handler.ctx.buff); - pst_handler_handle_dwarf(&handler); - pst_handler_print_dwarf(&handler); - pst_log(SEVERITY_INFO, "%s", handler.ctx.buff); - } else { - pst_log(SEVERITY_ERROR, "No stack trace obtained"); - } // comment out line below to prevent coredump // exit(EXIT_FAILURE); @@ -90,20 +93,7 @@ void FatalSignalHandler(int sig, siginfo_t* info, void* context) void SignalHandler(int sig) { -// if (handled_error_in_progress) -// raise (sig); -// handled_error_in_progress = 1; - -// const char* str_sig = strsignal(sig); -// logger->Log(SEVERITY_INFO, "%s received.", str_sig); - if(sig == SIGUSR1) { - pst_log(SEVERITY_INFO, "Maintenance mode enabled."); - } else if(sig == SIGUSR2) { - pst_log(SEVERITY_INFO, "Maintenance mode disabled."); - } -// signal (sig, SIG_DFL); -// raise(sig); - // reset to our handler back + // do nothing and reset to our handler back SetSignalHandler(); } @@ -117,7 +107,6 @@ void SetSignalHandler(sig_handler_t handler) sigfillset(&ss); //remove previous handlers -// sigdelset(&ss, SIGINT); sigdelset(&ss, SIGUSR1); sigdelset(&ss, SIGUSR2); sigdelset(&ss, SIGSEGV); @@ -136,10 +125,6 @@ void SetSignalHandler(sig_handler_t handler) sa.sa_handler = NULL; sa.sa_sigaction = NULL; -// //set interrupt signal -// sa.sa_handler = SignalHandler; -// sigaction(SIGINT, &sa, 0); - //set stop signal sa.sa_handler = (handler == NULL) ? SignalHandler : handler; sigaction(SIGUSR1, &sa, 0); @@ -176,7 +161,7 @@ void SetSignalHandler(sig_handler_t handler) limit.rlim_max = 1073741824; if (setrlimit(RLIMIT_CORE, &limit)) { - pst_log(SEVERITY_DEBUG, "Failed to set limit for core dump file size"); + printf("Failed to set limit for core dump file size\n"); } } @@ -192,8 +177,6 @@ void ResetSignalHandler() { int main(int argc, char* argv[]) { - pst_log_init_console(&logger); - //logger->SetCurrentSeverity(SEVERITY_INFO); SetSignalHandler(SigusrHandler); Fun1(1, DEF_2, 5);