summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjolsa@redhat.com <jolsa@redhat.com>2011-08-28 19:54:51 +0200
committerJiri Olsa <Jiri Olsa jolsa@redhat.com>2012-01-11 19:55:00 +0100
commitb258ebfcf8e7eaf513b61946242a1211d7559be1 (patch)
tree3aba79b2810c4acb8b9888a0cb906565aee0a139
parentfc5fd4495ed32c77c05f87be3d6882b676d8aa29 (diff)
downloadlatrace-b258ebfcf8e7eaf513b61946242a1211d7559be1.tar.gz
latrace-b258ebfcf8e7eaf513b61946242a1211d7559be1.tar.xz
latrace-b258ebfcf8e7eaf513b61946242a1211d7559be1.zip
error simulation: adding sigsegv handler support
-rw-r--r--src/audit-error.c43
-rw-r--r--src/config-bison.y9
-rw-r--r--src/config-flex.l1
-rw-r--r--src/error.c5
-rw-r--r--src/error.h6
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);