diff options
| author | jolsa@redhat.com <jolsa@redhat.com> | 2011-08-28 19:54:51 +0200 |
|---|---|---|
| committer | Jiri Olsa <Jiri Olsa jolsa@redhat.com> | 2012-01-11 19:55:00 +0100 |
| commit | b258ebfcf8e7eaf513b61946242a1211d7559be1 (patch) | |
| tree | 3aba79b2810c4acb8b9888a0cb906565aee0a139 | |
| parent | fc5fd4495ed32c77c05f87be3d6882b676d8aa29 (diff) | |
| download | latrace-b258ebfcf8e7eaf513b61946242a1211d7559be1.tar.gz latrace-b258ebfcf8e7eaf513b61946242a1211d7559be1.tar.xz latrace-b258ebfcf8e7eaf513b61946242a1211d7559be1.zip | |
error simulation: adding sigsegv handler support
| -rw-r--r-- | src/audit-error.c | 43 | ||||
| -rw-r--r-- | src/config-bison.y | 9 | ||||
| -rw-r--r-- | src/config-flex.l | 1 | ||||
| -rw-r--r-- | src/error.c | 5 | ||||
| -rw-r--r-- | src/error.h | 6 |
5 files changed, 61 insertions, 3 deletions
diff --git a/src/audit-error.c b/src/audit-error.c index 428d41e..b313a56 100644 --- a/src/audit-error.c +++ b/src/audit-error.c @@ -6,6 +6,7 @@ #include <sys/syscall.h> #include <strings.h> #include <string.h> +#include <signal.h> #include "config.h" #include "backtrace.h" @@ -73,6 +74,43 @@ static void share_info(struct lt_config_audit *cfg, dump_backtrace(cfg->sh, 0); } +static struct lt_config_shared *ss_cfg; + +static void sig_segv_handler(int sig) +{ + char text[LT_MAXMSG]; + struct timeval tv; + + gettimeofday(&tv, NULL); + + snprintf(text, LT_MAXMSG, "ERROR SIMULATION got SIGSEGV"); + + if (lt_sh(ss_cfg, pipe)) { + char buf[LT_FIFO_MSG_MAXLEN]; + int len; + + len = lt_fifo_mtext_get(ss_cfg, buf, &tv, text); + /* TODO erro handling */ + lt_fifo_send(ss_cfg, pipe_fd, buf, len); + } else + lt_out_text(ss_cfg->sh, &tv, syscall(SYS_gettid), text); + + dump_backtrace(ss_cfg, 0); + exit(-1); +} + +static int install_sigsegv(struct lt_config_shared *cfg) +{ + struct sigaction act; + + bzero(&act, sizeof(act)); + act.sa_handler = sig_segv_handler; + + ss_cfg = cfg; + + return sigaction(SIGSEGV, &act, NULL); +} + int lt_error_sym_exit(struct lt_config_audit *cfg, struct lt_symbol *sym, struct timeval *tv, @@ -104,6 +142,10 @@ int lt_error_sym_exit(struct lt_config_audit *cfg, /* and share some info about the sinner */ share_info(cfg, esym, tv, lr, inregs); + + if (esym->handle_sigsegv && install_sigsegv(cfg->sh)) + PRINT_VERBOSE(cfg, 1, "failed to install SIGSEGV handler\n"); + return 0; } @@ -135,6 +177,7 @@ static int symbol_add(struct lt_config_audit *cfg, sym->name = strdup(def_sym->symbol); sym->ret = def_sym->ret; + sym->handle_sigsegv = def_sym->handle_sigsegv; e.key = sym->name; e.data = sym; diff --git a/src/config-bison.y b/src/config-bison.y index c93c802..247a270 100644 --- a/src/config-bison.y +++ b/src/config-bison.y @@ -74,6 +74,7 @@ static struct lt_list_head ln_names; %token ERROR %token ERR_DO ERR_DIR ERR_RUN ERR_GO ERR_RETURN ERR_N %token ERR_PROG ERR_ARGS ERR_FILTER ERR_SEQ ERR_START +%token ERR_SIGSEGV %union { @@ -335,7 +336,13 @@ error_return: ERR_RETURN NAME '{' error_return_def '}' error_return_def: error_return_def NAME '=' VALUE { - if (lt_error_return_ass(scfg, &error_app_return, $2, $4)) + if (lt_error_return_ass(scfg, &error_app_return, $2, $4, 0)) + ABORT("failed to add symbol to return definition"); +} +| +error_return_def NAME '=' VALUE ERR_SIGSEGV +{ + if (lt_error_return_ass(scfg, &error_app_return, $2, $4, 1)) ABORT("failed to add symbol to return definition"); } | diff --git a/src/config-flex.l b/src/config-flex.l index 22855e4..5f86b9f 100644 --- a/src/config-flex.l +++ b/src/config-flex.l @@ -129,6 +129,7 @@ ERROR { BEGIN(error); return ERROR; } <error>START { return ERR_START; } <error>FILTER { return ERR_FILTER; } <error>SEQ { return ERR_SEQ; } +<error>SIGSEGV { return ERR_SIGSEGV; } <error>{value} { RETURN_LONG(VALUE); } <error>{name} { RETURN_STR(NAME); } diff --git a/src/error.c b/src/error.c index fefa87d..fc13cad 100644 --- a/src/error.c +++ b/src/error.c @@ -296,6 +296,7 @@ static int prepare_config_error(struct lt_config_app *cfg, strncpy(sym_def->symbol, sym->name, LT_MAXNAME); sym_def->ret = sym->val; sym_def->filter.type = ret->filter.type; + sym_def->handle_sigsegv = sym->handle_sigsegv; PRINT_VERBOSE(cfg, 1, "symbol %s, ret %s\n", sym->name, sym->val); @@ -624,7 +625,8 @@ app_return_get(struct lt_config_app *cfg, struct lt_error_app_return **ret) int lt_error_return_ass(struct lt_config_app *cfg, struct lt_error_app_return **ret, - char *name, unsigned long val) + char *name, unsigned long val, + int handle_sigsegv) { struct lt_error_app_return *app_ret = app_return_get(cfg, ret); struct lt_error_app_return_sym *sym; @@ -638,6 +640,7 @@ int lt_error_return_ass(struct lt_config_app *cfg, sym->name = strdup(name); sym->val = val; + sym->handle_sigsegv = handle_sigsegv; PRINT_VERBOSE(cfg, 1, "%s = %ld\n", sym->name, val); diff --git a/src/error.h b/src/error.h index 367e576..2486549 100644 --- a/src/error.h +++ b/src/error.h @@ -16,6 +16,7 @@ struct lt_error_def_sym { #define LT_MAXNAME 20 char symbol[LT_MAXNAME]; long ret; + int handle_sigsegv; struct lt_error_def_filter filter; }; @@ -38,6 +39,7 @@ struct lt_error_sym { char *name; unsigned long ret; unsigned long call; + int handle_sigsegv; struct lt_error_audit_filter filter; struct lt_list_head list; @@ -46,6 +48,7 @@ struct lt_error_sym { struct lt_error_app_return_sym { char *name; long val; + int handle_sigsegv; struct lt_list_head list; }; @@ -112,7 +115,8 @@ int lt_error_run_args(struct lt_config_app *cfg, struct lt_list_head *args); int lt_error_return_ass(struct lt_config_app *cfg, struct lt_error_app_return **ret, - char *name, unsigned long val); + char *name, unsigned long val, + int handle_sigsegv); int lt_error_return_filter(struct lt_config_app *cfg, struct lt_error_app_return **ret, int type, void *data); |
