implement external interface to library and use it in tests. need to be
reworked a bit to use file descriptor or buffer provided to callse
This commit is contained in:
+30
-22
@@ -10,31 +10,39 @@
|
||||
|
||||
//system
|
||||
#include <ucontext.h>
|
||||
/*
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
#include <libunwind.h>
|
||||
#include <elfutils/libdwfl.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#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_ */
|
||||
|
||||
+1
-1
@@ -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))))
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* libpst.c
|
||||
*
|
||||
* Created on: Feb 5, 2020
|
||||
* Author: nnosov
|
||||
*/
|
||||
|
||||
#include <ucontext.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
+18
-35
@@ -1,9 +1,9 @@
|
||||
//system
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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 <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef void (*sig_handler_t)(int sig);
|
||||
|
||||
@@ -59,24 +60,26 @@ 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;
|
||||
}
|
||||
|
||||
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);
|
||||
int ret = pst_unwind_simple(handler, stdout);
|
||||
if(!ret) {
|
||||
pst_unwind_pretty(handler, stdout);
|
||||
} else {
|
||||
pst_log(SEVERITY_ERROR, "No stack trace obtained");
|
||||
printf("No stack trace obtained\n");
|
||||
}
|
||||
|
||||
pst_del_handler(handler);
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
Reference in New Issue
Block a user