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
|
//system
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
/*
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdint.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <string.h>
|
|
||||||
#include <libunwind.h>
|
|
||||||
#include <elfutils/libdwfl.h>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "utils/list_head.h"
|
typedef struct pst_handler pst_handler;
|
||||||
#include "context.h"
|
|
||||||
|
|
||||||
typedef struct pst_handler {
|
// allocate and initialize libpst handler.
|
||||||
pst_context ctx; // context of unwinding
|
pst_handler* pst_new_handler(ucontext_t* hctx);
|
||||||
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);
|
|
||||||
|
|
||||||
bool pst_handler_handle_dwarf(pst_handler* h);
|
// deallocate libpst handler
|
||||||
void pst_handler_print_dwarf(pst_handler* h);
|
void pst_del_handler(pst_handler* h);
|
||||||
bool pst_handler_unwind(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_ */
|
#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")
|
DATE_BUILD = $(shell date +"%D %T")
|
||||||
|
|
||||||
#source and header files search path. add here new directories which contains files specified for $(SRC)
|
#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}))
|
SRC = $(wildcard $(addsuffix /*.cpp,${VPATH}))
|
||||||
OBJ = $(patsubst %.cpp,%.o,$(addprefix $(BUILD_DIR)/,$(notdir $(SRC))))
|
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)
|
void pst_context_init(pst_context* ctx, ucontext_t* hctx)
|
||||||
{
|
{
|
||||||
// global
|
|
||||||
pst_alloc_init(&allocator);
|
|
||||||
pst_log_init_console(&logger);
|
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
ctx->clean_print = clean_print;
|
ctx->clean_print = clean_print;
|
||||||
ctx->print = print;
|
ctx->print = print;
|
||||||
@@ -184,10 +180,6 @@ void pst_context_fini(pst_context* ctx)
|
|||||||
ctx->frame = NULL;
|
ctx->frame = NULL;
|
||||||
ctx->dwfl = NULL;
|
ctx->dwfl = NULL;
|
||||||
ctx->module = 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;
|
||||||
|
}
|
||||||
+20
-37
@@ -1,9 +1,9 @@
|
|||||||
//system
|
//system
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "dwarf/dwarf_handler.h"
|
#include "../include/libpst.h"
|
||||||
#include "context.h"
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DEF_1 = 1,
|
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/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
typedef void (*sig_handler_t)(int sig);
|
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;
|
fatal_error_in_progress = 1;
|
||||||
|
|
||||||
pst_log(SEVERITY_ERROR, "%s signal handled", strsignal(sig));
|
printf("%s signal handled\n", strsignal(sig));
|
||||||
bool ret = false;
|
|
||||||
pst_decl(pst_handler, handler, (ucontext_t*)context);
|
|
||||||
|
|
||||||
if((context != 0) && (sig == SIGSEGV || sig == SIGABRT || sig == SIGBUS || sig == SIGFPE))
|
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
|
// comment out line below to prevent coredump
|
||||||
// exit(EXIT_FAILURE);
|
// exit(EXIT_FAILURE);
|
||||||
@@ -90,20 +93,7 @@ void FatalSignalHandler(int sig, siginfo_t* info, void* context)
|
|||||||
|
|
||||||
void SignalHandler(int sig)
|
void SignalHandler(int sig)
|
||||||
{
|
{
|
||||||
// if (handled_error_in_progress)
|
// do nothing and reset to our handler back
|
||||||
// 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
|
|
||||||
SetSignalHandler();
|
SetSignalHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +107,6 @@ void SetSignalHandler(sig_handler_t handler)
|
|||||||
sigfillset(&ss);
|
sigfillset(&ss);
|
||||||
|
|
||||||
//remove previous handlers
|
//remove previous handlers
|
||||||
// sigdelset(&ss, SIGINT);
|
|
||||||
sigdelset(&ss, SIGUSR1);
|
sigdelset(&ss, SIGUSR1);
|
||||||
sigdelset(&ss, SIGUSR2);
|
sigdelset(&ss, SIGUSR2);
|
||||||
sigdelset(&ss, SIGSEGV);
|
sigdelset(&ss, SIGSEGV);
|
||||||
@@ -136,10 +125,6 @@ void SetSignalHandler(sig_handler_t handler)
|
|||||||
sa.sa_handler = NULL;
|
sa.sa_handler = NULL;
|
||||||
sa.sa_sigaction = NULL;
|
sa.sa_sigaction = NULL;
|
||||||
|
|
||||||
// //set interrupt signal
|
|
||||||
// sa.sa_handler = SignalHandler;
|
|
||||||
// sigaction(SIGINT, &sa, 0);
|
|
||||||
|
|
||||||
//set stop signal
|
//set stop signal
|
||||||
sa.sa_handler = (handler == NULL) ? SignalHandler : handler;
|
sa.sa_handler = (handler == NULL) ? SignalHandler : handler;
|
||||||
sigaction(SIGUSR1, &sa, 0);
|
sigaction(SIGUSR1, &sa, 0);
|
||||||
@@ -176,7 +161,7 @@ void SetSignalHandler(sig_handler_t handler)
|
|||||||
limit.rlim_max = 1073741824;
|
limit.rlim_max = 1073741824;
|
||||||
if (setrlimit(RLIMIT_CORE, &limit))
|
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[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
pst_log_init_console(&logger);
|
|
||||||
//logger->SetCurrentSeverity(SEVERITY_INFO);
|
|
||||||
SetSignalHandler(SigusrHandler);
|
SetSignalHandler(SigusrHandler);
|
||||||
|
|
||||||
Fun1(1, DEF_2, 5);
|
Fun1(1, DEF_2, 5);
|
||||||
|
|||||||
Reference in New Issue
Block a user