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:
2020-02-05 12:13:26 +04:00
parent d4e9307fe1
commit 24efc4580b
5 changed files with 142 additions and 68 deletions
+30 -22
View File
@@ -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
View File
@@ -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))))
-8
View File
@@ -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);
}
+91
View File
@@ -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
View File
@@ -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);