diff options
Diffstat (limited to 'src/audit-error.c')
-rw-r--r-- | src/audit-error.c | 141 |
1 files changed, 122 insertions, 19 deletions
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); |