diff options
author | jolsa@redhat.com <jolsa@redhat.com> | 2011-11-11 19:42:52 -0500 |
---|---|---|
committer | Jiri Olsa <Jiri Olsa jolsa@redhat.com> | 2011-11-13 11:06:42 +0100 |
commit | 291cd946a26bfd3a6edf1a232e1a2bf7888ddf42 (patch) | |
tree | 5e1243a9ca2bf8328e6b5627ca7821df5599f402 /src/audit-error.c | |
parent | 78a2fe366cf23632dd561e34d849e7fceaefd017 (diff) | |
download | latrace-error_simulation.tar.gz latrace-error_simulation.tar.xz latrace-error_simulation.zip |
changeserror_simulation
Diffstat (limited to 'src/audit-error.c')
-rw-r--r-- | src/audit-error.c | 116 |
1 files changed, 101 insertions, 15 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); |