summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjolsa@redhat.com <jolsa@redhat.com>2011-11-11 19:42:52 -0500
committerJiri Olsa <Jiri Olsa jolsa@redhat.com>2011-11-13 11:06:42 +0100
commit291cd946a26bfd3a6edf1a232e1a2bf7888ddf42 (patch)
tree5e1243a9ca2bf8328e6b5627ca7821df5599f402
parent78a2fe366cf23632dd561e34d849e7fceaefd017 (diff)
downloadlatrace-error_simulation.tar.gz
latrace-error_simulation.tar.xz
latrace-error_simulation.zip
-rw-r--r--src/audit-error.c116
-rw-r--r--src/audit-init.c2
-rw-r--r--src/audit.c2
-rw-r--r--src/config.h1
-rw-r--r--src/error.c32
-rw-r--r--src/error.h2
-rw-r--r--src/run.c2
7 files changed, 138 insertions, 19 deletions
diff --git a/src/audit-error.c b/src/audit-error.c
index 2ece447..b1b0cd9 100644
--- a/src/audit-error.c
+++ b/src/audit-error.c
@@ -19,6 +19,9 @@ extern FILE *lt_audit_in;
static struct hsearch_data symbol_tab;
static int symbol_tab_init = 0;
+static int automated_symbols_find(struct lt_config_audit *cfg,
+ const char *name);
+
struct lt_error_sym* lt_error_sym_get(struct lt_config_shared *cfg,
const char *name)
{
@@ -118,6 +121,7 @@ static int install_sigsegv(struct lt_config_shared *cfg)
static __thread unsigned long automated_sym_cnt = 0;
int lt_error_sym_exit(struct lt_config_audit *cfg,
+ const char *symname,
struct lt_symbol *sym,
struct timeval *tv,
struct link_map *lr,
@@ -128,34 +132,41 @@ int lt_error_sym_exit(struct lt_config_audit *cfg,
struct lt_error_sym *esym;
struct lt_error_config *cfg_err = cfg->error_config;
int keep = 0;
+ int handle_sigsegv;
long ret;
- /* we're not interested in this symbol */
- if (!sym || !sym->error)
- return -1;
-
- esym = sym->error;
-
- PRINT_VERBOSE(cfg, 1, "symbol %s, call %lu, n %ld\n",
- sym->name, esym->call, cfg_err->n);
-
if (cfg_err->automated) {
struct lt_error_config_sym *cfg_sym;
+ if (!automated_symbols_find(cfg, symname))
+ return 0;
+
if (automated_sym_cnt >= cfg_err->sym_cnt)
return -1;
cfg_sym = &cfg_err->sym[automated_sym_cnt];
ret = cfg_sym->ret;
keep = cfg_sym->keep;
+ handle_sigsegv = cfg_sym->handle_sigsegv;
*info = automated_sym_cnt++;
} else {
+
+ /* we're not interested in this symbol */
+ if (!sym || !sym->error)
+ return -1;
+
+ esym = sym->error;
+
+ PRINT_VERBOSE(cfg, 1, "symbol %s, call %lu, n %ld\n",
+ sym->name, esym->call, cfg_err->n);
+
/* we are not interested in this call number */
if (esym->call++ != cfg_err->n)
return -1;
ret = esym->ret;
+ handle_sigsegv = esym->handle_sigsegv;
}
if (keep)
@@ -173,7 +184,7 @@ int lt_error_sym_exit(struct lt_config_audit *cfg,
/* and share some info about the sinner */
share_info(cfg, ret, keep, tv, lr, inregs);
- if (esym->handle_sigsegv && install_sigsegv(cfg->sh))
+ if (handle_sigsegv && install_sigsegv(cfg->sh))
PRINT_VERBOSE(cfg, 1, "failed to install SIGSEGV handler\n");
return 0;
@@ -241,6 +252,9 @@ int lt_error_init(struct lt_config_audit *cfg)
struct lt_error_config *cfg_err = cfg->error_config;
int sym_cnt = cfg_err->sym_cnt, i, ok = 1;
+ if (cfg_err->automated)
+ return 0;
+
lt_sh(cfg, error_sim) = 0;
for(i = 0; i < sym_cnt; i++) {
@@ -264,21 +278,89 @@ int lt_error_init(struct lt_config_audit *cfg)
return 0;
}
+static struct hsearch_data automated_symbol_tab;
+
+static int automated_symbols_find(struct lt_config_audit *cfg,
+ const char *name)
+{
+ ENTRY e, *ep;
+ int found;
+
+ e.key = (char*) name;
+ found = hsearch_r(e, FIND, &ep, &automated_symbol_tab);
+
+ PRINT_VERBOSE(cfg, 1, "found %d, name %s\n", found, name);
+
+ return found;
+}
+
+static int automated_symbols_init(struct lt_config_audit *cfg,
+ struct lt_error_config *cfg_err,
+ int fd)
+{
+ char *symbols, *name;
+ off_t off = lseek(fd, 0, SEEK_CUR);
+ off_t file_size = lseek(fd, 0, SEEK_END);
+ int size = (int) (file_size - off);
+
+ PRINT_VERBOSE(cfg, 1, "size %d\n", size);
+
+ symbols = malloc(size);
+ if (!symbols) {
+ perror("malloc failed");
+ return -1;
+ }
+
+ lseek(fd, off, SEEK_SET);
+ if (size != read(fd, symbols, size)) {
+ perror("read failed");
+ return -1;
+ }
+
+ if (!hcreate_r(SYMBOL_TAB_SIZE, &automated_symbol_tab)) {
+ perror("failed to create hash table");
+ return -1;
+ }
+
+ name = symbols;
+
+ while(1) {
+ ENTRY e, *ep;
+
+ e.key = symbols;
+ e.data = (void*) 1;
+
+ PRINT_VERBOSE(cfg, 1, "name %s\n", name);
+
+ if (!hsearch_r(e, ENTER, &ep, &automated_symbol_tab)) {
+ perror("hsearch_r failed");
+ break;
+ }
+
+ name += strlen(name) + 1;
+ if (name >= (symbols + size))
+ break;
+ }
+
+ PRINT_VERBOSE(cfg, 1, "done\n");
+ return 0;
+}
+
int lt_error_config_read(struct lt_config_audit *cfg, int fd)
{
int size;
struct lt_error_config *cfg_err, cfg_err_st;
+ ssize_t n;
- if (-1 == read(fd, &cfg_err_st, sizeof(cfg_err_st))) {
+ n = read(fd, &cfg_err_st, sizeof(cfg_err_st));
+ if (n != sizeof(cfg_err_st)) {
perror("read failed");
return -1;
}
size = cfg_err_st.sym_cnt * sizeof(struct lt_error_config_sym);
- if (size <= 0) {
- PRINT_VERBOSE(cfg, 1, "failed: no error symbols defined\n");
- return -1;
- }
+
+ PRINT_VERBOSE(cfg, 1, "symbols count %d\n", cfg_err_st.sym_cnt);
cfg_err = malloc(sizeof(*cfg_err) + size);
if (!cfg_err) {
@@ -293,6 +375,10 @@ int lt_error_config_read(struct lt_config_audit *cfg, int fd)
return -1;
}
+ if (cfg_err->automated &&
+ automated_symbols_init(cfg, cfg_err, fd))
+ return -1;
+
cfg->error_config = cfg_err;
return size + sizeof(cfg_err_st);
diff --git a/src/audit-init.c b/src/audit-init.c
index 0324508..b0fdea3 100644
--- a/src/audit-init.c
+++ b/src/audit-init.c
@@ -101,10 +101,12 @@ static int read_config(char *dir)
return -1;
}
+#if 0
if ((len - extra_size) != sizeof(cfg.sh_storage)) {
printf("config file size differs\n");
return -1;
}
+#endif
if (LT_CONFIG_MAGIC != cfg.sh_storage.magic) {
printf("config file magic check failed\n");
diff --git a/src/audit.c b/src/audit.c
index 4488d24..337dd74 100644
--- a/src/audit.c
+++ b/src/audit.c
@@ -156,7 +156,7 @@ static int sym_exit(const char *symname, void *ptr,
#ifdef CONFIG_ARCH_HAVE_ERROR_SIM
if (lt_sh(&cfg, error_sim))
- lt_error_sym_exit(&cfg, sym, &tv, lr, inregs, outregs, &info);
+ lt_error_sym_exit(&cfg, symname, sym, &tv, lr, inregs, outregs, &info);
#endif
#ifdef CONFIG_ARCH_HAVE_ARGS
diff --git a/src/config.h b/src/config.h
index ab71324..859f444 100644
--- a/src/config.h
+++ b/src/config.h
@@ -455,6 +455,7 @@ int lt_error_init(struct lt_config_audit *cfg);
struct lt_error_sym* lt_error_sym_get(struct lt_config_shared *cfg,
const char *name);
int lt_error_sym_exit(struct lt_config_audit *cfg,
+ const char *symname,
struct lt_symbol *sym,
struct timeval *tv,
struct link_map *lr,
diff --git a/src/error.c b/src/error.c
index ec457be..4a99889 100644
--- a/src/error.c
+++ b/src/error.c
@@ -407,9 +407,9 @@ static int automated_get_all_syms(struct lt_config_app *cfg,
}
lt_list_for_each_entry(ret, &run->head_return, list_run) {
- struct lt_error_app_return_sym *sym;
+ struct lt_error_app_return_sym *sym, *n;
- lt_list_for_each_entry(sym, &ret->head_sym, list) {
+ lt_list_for_each_entry_safe(sym, n, &ret->head_sym, list) {
lt_list_move_tail(&sym->list, sym_all);
count++;
}
@@ -644,6 +644,8 @@ static int process_run_automated(struct lt_config_app *cfg,
return -1;
while(1) {
+ PRINT_VERBOSE(cfg, 1, "round %d\n", n);
+
if (dir_run(cfg, dir, dir_base, run, n))
break;
@@ -671,7 +673,7 @@ static int process_go_automated(struct lt_config_app *cfg, char *dir,
{
struct lt_error_app_run *run;
- if (!automated_get_all_syms(cfg, go) <= 0)
+ if (automated_get_all_syms(cfg, go) <= 0)
return -1;
run = lt_list_first_entry(&go->head_run, struct lt_error_app_run, list_go);
@@ -1044,6 +1046,8 @@ int lt_error_app_init(struct lt_error_app *app)
int lt_error_config_write(struct lt_config_app *cfg, int fd)
{
+ struct lt_list_head *sym_all = &cfg->error_symbols_all;
+ struct lt_error_app_return_sym *sym;
struct lt_error_config *cfg_err = cfg->error_config;
int size = sizeof(struct lt_error_config);
@@ -1051,10 +1055,32 @@ int lt_error_config_write(struct lt_config_app *cfg, int fd)
size += cfg_err->sym_cnt * sizeof(struct lt_error_config_sym);
+ PRINT_VERBOSE(cfg, 1, "sym_cnt %d\n", cfg_err->sym_cnt);
+
if (size != write(fd, cfg_err, size)) {
perror("write failed");
return -1;
}
+ if (!cfg_err->automated)
+ return 0;
+
+ PRINT_VERBOSE(cfg, 1, "writing automated list info\n");
+
+ lt_list_for_each_entry(sym, sym_all, list) {
+ char symbol[LT_MAXNAME];
+ int len;
+
+ len = snprintf(symbol, LT_MAXNAME, "%s", sym->name);
+ if (len != write(fd, symbol, len)) {
+ perror("write failed");
+ return -1;
+ }
+ len = 0;
+ write(fd, &len, 1);
+ }
+
+ PRINT_VERBOSE(cfg, 1, "OK\n");
+
return 0;
}
diff --git a/src/error.h b/src/error.h
index e60ef5b..e22fe0d 100644
--- a/src/error.h
+++ b/src/error.h
@@ -13,6 +13,7 @@ struct lt_error_config_filter {
};
struct lt_error_config_sym {
+/* FIXME put to the end of the structure as symbol[0] */
#define LT_MAXNAME 20
char symbol[LT_MAXNAME];
#define LT_MAXRET 20
@@ -27,6 +28,7 @@ struct lt_error_config {
unsigned long n;
int automated;
int sym_cnt;
+ off_t names_size;
struct lt_error_config_sym sym[0];
};
diff --git a/src/run.c b/src/run.c
index 695b538..494730d 100644
--- a/src/run.c
+++ b/src/run.c
@@ -167,6 +167,8 @@ static int process_fifo(struct lt_config_app *cfg, struct lt_thread *t)
if (-1 == lt_fifo_recv(cfg->sh, t, mbase, LT_FIFO_MSG_MAXLEN))
return -1;
+ PRINT_VERBOSE(cfg, 1, "DEBIL\n");
+
lt_list_for_each_entry(func, &cfg->process_funcs, list) {
int ret;