diff options
author | Jiri Olsa <Jiri Olsa jolsa@redhat.com> | 2011-11-13 15:15:32 +0100 |
---|---|---|
committer | Jiri Olsa <Jiri Olsa jolsa@redhat.com> | 2011-11-13 15:49:02 +0100 |
commit | 09458f02f84fda018378952eecbb051ee5666d80 (patch) | |
tree | 08584143390dad0192e4ae72d2df5836fbe8be8e | |
parent | b91cee1b80e96d27d97a2700212f56996a28545f (diff) | |
download | latrace-09458f02f84fda018378952eecbb051ee5666d80.tar.gz latrace-09458f02f84fda018378952eecbb051ee5666d80.tar.xz latrace-09458f02f84fda018378952eecbb051ee5666d80.zip |
changes
-rw-r--r-- | TODO | 5 | ||||
-rw-r--r-- | src/args.c | 4 | ||||
-rw-r--r-- | src/args.h | 2 | ||||
-rw-r--r-- | src/audit-error.c | 141 | ||||
-rw-r--r-- | src/audit-init.c | 2 | ||||
-rw-r--r-- | src/audit.c | 8 | ||||
-rw-r--r-- | src/config.h | 7 | ||||
-rw-r--r-- | src/error.c | 54 | ||||
-rw-r--r-- | src/error.h | 2 | ||||
-rw-r--r-- | src/symbol.c | 6 |
10 files changed, 189 insertions, 42 deletions
@@ -31,3 +31,8 @@ bugs - check we dont cross all the hardcoded limits - consolidate leveled VERBOSE output - info doc (produce html, pdf... outputs) + +error simulation: + - config extra size read/write + - put automated into separate files + - consolidate patches @@ -981,7 +981,7 @@ static int getargs(struct lt_config_shared *cfg, struct lt_args_sym *asym, return lt_stack_process(cfg, asym, regs, &data); } -struct lt_args_sym* lt_args_sym_get(struct lt_config_shared *cfg, +struct lt_args_sym* lt_args_sym_get(struct lt_config_audit *cfg, const char *sym) { struct lt_args_sym *a; @@ -990,7 +990,7 @@ struct lt_args_sym* lt_args_sym_get(struct lt_config_shared *cfg, PRINT_VERBOSE(cfg, 1, "request for <%s>\n", sym); e.key = (char*) sym; - hsearch_r(e, FIND, &ep, &cfg->args_tab); + hsearch_r(e, FIND, &ep, &cfg->sh->args_tab); if (!ep) return NULL; @@ -120,7 +120,7 @@ struct lt_args_data { /* arguments */ int lt_args_init(struct lt_config_shared *cfg); -struct lt_args_sym* lt_args_sym_get(struct lt_config_shared *cfg, +struct lt_args_sym* lt_args_sym_get(struct lt_config_audit *cfg, const char *sym); int lt_args_sym_entry(struct lt_config_shared *cfg, struct lt_symbol *sym, La_regs *regs, char **argbuf, char **argdbuf); diff --git a/src/audit-error.c b/src/audit-error.c index 2ece447..c93c75c 100644 --- a/src/audit-error.c +++ b/src/audit-error.c @@ -19,12 +19,22 @@ extern FILE *lt_audit_in; static struct hsearch_data symbol_tab; static int symbol_tab_init = 0; -struct lt_error_sym* lt_error_sym_get(struct lt_config_shared *cfg, +static int automated_symbols_find(struct lt_config_audit *cfg, + const char *name); + +static struct lt_error_sym* +automated_sym_get(struct lt_config_audit *cfg, const char *name); + +struct lt_error_sym* lt_error_sym_get(struct lt_config_audit *cfg, const char *name) { + struct lt_error_config *cfg_err = cfg->error_config; struct lt_error_sym *sym; ENTRY e, *ep; + if (cfg_err->automated) + return automated_sym_get(cfg, name); + BUG_ON(!symbol_tab_init); PRINT_VERBOSE(cfg, 1, "request for <%s>\n", name); @@ -59,11 +69,11 @@ static void share_info(struct lt_config_audit *cfg, ret_addr -= lr->l_addr; if (keep) - snprintf(text, LT_MAXMSG, "ERROR SIMULATION inserted %ld, ret %p", - ret, ret_addr); - else snprintf(text, LT_MAXMSG, "ERROR SIMULATION no change, ret %p", ret_addr); + else + snprintf(text, LT_MAXMSG, "ERROR SIMULATION inserted %ld, ret %p", + ret, ret_addr); if (lt_sh(cfg, pipe)) { char buf[LT_FIFO_MSG_MAXLEN]; @@ -118,6 +128,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 +139,44 @@ 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; + + PRINT_VERBOSE(cfg, 1, "automated_sym_cnt %d, cfg_err->sym_cnt %d\n", + automated_sym_cnt, cfg_err->sym_cnt); + 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 +194,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 +262,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 +288,96 @@ 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 struct lt_error_sym* +automated_sym_get(struct lt_config_audit *cfg, + const char *name) +{ + return NULL; +} + +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 = name; + 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 +392,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..31465d4 100644 --- a/src/audit.c +++ b/src/audit.c @@ -99,7 +99,7 @@ static int sym_entry(const char *symname, void *ptr, gettimeofday(&tv, NULL); if (lt_sh(&cfg, global_symbols)) - sym = lt_symbol_get(cfg.sh, ptr, symname); + sym = lt_symbol_get(&cfg, ptr, symname); #ifdef CONFIG_ARCH_HAVE_ARGS argret = lt_sh(&cfg, args_enabled) ? @@ -152,11 +152,11 @@ static int sym_exit(const char *symname, void *ptr, gettimeofday(&tv, NULL); if (lt_sh(&cfg, global_symbols)) - sym = lt_symbol_get(cfg.sh, ptr, symname); + sym = lt_symbol_get(&cfg, ptr, symname); #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 @@ -277,7 +277,7 @@ static unsigned int la_symbind(ElfW(Sym) *sym, const char *symname) /* we are interested in this symbol */ if (lt_sh(&cfg, global_symbols) && !(flags & LA_SYMB_NOPLTENTER)) - lt_symbol_bind(cfg.sh, (void*) sym->st_value, symname); + lt_symbol_bind(&cfg, (void*) sym->st_value, symname); return flags; } diff --git a/src/config.h b/src/config.h index 167aa25..fd4a032 100644 --- a/src/config.h +++ b/src/config.h @@ -425,9 +425,9 @@ char* lt_objsearch(struct lt_config_audit *cfg, const char *name, int lt_stack_framesize(struct lt_config_audit *cfg, La_regs *regs); /* symbol */ -struct lt_symbol* lt_symbol_bind(struct lt_config_shared *cfg, +struct lt_symbol* lt_symbol_bind(struct lt_config_audit *cfg, void *ptr, const char *name); -struct lt_symbol* lt_symbol_get(struct lt_config_shared *cfg, +struct lt_symbol* lt_symbol_get(struct lt_config_audit *cfg, void *ptr, const char *name); /* config options */ @@ -456,9 +456,10 @@ int lt_error_run(struct lt_config_app *cfg); /* error simulation lib */ int lt_error_init(struct lt_config_audit *cfg); -struct lt_error_sym* lt_error_sym_get(struct lt_config_shared *cfg, +struct lt_error_sym* lt_error_sym_get(struct lt_config_audit *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..adf5948 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++; } @@ -475,24 +475,33 @@ static int process_run_automated_cb(struct lt_config_app *cfg, char *symname; long index; + PRINT_VERBOSE(cfg, 1, "type %d\n", mbase->type); + if (mbase->type != LT_FIFO_MTYPE_EXIT) return 0; index = automated_get_index(cfg, mbase); error_config = cfg->error_config; - if (cfg->error_automated_symbol_index < error_config->sym_cnt) { + 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); + + symname = automated_get_symname(cfg, mbase); + PRINT_VERBOSE(cfg, 1, "symname %s\n", symname); + + if (cfg->error_automated_symbol_index < (error_config->sym_cnt - 1)) { if (index != -1) - BUG_ON((cfg->error_automated_symbol_index + 1) != index); cfg->error_automated_symbol_index = index; + return 0; } - symname = automated_get_symname(cfg, mbase); sym = automated_find_symbol_all(cfg, symname); if (!sym) return 0; + PRINT_VERBOSE(cfg, 1, "added %s\n", symname); + if (automated_add_symbol_current(cfg, sym)) return -1; @@ -557,8 +566,6 @@ static int prepare_config_error_automated(struct lt_config_app *cfg, lt_list_for_each_entry(sym, sym_current, list) sym_cnt++; - BUG_ON(sym_cnt); - PRINT_VERBOSE(cfg, 1, "number of symbols %d\n", sym_cnt); cfg_err = malloc(sizeof(*cfg_err) + @@ -580,11 +587,12 @@ static int prepare_config_error_automated(struct lt_config_app *cfg, cfg_sym->keep = sym->keep; cfg_sym->handle_sigsegv = sym->handle_sigsegv; - PRINT_VERBOSE(cfg, 1, "symbol %s, ret %s\n", - sym->name, cfg_sym->ret); + PRINT_VERBOSE(cfg, 1, "symbol %s, keep %d, ret %llu\n", + cfg_sym->symbol, cfg_sym->keep, cfg_sym->ret); } cfg->error_config = cfg_err; + cfg->error_automated_symbol_index = -1; return 0; } @@ -644,6 +652,8 @@ static int process_run_automated(struct lt_config_app *cfg, return -1; while(1) { + printf("round %d\n", n); + if (dir_run(cfg, dir, dir_base, run, n)) break; @@ -671,7 +681,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 +1054,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 +1063,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/symbol.c b/src/symbol.c index 707fbf6..cbbec6e 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -70,7 +70,7 @@ static int compare(const void *a, const void *b) #endif } -static int symbol_init(struct lt_config_shared *cfg, +static int symbol_init(struct lt_config_audit *cfg, struct lt_symbol *sym, const char *name) { struct lt_args_sym *a = NULL; @@ -93,7 +93,7 @@ static int symbol_init(struct lt_config_shared *cfg, return 0; } -struct lt_symbol* lt_symbol_bind(struct lt_config_shared *cfg, +struct lt_symbol* lt_symbol_bind(struct lt_config_audit *cfg, void *ptr, const char *name) { static struct lt_symbol *sym = NULL; @@ -138,7 +138,7 @@ struct lt_symbol* lt_symbol_bind(struct lt_config_shared *cfg, return s; } -struct lt_symbol* lt_symbol_get(struct lt_config_shared *cfg, +struct lt_symbol* lt_symbol_get(struct lt_config_audit *cfg, void *ptr, const char *name) { void *val; |