summaryrefslogtreecommitdiffstats
path: root/src/error.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/error.c')
-rw-r--r--src/error.c574
1 files changed, 440 insertions, 134 deletions
diff --git a/src/error.c b/src/error.c
index 6698ff8..48afa23 100644
--- a/src/error.c
+++ b/src/error.c
@@ -185,11 +185,28 @@ static int dir_go(struct lt_config_app *cfg,
static int dir_run(struct lt_config_app *cfg,
char *dir, char *dir_base,
- struct lt_error_app_run *run, int n)
+ struct lt_error_app_run *run)
{
int size;
- size = snprintf(dir, LT_MAXFILE, "%s/RUN-%s-%05d/", dir_base, run->name, n);
+ size = snprintf(dir, LT_MAXFILE, "%s/RUN-%s/", dir_base, run->name);
+ if (size == LT_MAXFILE)
+ return -1;
+
+ if (dir_get(cfg, dir, 0))
+ return -1;
+
+ return 0;
+}
+
+static int dir_round(struct lt_config_app *cfg,
+ char *dir, char *dir_run,
+ struct lt_error_app_run *run,
+ unsigned long round)
+{
+ int size;
+
+ size = snprintf(dir, LT_MAXFILE, "%s/%lu/", dir_run, round);
if (size == LT_MAXFILE)
return -1;
@@ -277,60 +294,314 @@ static int prepare_config_args(struct lt_config_app *cfg,
return 0;
}
-static int prepare_config_error(struct lt_config_app *cfg,
- struct lt_error_app_run *run,
- int n)
+static int get_symbols_all(struct lt_config_app *cfg,
+ struct lt_error_app_run *run)
{
+ struct lt_list_head *sym_all = &cfg->error_symbols_all;
struct lt_error_app_return *ret;
- struct lt_error_config *cfg_err;
- int sym_cnt = 0;
+ int count = 0;
- /* get the nymber of configured symbols */
lt_list_for_each_entry(ret, &run->head_return, list_run) {
- struct lt_error_app_return_sym *sym;
- lt_list_for_each_entry(sym, &ret->head_sym, list)
- sym_cnt++;
+ struct lt_error_app_return_sym *sym, *n;
+
+ lt_list_for_each_entry_safe(sym, n, &ret->head_sym, list) {
+ lt_list_move_tail(&sym->list, sym_all);
+ count++;
+ }
+ }
+
+ PRINT_VERBOSE(cfg, 1, "got %d symbols\n", count);
+ return count;
+}
+
+long automated_get_index(struct lt_config_app *cfg,
+ struct lt_fifo_mbase *mbase)
+{
+ struct lt_fifo_msym *msym = (struct lt_fifo_msym*) mbase;
+ return msym->info;
+}
+
+static char *automated_get_symname(struct lt_config_app *cfg,
+ struct lt_fifo_mbase *mbase)
+{
+ struct lt_fifo_msym *msym = (struct lt_fifo_msym*) mbase;
+ return msym->data + msym->sym;
+}
+
+static struct lt_error_app_return_sym*
+automated_find_symbol_all(struct lt_config_app *cfg, char *symname)
+{
+ struct lt_error_app_return_sym *sym;
+ struct lt_list_head *sym_all = &cfg->error_symbols_all;
+
+ /* TODO hash, hash, hash... and hash again .. pleaeease ;) hash! */
+ lt_list_for_each_entry(sym, sym_all, list)
+ if (!strcmp(sym->name, symname))
+ return sym;
+
+ return NULL;
+}
+
+static int automated_add_symbol_current(struct lt_config_app *cfg,
+ struct lt_error_app_return_sym *sym_orig)
+{
+ struct lt_error_app_return_sym *sym;
+
+ sym = malloc(sizeof(*sym));
+ if (!sym)
+ return -1;
+
+ *sym = *sym_orig;
+
+ sym->keep = 1;
+ sym->val_idx = 0;
+
+ lt_list_add_tail(&sym->list, &cfg->error_symbols_current);
+ return 0;
+}
+
+static int
+prepare_config_symbols_automated(struct lt_config_app *cfg,
+ struct lt_error_app_run *run,
+ unsigned long round)
+{
+ struct lt_list_head *sym_current = &cfg->error_symbols_current;
+
+ cfg->error_automated_symbol_index = -1;
+
+ if (!round) {
+ int cnt;
+ cnt = get_symbols_all(cfg, run);
+ if (cnt <= 0)
+ return -EINVAL;
+
+ cfg->error_symbols_all_cnt = cnt;
+ return 0;
+ }
+
+ while (!lt_list_empty(sym_current)) {
+ struct lt_error_app_return_sym *last;
+
+ last = lt_list_last_entry(sym_current,
+ struct lt_error_app_return_sym,
+ list);
+
+ PRINT_VERBOSE(cfg, 1, "last %s\n", last->name);
+
+ if (last->keep) {
+ int idx = last->val_idx;
+ last->keep = 0;
+
+ PRINT_VERBOSE(cfg, 1, "from keep to vals[%d] = %llu\n",
+ idx, last->vals[idx]);
+ break;
+ } else {
+ int idx = last->val_idx + 1;
+
+ if (idx < last->val_cnt) {
+ last->val_idx = idx;
+
+ PRINT_VERBOSE(cfg, 1, "from vals[%d] = %llu to vals[%d] = %llu\n",
+ idx - 1, last->vals[idx - 1],
+ idx, last->vals[idx]);
+ break;
+ }
+
+ PRINT_VERBOSE(cfg, 1, "removing\n");
+ lt_list_del(&last->list);
+ }
+ }
+
+ /* nothing more to try, we are done */
+ if (lt_list_empty(sym_current)) {
+ PRINT_VERBOSE(cfg, 1, "FINISHED\n");
+ cfg->error_finished = 1;
+ return 0;
+ }
+
+ return 0;
+}
+
+static int
+prepare_config_symbols_replay(struct lt_config_app *cfg)
+{
+ return 0;
+}
+
+static int
+prepare_config_symbols_seq(struct lt_config_app *cfg,
+ unsigned long round)
+{
+ return 0;
+}
+
+static int prepare_config_symbols(struct lt_config_app *cfg,
+ struct lt_error_app_run *run,
+ unsigned long round)
+{
+ switch(run->type) {
+ case LT_ERROR_RUN_TYPE_SEQ:
+ return prepare_config_symbols_seq(cfg, round);
+
+ case LT_ERROR_RUN_TYPE_AUTO:
+ return prepare_config_symbols_automated(cfg, run, round);
+
+ case LT_ERROR_RUN_TYPE_REPLAY:
+ return prepare_config_symbols_replay(cfg);
+ }
+
+ BUG();
+ return -EINVAL;
+}
+
+static int find_error_symbol(struct lt_config_app *cfg, char *name,
+ int len)
+{
+ char *names = cfg->error_symbols;
+ int size_names = cfg->error_symbols_size_names;
+ char *p;
+
+ PRINT_VERBOSE(cfg, 1, "name %s\n", name);
+
+ while(size_names) {
+ if (!strncmp(names, name, len)) {
+ int idx = names - cfg->error_symbols;
+ PRINT_VERBOSE(cfg, 1, "found idx %d\n", idx);
+ return names - cfg->error_symbols;
+ }
+
+ p = memchr(names, 0, size_names);
+ size_names -= ++p - names;
+ names = p;
+ }
+
+ PRINT_VERBOSE(cfg, 1, "not found\n");
+ return -1;
+}
+
+static void display_error_symbols(struct lt_config_app *cfg)
+{
+ char *names = cfg->error_symbols;
+ int size_names = cfg->error_symbols_size_names;
+ char *p;
+
+ PRINT_VERBOSE(cfg, 1, "START\n");
+
+ while(size_names) {
+ PRINT_VERBOSE(cfg, 1, "name %s\n", names);
+ p = memchr(names, 0, size_names);
+ size_names -= ++p - names;
+ names = p;
+ }
+
+ PRINT_VERBOSE(cfg, 1, "END\n");
+}
+
+static int add_error_symbol(struct lt_config_app *cfg, char *name)
+{
+ char *names = cfg->error_symbols;
+ int len = strlen(name);
+ int size_names = cfg->error_symbols_size_names;
+ int size_total = cfg->error_symbols_size_total;
+ int index;
+
+ PRINT_VERBOSE(cfg, 1, "name %s\n", name);
+ display_error_symbols(cfg);
+
+ if (!names) {
+ names = malloc(1000);
+ if (!names)
+ return -ENOMEM;
+
+ PRINT_VERBOSE(cfg, 1, "initial allocation\n");
+ cfg->error_symbols = names;
+ size_names = cfg->error_symbols_size_names = 0;
+ size_total = cfg->error_symbols_size_total = 1000;
}
+ index = find_error_symbol(cfg, name, len);
+ if (index >= 0)
+ return index;
+
+ /* +1 for ZERO byte */
+ if (len + size_names + 1 >= size_total) {
+ size_total += 1000;
+ names = realloc(names, size_total);
+ if (!names)
+ return -ENOMEM;
+
+ PRINT_VERBOSE(cfg, 1, "reallocation size %d\n", size_total);
+ cfg->error_symbols = names;
+ cfg->error_symbols_size_total = size_total;
+ }
+
+ index = size_names;
+
+ strncpy(names + size_names, name, len);
+ size_names += len;
+ names[size_names++] = 0;
+
+ cfg->error_symbols_size_names = size_names;
+
+ PRINT_VERBOSE(cfg, 1, "added %s, index %d\n", name, index);
+ display_error_symbols(cfg);
+ return index;
+}
+
+static int prepare_config_error(struct lt_config_app *cfg,
+ struct lt_error_app_run *run)
+{
+ struct lt_list_head *sym_current = &cfg->error_symbols_current;
+ struct lt_error_app_return_sym *sym;
+ struct lt_error_config *cfg_err;
+ int sym_cnt = 0;
+
+ lt_list_for_each_entry(sym, sym_current, list)
+ sym_cnt++;
+
PRINT_VERBOSE(cfg, 1, "number of symbols %d\n", sym_cnt);
cfg_err = malloc(sizeof(*cfg_err) +
- sym_cnt * sizeof(struct lt_error_config_sym));
+ sym_cnt * sizeof(struct lt_error_sym));
if (!cfg_err)
return -ENOMEM;
+ memset(cfg_err, 0, sizeof(*cfg_err));
cfg_err->sym_cnt = sym_cnt;
- cfg_err->n = n;
+ cfg_err->type = run->type;
sym_cnt = 0;
- lt_list_for_each_entry(ret, &run->head_return, list_run) {
- struct lt_error_app_return_sym *sym;
+ lt_list_for_each_entry(sym, sym_current, list) {
+ struct lt_error_sym *cfg_sym;
+ int index;
- lt_list_for_each_entry(sym, &ret->head_sym, list) {
- struct lt_error_config_sym *cfg_sym;
+ cfg_sym = &cfg_err->sym[sym_cnt++];
- cfg_sym = &cfg_err->sym[sym_cnt++];
- strncpy(cfg_sym->symbol, sym->name, LT_MAXNAME);
- cfg_sym->ret = sym->val;
- cfg_sym->filter.type = ret->filter.type;
- cfg_sym->handle_sigsegv = sym->handle_sigsegv;
+ index = add_error_symbol(cfg, sym->name);
+ if (index < 0)
+ return -ENOMEM;
- PRINT_VERBOSE(cfg, 1, "symbol %s, ret %s\n",
- sym->name, sym->val);
- }
+ cfg_sym->name.index = index;
+ cfg_sym->ret = sym->vals[sym->val_idx];
+ cfg_sym->keep = sym->keep;
+ cfg_sym->handle_sigsegv = sym->handle_sigsegv;
+
+ PRINT_VERBOSE(cfg, 1, "symbol %s, keep %d, ret %llu\n",
+ sym->name, cfg_sym->keep, cfg_sym->ret);
}
+ cfg_err->names_size = cfg->error_symbols_size_names;
cfg->error_config = cfg_err;
return 0;
}
-static int prepare_config(struct lt_config_app *cfg, char *dir,
+static int prepare_config(struct lt_config_app *cfg,
+ char *dir,
struct lt_error_app *app,
- struct lt_error_app_run *run, int n)
+ struct lt_error_app_run *run,
+ unsigned long round)
{
- PRINT_VERBOSE(cfg, 1, "dir '%s'\n", dir);
-
if (!app->no_storage) {
if (prepare_config_trace(cfg, dir))
return -1;
@@ -345,137 +616,153 @@ static int prepare_config(struct lt_config_app *cfg, char *dir,
if (prepare_config_args(cfg, app, run))
return -1;
- if (prepare_config_error(cfg, run, n))
+ if (prepare_config_symbols(cfg, run, round))
+ return -1;
+
+ if (prepare_config_error(cfg, run))
return -1;
return 0;
}
+static void automated_dump_config(struct lt_config_app *cfg,
+ struct lt_error_app *app,
+ char *dir)
+{
+ /* dump config to be replayed with REPLAY */
+}
+
+static void post_config_automated(struct lt_config_app *cfg,
+ struct lt_error_app *app,
+ char *dir)
+{
+ automated_dump_config(cfg, app, dir);
+}
+
static void post_config(struct lt_config_app *cfg,
- struct lt_error_app *app)
+ struct lt_error_app *app,
+ struct lt_error_app_run *run,
+ char *dir)
{
+ switch(run->type) {
+ case LT_ERROR_RUN_TYPE_AUTO:
+ return post_config_automated(cfg, app, dir);
+ }
+
if (!app->no_storage) {
if ((lt_sh(cfg, pipe)) && (*lt_sh(cfg, output)))
fclose(lt_sh(cfg, fout));
fclose(cfg->fstat);
}
+
+ free(cfg->error_config);
+ free(cfg->error_symbols);
+
+ cfg->error_config = NULL;
+ cfg->error_symbols = NULL;
+ cfg->error_symbols_size_names = 0;
+ cfg->error_symbols_size_total = 0;
}
-static int process_run(struct lt_config_app *cfg,
- char *dir_base,
- struct lt_error_app *app,
- struct lt_error_app_go *go,
- struct lt_error_app_run *run,
- int n)
+static int process_run_automated_cb(struct lt_config_app *cfg,
+ struct lt_thread *t,
+ struct lt_fifo_mbase *mbase)
{
- static char dir[LT_MAXFILE];
+ struct lt_error_app_return_sym *sym;
+ struct lt_error_config *error_config;
+ char *symname;
+ long index;
- if (!app->no_storage &&
- dir_run(cfg, dir, dir_base, run, n))
- return -1;
+ PRINT_VERBOSE(cfg, 1, "type %d\n", mbase->type);
- PRINT_VERBOSE(cfg, 1, "dir '%s'\n", dir);
+ if (mbase->type != LT_FIFO_MTYPE_EXIT)
+ return 0;
- if (prepare_config(cfg, dir, app, run, n))
- return -1;
+ index = automated_get_index(cfg, mbase);
+ error_config = cfg->error_config;
- if (app->no_storage)
- printf("latrace error simulation [%s] n = %d\n", app->name, n);
+ PRINT_VERBOSE(cfg, 1, "index %d, error_automated_symbol_index %d, sym_cnt %d\n",
+ index, cfg->error_automated_symbol_index, error_config->sym_cnt);
- lt_run(cfg);
+ symname = automated_get_symname(cfg, mbase);
+ PRINT_VERBOSE(cfg, 1, "symname %s\n", symname);
- post_config(cfg, app);
+ if (cfg->error_automated_symbol_index < (error_config->sym_cnt - 1)) {
+ if (index != -1)
+ cfg->error_automated_symbol_index = index;
- return 0;
-}
-
-static int process_automated_cb(struct lt_config_app *cfg,
- struct lt_thread *t,
- struct lt_fifo_mbase *mbase)
-{
- return 0;
-}
+ return 0;
+ }
-static int automated_get_all_syms(struct lt_config_app *cfg,
- struct lt_error_app_go *go)
-{
- struct lt_list_head *sym_all = &cfg->error_symbols_all;
- struct lt_error_app_run *run;
- int count = 0;
+ sym = automated_find_symbol_all(cfg, symname);
+ if (!sym)
+ return 0;
- lt_list_for_each_entry(run, &go->head_run, list_go) {
- struct lt_error_app_return *ret;
+ PRINT_VERBOSE(cfg, 1, "added %s\n", symname);
- lt_list_for_each_entry(ret, &run->head_return, list_run) {
- struct lt_error_app_return_sym *sym;
+ if (automated_add_symbol_current(cfg, sym))
+ return -1;
- lt_list_for_each_entry(sym, &ret->head_sym, list) {
- lt_list_move_tail(&sym->list, sym_all);
- count++;
- }
- }
- }
+ return 0;
+}
- return count;
+static int process_run_cb(struct lt_config_app *cfg,
+ struct lt_thread *t,
+ struct lt_fifo_mbase *mbase)
+{
+ /* TODO need a way to distiguish error type inside tracer */
+ return process_run_automated_cb(cfg, t, mbase);
}
-static int process_go_automated(struct lt_config_app *cfg, char *dir,
- struct lt_error_app *app,
- struct lt_error_app_go *go)
+static int process_run(struct lt_config_app *cfg,
+ char *dir_base,
+ struct lt_error_app *app,
+ struct lt_error_app_run *run)
{
- int ret = 0;
+ static char dir[LT_MAXFILE];
+ static char round[LT_MAXFILE];
+ unsigned long r = 0;
- if (lt_process_register(cfg, process_automated_cb))
+ if (!app->no_storage &&
+ dir_run(cfg, dir, dir_base, run))
return -1;
- if (!automated_get_all_syms(cfg, go)) {
- PRINT_VERBOSE(cfg, 1, "no symbols defined\n");
+ PRINT_VERBOSE(cfg, 1, "dir '%s'\n", dir);
+
+ if (lt_process_register(cfg, process_run_cb))
return -1;
- }
- /* TODO
- * 1) first run with no symbols
- * 2) after each run add new symbol to the 'cur' list from global 'all' list
- * 3) 'cur' list has fresh reallocated symbols giving the position and return
- * for each symbol occurence
- * 4) each 'cur' list symbol moves to new return value if all symbols 'below' it
- * has changed all their return values
- * 5) finish when first symbol cycles its all return values
- * 6) repeating till there are new symbols (from 'all' list) visible
- *
- */
+ while(1) {
+ int status;
- BUG_ON(lt_process_unregister(cfg, process_automated_cb));
+ if (!app->no_storage &&
+ dir_round(cfg, round, dir, run, r))
+ return -1;
- return ret;
-}
+ printf(".");
-static int process_go_replay(struct lt_config_app *cfg, char *dir,
- struct lt_error_app *app,
- struct lt_error_app_go *go)
-{
- return 0;
-}
+ if (prepare_config(cfg, round, app, run, r))
+ break;
-static int process_go_configured(struct lt_config_app *cfg, char *dir,
- struct lt_error_app *app,
- struct lt_error_app_go *go)
-{
- int i;
+ if (cfg->error_finished)
+ break;
- PRINT_VERBOSE(cfg, 1, "dir '%s', name %s, start %d, n %d\n",
- dir, go->name, go->start, go->n);
+ status = lt_run(cfg);
+ if (WIFSIGNALED(status))
+ printf("\nround %lu killed by signal %d\n",
+ r, WTERMSIG(status));
+ fflush(NULL);
- for(i = go->start; i < (go->start + go->n); i++) {
- struct lt_error_app_run *run;
+ post_config(cfg, app, run, round);
- lt_list_for_each_entry(run, &go->head_run, list_go)
- if (process_run(cfg, dir, app, go, run, i))
- return -1;
- }
+ r++;
+ };
- return 0;
+ printf("\n");
+ BUG_ON(lt_process_unregister(cfg, process_run_cb));
+
+ return cfg->error_finished ? 0 : -1;
}
static int process_go(struct lt_config_app *cfg, char *dir_base,
@@ -483,21 +770,17 @@ static int process_go(struct lt_config_app *cfg, char *dir_base,
struct lt_error_app_go *go)
{
static char dir[LT_MAXFILE];
+ struct lt_error_app_run *run;
if (!app->no_storage &&
dir_go(cfg, dir, dir_base, go))
return -1;
- /* automated processing.. God save us */
- if (go->automated)
- return process_go_automated(cfg, dir, app, go);
-
- /* exact symbols return replay */
- if (go->replay)
- return process_go_replay(cfg, dir, app, go);
+ lt_list_for_each_entry(run, &go->head_run, list_go)
+ if (process_run(cfg, dir, app, run))
+ return -1;
- /* Whatever user configuration wants.. */
- return process_go_configured(cfg, dir, app, go);
+ return 0;
}
int lt_error_run(struct lt_config_app *cfg)
@@ -608,6 +891,19 @@ int lt_error_run_return(struct lt_config_app *cfg,
return 0;
}
+int lt_error_run_type(struct lt_config_app *cfg,
+ struct lt_error_app_run **run,
+ int type)
+{
+ struct lt_error_app_run *app_run = app_run_get(cfg, run);
+
+ if (!app_run)
+ return -ENOMEM;
+
+ app_run->type = type;
+ return 0;
+};
+
int lt_error_run_args(struct lt_config_app *cfg,
struct lt_error_app_run **run,
struct lt_list_head *head)
@@ -657,9 +953,7 @@ static struct lt_error_app_run *find_run(struct lt_config_app *cfg,
int lt_error_go(struct lt_config_app *cfg,
struct lt_error_app_go **go,
struct lt_error_app *error_app,
- char *name, int start, int n,
- int automated, int replay,
- struct lt_list_head *runs)
+ char *name, struct lt_list_head *runs)
{
struct lt_error_app_go *app_go = *go;
struct lt_config_ln *ln, *h;
@@ -672,11 +966,7 @@ int lt_error_go(struct lt_config_app *cfg,
lt_init_list_head(&app_go->head_run);
lt_init_list_head(&app_go->list);
- app_go->n = n;
- app_go->start = start;
app_go->name = name;
- app_go->automated = automated;
- app_go->replay = replay;
lt_list_for_each_entry_safe(ln, h, runs, list) {
struct lt_error_app_run *run;
@@ -765,6 +1055,8 @@ int lt_error_return_ass(struct lt_config_app *cfg,
free(ln);
}
+ sym->val_cnt = vals_cnt;
+
PRINT_VERBOSE(cfg, 1, "%s = %ld, handle_sigsegv = %d, keep %d\n",
sym->name, sym->val, handle_sigsegv, keep);
@@ -812,16 +1104,30 @@ int lt_error_app_init(struct lt_error_app *app)
int lt_error_config_write(struct lt_config_app *cfg, int fd)
{
struct lt_error_config *cfg_err = cfg->error_config;
- int size = sizeof(struct lt_error_config);
+ int len, size = sizeof(struct lt_error_config);
BUG_ON(!cfg_err);
- size += cfg_err->sym_cnt * sizeof(struct lt_error_config_sym);
+ size += cfg_err->sym_cnt * sizeof(struct lt_error_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;
}
+ PRINT_VERBOSE(cfg, 1, "writing names size %d\n", cfg->error_symbols_size_names);
+ display_error_symbols(cfg);
+
+ len = cfg->error_symbols_size_names;
+ size = write(fd, cfg->error_symbols, len);
+
+ if (size != len) {
+ perror("write failed");
+ return -1;
+ }
+
+ PRINT_VERBOSE(cfg, 1, "OK\n");
return 0;
}