diff options
author | jolsa@redhat.com <jolsa@redhat.com> | 2011-11-01 16:37:03 +0100 |
---|---|---|
committer | Jiri Olsa <Jiri Olsa jolsa@redhat.com> | 2012-01-11 20:06:34 +0100 |
commit | daafe68255b0fbae2d7c1d4c696538327037b067 (patch) | |
tree | 075bf6f26c4464dbd983e240d5d227a7693d95db | |
parent | 363e9f3169f985b1ab2d9b22ffca1f2458581dcd (diff) | |
download | latrace-daafe68255b0fbae2d7c1d4c696538327037b067.tar.gz latrace-daafe68255b0fbae2d7c1d4c696538327037b067.tar.xz latrace-daafe68255b0fbae2d7c1d4c696538327037b067.zip |
error simulation: automated changes
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | etc/latrace.d/latrace.conf.in | 32 | ||||
-rw-r--r-- | src/args.c | 4 | ||||
-rw-r--r-- | src/args.h | 2 | ||||
-rw-r--r-- | src/audit-error.c | 148 | ||||
-rw-r--r-- | src/audit-init.c | 14 | ||||
-rw-r--r-- | src/audit.c | 13 | ||||
-rw-r--r-- | src/config-bison.y | 38 | ||||
-rw-r--r-- | src/config-flex.l | 7 | ||||
-rw-r--r-- | src/config.c | 3 | ||||
-rw-r--r-- | src/config.h | 19 | ||||
-rw-r--r-- | src/error.c | 574 | ||||
-rw-r--r-- | src/error.h | 85 | ||||
-rw-r--r-- | src/fifo.c | 4 | ||||
-rw-r--r-- | src/list.h | 3 | ||||
-rw-r--r-- | src/symbol.c | 6 |
16 files changed, 686 insertions, 269 deletions
@@ -31,3 +31,6 @@ bugs - check we dont cross all the hardcoded limits - consolidate leveled VERBOSE output - info doc (produce html, pdf... outputs) + +error simulation: + - display if round finished with killed tracee diff --git a/etc/latrace.d/latrace.conf.in b/etc/latrace.d/latrace.conf.in index 4186882..3d9df8e 100644 --- a/etc/latrace.d/latrace.conf.in +++ b/etc/latrace.d/latrace.conf.in @@ -173,7 +173,7 @@ OPTIONS { # } # # RETURN R2 { -# sym1 = -1 +# sym1 = -1 SIGSEGV # sym2 = 0 # sym1 = KEEP # sym1 = -2 @@ -182,12 +182,38 @@ OPTIONS { # } # # RUN run1 { +# TYPE AUTO MAX 100 +# +# START SYM sym4 +# START LIB libc +# START NTH 10 +# # RETURN R1, R2 # ARGS a a a # } # -# GO go1 AUTOMATED run1 -# GO go2 REPLAY run2 +# RUN run2 { +# TYPE SEQ +# +# START SYM sym4 +# START LIB libc +# START NTH 10 +# +# RETURN R1 +# ARGS a a a +# } +# +# RUN run3 { +# TYPE REPLAY +# +# START sym=sym4,lib=libc,n=4 +# +# RETURN R1 +# ARGS a a a +# } +# +# GO run1 +# GO run2 #} # directory structure # ------------------- @@ -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 3824d18..f6286cd 100644 --- a/src/audit-error.c +++ b/src/audit-error.c @@ -19,13 +19,14 @@ 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, +struct lt_error_sym* lt_error_sym_get(struct lt_config_audit *cfg, const char *name) { struct lt_error_sym *sym; ENTRY e, *ep; - BUG_ON(!symbol_tab_init); + if (!symbol_tab_init) + return NULL; PRINT_VERBOSE(cfg, 1, "request for <%s>\n", name); @@ -46,7 +47,7 @@ struct lt_error_sym* lt_error_sym_get(struct lt_config_shared *cfg, extern __thread int pipe_fd; static void share_info(struct lt_config_audit *cfg, - struct lt_error_sym *esym, + long ret, int keep, struct timeval *tv, struct link_map *lr, const La_regs *inregs) @@ -58,8 +59,12 @@ static void share_info(struct lt_config_audit *cfg, lt_error_get_retaddr(cfg, &ret_addr, inregs); ret_addr -= lr->l_addr; - snprintf(text, LT_MAXMSG, "ERROR SIMULATION inserted %ld, ret %p", - esym->ret, ret_addr); + if (keep) + 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]; @@ -111,53 +116,86 @@ static int install_sigsegv(struct lt_config_shared *cfg) return sigaction(SIGSEGV, &act, NULL); } +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, const La_regs *inregs, - La_retval *outregs) + La_retval *outregs, + long *info) { 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; + if (cfg_err->type == LT_ERROR_RUN_TYPE_AUTO) { + struct lt_error_sym *esym; - PRINT_VERBOSE(cfg, 1, "symbol %s, call %lu, n %ld\n", - sym->name, esym->call, cfg_err->n); + PRINT_VERBOSE(cfg, 1, "automated_sym_cnt %d, cfg_err->sym_cnt %d\n", + automated_sym_cnt, cfg_err->sym_cnt); - /* we are not interested in this call number */ - if (esym->call++ != cfg_err->n) - return -1; + if (automated_sym_cnt >= cfg_err->sym_cnt) + return -1; + + esym = &cfg_err->sym[automated_sym_cnt]; + ret = esym->ret; + keep = esym->keep; + handle_sigsegv = esym->handle_sigsegv; + + *info = automated_sym_cnt++; + } else { + + esym = sym->error; + + PRINT_VERBOSE(cfg, 1, "symbol %s, call %lu, n %ld\n", + sym->name, esym->call_configured, cfg_err->n); - PRINT_VERBOSE(cfg, 1, "changing retval to %lu\n", - esym->ret); + /* we are not interested in this call number */ + if (esym->call_current++ != esym->call_configured) + return -1; + + ret = esym->ret; + handle_sigsegv = esym->handle_sigsegv; + } + + if (keep) + PRINT_VERBOSE(cfg, 1, "keeping the return value\n", + ret); + else + PRINT_VERBOSE(cfg, 1, "changing retval to %lu\n", + ret); /* The fun begins right now.. let's change the return * value for the symbol ... */ - lt_error_set_retval(cfg, esym->ret, outregs); + if (!keep) + lt_error_set_retval(cfg, ret, outregs); /* and share some info about the sinner */ - share_info(cfg, esym, tv, lr, inregs); + 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; } static int symbol_add(struct lt_config_audit *cfg, - struct lt_error_config_sym *cfg_sym) + struct lt_error_config *cfg_err, + struct lt_error_sym *sym) { ENTRY e, *ep; - struct lt_error_sym *sym; PRINT_VERBOSE(cfg, 1, "symbol %s, ret %ld\n", - cfg_sym->symbol, cfg_sym->ret); + sym->name.symbol, sym->ret); /* should be safe, since only one thread * is doing the initialization */ @@ -170,17 +208,16 @@ static int symbol_add(struct lt_config_audit *cfg, PRINT_VERBOSE(cfg, 1, "symbol table initialized\n"); } - sym = malloc(sizeof(*sym)); - if (!sym) { - PRINT_VERBOSE(cfg, 1, "failed to allocate error symbol\n"); - return -1; + e.key = sym->name.symbol; + if (hsearch_r(e, FIND, &ep, &symbol_tab)) { + PRINT_VERBOSE(cfg, 1, "symbol %s already in the table\n", + sym->name.symbol); + /* This is a bug in normal processing, + * but completelly ok in automated mode. */ + return cfg_err->type == LT_ERROR_RUN_TYPE_AUTO? 0 : -1; } - sym->name = strdup(cfg_sym->symbol); - sym->ret = cfg_sym->ret; - sym->handle_sigsegv = cfg_sym->handle_sigsegv; - - e.key = sym->name; + e.key = sym->name.symbol; e.data = sym; if (!hsearch_r(e, ENTER, &ep, &symbol_tab)) { @@ -197,19 +234,47 @@ static int symbol_add(struct lt_config_audit *cfg, return 0; } +static void display_error_symbols(struct lt_config_audit *cfg, + char *names, int size) +{ + char *p; + + PRINT_VERBOSE(cfg, 1, "START size %d\n", size); + + while(size) { + PRINT_VERBOSE(cfg, 1, "name %s\n", names); + p = memchr(names, 0, size); + size -= ++p - names; + names = p; + } + + PRINT_VERBOSE(cfg, 1, "END\n"); +} + 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; + char *names; lt_sh(cfg, error_sim) = 0; + names = (char*) (((void*) &cfg_err->sym) + + (sym_cnt * sizeof(struct lt_error_sym))); + + display_error_symbols(cfg, names, cfg_err->names_size); + for(i = 0; i < sym_cnt; i++) { - struct lt_error_config_sym *cfg_sym; + struct lt_error_sym *sym; - cfg_sym = &cfg_err->sym[i]; + sym = &cfg_err->sym[i]; - if (symbol_add(cfg, cfg_sym)) { + PRINT_VERBOSE(cfg, 1, "symbol index %d, name %s\n", + sym->name.index, names + sym->name.index); + + sym->name.symbol = names + sym->name.index; + + if (symbol_add(cfg, cfg_err, sym)) { ok = 0; break; } @@ -229,17 +294,19 @@ 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; - } + size = cfg_err_st.sym_cnt * sizeof(struct lt_error_sym); + size += cfg_err_st.names_size; + + PRINT_VERBOSE(cfg, 1, "symbols count %d, names_size %d, total size %d\n", + cfg_err_st.sym_cnt, cfg_err_st.names_size, size); cfg_err = malloc(sizeof(*cfg_err) + size); if (!cfg_err) { @@ -249,12 +316,11 @@ int lt_error_config_read(struct lt_config_audit *cfg, int fd) *cfg_err = cfg_err_st; - if (size != read(fd, cfg_err->sym, size)) { + if (size != read(fd, &cfg_err->sym, size)) { PRINT_VERBOSE(cfg, 1, "failed: no error symbols defined\n"); return -1; } cfg->error_config = cfg_err; - - return size + sizeof(cfg_err_st); + return 0; } diff --git a/src/audit-init.c b/src/audit-init.c index 0324508..73a5208 100644 --- a/src/audit-init.c +++ b/src/audit-init.c @@ -70,7 +70,6 @@ static int init_ctl_config(char *file) static int read_config(char *dir) { int fd; - off_t len, extra_size = 0; char file[LT_MAXFILE]; memset(&cfg, 0, sizeof(cfg)); @@ -91,21 +90,10 @@ static int read_config(char *dir) cfg.sh = cfg.sh_storage.sh = &cfg.sh_storage; if (lt_sh(&cfg, error_sim)) { - extra_size = lt_error_config_read(&cfg, fd); - if (extra_size < 0) + if (lt_error_config_read(&cfg, fd)) return -1; } - if (-1 == (len = lseek(fd, 0, SEEK_END))) { - perror("lseek failed"); - return -1; - } - - if ((len - extra_size) != sizeof(cfg.sh_storage)) { - printf("config file size differs\n"); - return -1; - } - if (LT_CONFIG_MAGIC != cfg.sh_storage.magic) { printf("config file magic check failed\n"); return -1; diff --git a/src/audit.c b/src/audit.c index 7a83b56..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) ? @@ -114,7 +114,7 @@ static int sym_entry(const char *symname, void *ptr, pipe_fd = lt_fifo_create(cfg.sh, cfg.dir); len = lt_fifo_msym_get(cfg.sh, buf, LT_FIFO_MTYPE_ENTRY, &tv, - (char*) symname, lib_to, argbuf, argdbuf); + (char*) symname, lib_to, argbuf, argdbuf, 0); free_argbuf(argret, argbuf, argdbuf); return lt_fifo_send(cfg.sh, pipe_fd, buf, len); @@ -141,6 +141,7 @@ static int sym_exit(const char *symname, void *ptr, char *argbuf = "", *argdbuf = ""; struct timeval tv; struct lt_symbol *sym = NULL; + long info = -1; PRINT_VERBOSE(&cfg, 2, "%s@%s\n", symname, lib_to); @@ -151,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); + lt_error_sym_exit(&cfg, symname, sym, &tv, lr, inregs, outregs, &info); #endif #ifdef CONFIG_ARCH_HAVE_ARGS @@ -169,7 +170,7 @@ static int sym_exit(const char *symname, void *ptr, int len; len = lt_fifo_msym_get(cfg.sh, buf, LT_FIFO_MTYPE_EXIT, &tv, - (char*) symname, lib_to, argbuf, argdbuf); + (char*) symname, lib_to, argbuf, argdbuf, info); free_argbuf(argret, argbuf, argdbuf); return lt_fifo_send(cfg.sh, pipe_fd, buf, len); @@ -276,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-bison.y b/src/config-bison.y index db1d6bc..9d22b0b 100644 --- a/src/config-bison.y +++ b/src/config-bison.y @@ -74,7 +74,8 @@ static struct lt_list_head ln_names; %token ERROR %token ERR_DO ERR_DIR ERR_RUN ERR_GO ERR_RETURN ERR_N %token ERR_PROG ERR_ARGS ERR_FILTER ERR_SEQ ERR_START -%token ERR_SIGSEGV ERR_AUTOMATED ERR_REPLAY ERR_KEEP +%token ERR_SIGSEGV ERR_AUTO ERR_REPLAY ERR_KEEP +%token ERR_TYPE %union { @@ -393,40 +394,35 @@ error_run_def ERR_RETURN list_names_comma ABORT("failed to add run"); } | - -error_go: -ERR_GO NAME list_names_comma +error_run_def ERR_START ERR_N '=' VALUE { - if (lt_error_go(scfg, &error_app_go, &error_app, - strdup($2), 0, 1, 0, 0, &ln_names)) - ABORT("failed to add go"); + error_app_run->start.n = $5; } | -ERR_GO NAME ERR_AUTOMATED list_names_comma +error_run_def ERR_TYPE ERR_SEQ { - if (lt_error_go(scfg, &error_app_go, &error_app, - strdup($2), 0, 1, 1, 0, &ln_names)) - ABORT("failed to add go"); + if (lt_error_run_type(scfg, &error_app_run, LT_ERROR_RUN_TYPE_SEQ)) + ABORT("failed to add run"); } | -ERR_GO NAME ERR_REPLAY list_names_comma +error_run_def ERR_TYPE ERR_AUTO { - if (lt_error_go(scfg, &error_app_go, &error_app, - strdup($2), 0, 1, 1, 1, &ln_names)) - ABORT("failed to add go"); + if (lt_error_run_type(scfg, &error_app_run, LT_ERROR_RUN_TYPE_AUTO)) + ABORT("failed to add run"); } | -ERR_GO NAME ERR_N '=' VALUE list_names_comma +error_run_def ERR_TYPE ERR_REPLAY { - if (lt_error_go(scfg, &error_app_go, &error_app, - strdup($2), 0, $5, 0, 0, &ln_names)) - ABORT("failed to add go"); + if (lt_error_run_type(scfg, &error_app_run, LT_ERROR_RUN_TYPE_REPLAY)) + ABORT("failed to add run"); } | -ERR_GO NAME ERR_START '=' VALUE ERR_N '=' VALUE list_names_comma + +error_go: +ERR_GO NAME list_names_comma { if (lt_error_go(scfg, &error_app_go, &error_app, - strdup($2), $5, $8, 0, 0, &ln_names)) + strdup($2), &ln_names)) ABORT("failed to add go"); } diff --git a/src/config-flex.l b/src/config-flex.l index 03d7a1b..9204375 100644 --- a/src/config-flex.l +++ b/src/config-flex.l @@ -126,12 +126,11 @@ ERROR { BEGIN(error); return ERROR; } <error>PROG { return ERR_PROG; } <error>ARGS { return ERR_ARGS; } <error>N { return ERR_N; } -<error>START { return ERR_START; } -<error>FILTER { return ERR_FILTER; } +<error>TYPE { return ERR_TYPE; } <error>SEQ { return ERR_SEQ; } -<error>SIGSEGV { return ERR_SIGSEGV; } -<error>AUTOMATED { return ERR_AUTOMATED; } +<error>AUTO { return ERR_AUTO; } <error>REPLAY { return ERR_REPLAY; } +<error>SIGSEGV { return ERR_SIGSEGV; } <error>KEEP { return ERR_KEEP; } <error>{value} { RETURN_LONG(VALUE); } diff --git a/src/config.c b/src/config.c index 9bde8a4..6bffc93 100644 --- a/src/config.c +++ b/src/config.c @@ -144,6 +144,7 @@ static int read_config(struct lt_config_app *cfg, char *file) ret = -1; } + PRINT_VERBOSE(cfg, 1, "passed\n"); return ret; } @@ -478,9 +479,11 @@ int lt_config(struct lt_config_app *cfg, int argc, char **argv) cfg->output_tty_fd = -1; lt_init_list_head(&cfg->error_apps); +#ifdef CONFIG_ARCH_HAVE_ERROR_SIM lt_init_list_head(&cfg->process_funcs); lt_init_list_head(&cfg->error_symbols_all); lt_init_list_head(&cfg->error_symbols_current); +#endif /* read the default config file first */ if (read_config(cfg, LT_CONF_DIR "/latrace.conf")) { diff --git a/src/config.h b/src/config.h index 5e44935..28215f1 100644 --- a/src/config.h +++ b/src/config.h @@ -197,9 +197,15 @@ struct lt_config_app { /* error definition (error_sim = 1 in shared config) */ struct lt_error_config *error_config; + char *error_symbols; + int error_symbols_size_names; + int error_symbols_size_total; struct lt_list_head error_symbols_all; struct lt_list_head error_symbols_current; + int error_symbols_all_cnt; + int error_finished; + int error_automated_symbol_index; }; struct lt_config_ctl { @@ -300,6 +306,7 @@ struct lt_fifo_mbase { struct lt_fifo_msym { struct lt_fifo_mbase h; + long info; int sym; int lib; int arg; @@ -385,7 +392,7 @@ int lt_fifo_recv(struct lt_config_shared *cfg, struct lt_thread *t, void *buf, int bufsize); int lt_fifo_msym_get(struct lt_config_shared *cfg, char *buf, int type, struct timeval *tv, char *symname, char *libto, - char *arg, char *argd); + char *arg, char *argd, long info); int lt_fifo_mtext_get(struct lt_config_shared *cfg, char *buf, struct timeval *tv, char *text); @@ -422,9 +429,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 */ @@ -453,14 +460,16 @@ 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, const La_regs *inregs, - La_retval *outregs); + La_retval *outregs, + long *info); int lt_error_set_retval(struct lt_config_audit *cfg, unsigned long ret, La_retval *outregs); void lt_error_get_retaddr(struct lt_config_audit *cfg, 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; } diff --git a/src/error.h b/src/error.h index d22ba4f..97a16dd 100644 --- a/src/error.h +++ b/src/error.h @@ -12,38 +12,38 @@ struct lt_error_config_filter { int type; }; -struct lt_error_config_sym { -#define LT_MAXNAME 20 - char symbol[LT_MAXNAME]; +struct lt_error_sym { + /* + * It is 'symbol' for normal usage and 'index' for + * file storage in names section (see struct + * lt_error_config definition + */ + union { + char *symbol; + int index; + } name; #define LT_MAXRET 20 long ret; - struct lt_error_config_filter filter; + long call_current; + long call_configured; int handle_sigsegv; int keep; }; +/* + * stored in file like: + * + * struct lt_error_config + * struct lt_error_config_sym array + * names.. + */ struct lt_error_config { unsigned long n; - int sym_cnt; - struct lt_error_config_sym sym[0]; -}; - -struct lt_error_audit_filter { int type; - union { - int **nth; - }; -}; - -struct lt_error_sym { - char *name; - unsigned long ret; - unsigned long call; - int handle_sigsegv; - struct lt_error_audit_filter filter; - - struct lt_list_head list; + int sym_cnt; + int names_size; + struct lt_error_sym sym[0]; }; struct lt_error_app_return_sym { @@ -55,6 +55,9 @@ struct lt_error_app_return_sym { long vals[LT_MAX_SYM_RETURNS]; }; + int val_idx; + int val_cnt; + /* When the symbol return is changed, * set SIGSEGV handlers. */ int handle_sigsegv; @@ -77,22 +80,28 @@ struct lt_error_app_return { struct lt_list_head list_run; }; +struct lt_error_start { + long n; +}; + +enum { + LT_ERROR_RUN_TYPE_SEQ, + LT_ERROR_RUN_TYPE_AUTO, + LT_ERROR_RUN_TYPE_REPLAY, +}; + struct lt_error_app_run { char *name; char **args; - + int type; + struct lt_error_start start; struct lt_list_head head_return; struct lt_list_head list_go; struct lt_list_head list_app; }; struct lt_error_app_go { - int n; - int start; - int automated; - int replay; char *name; - struct lt_list_head head_run; struct lt_list_head list; }; @@ -118,9 +127,7 @@ int lt_error_app(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); int lt_error_run_return(struct lt_config_app *cfg, struct lt_error_app_run **run, struct lt_error_app *error_app, @@ -128,6 +135,9 @@ int lt_error_run_return(struct lt_config_app *cfg, int lt_error_run_args(struct lt_config_app *cfg, struct lt_error_app_run **run, struct lt_list_head *args); +int lt_error_run_type(struct lt_config_app *cfg, + struct lt_error_app_run **run, + int type); int lt_error_return_ass(struct lt_config_app *cfg, struct lt_error_app_return **ret, char *name, struct lt_list_head *list_vals, @@ -145,12 +155,10 @@ static inline int lt_error_app(struct lt_config_app *cfg, return -1; } -static inline int lt_error_go(struct lt_config_app *cfg, +static 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) { return -1; } @@ -170,6 +178,13 @@ static inline int lt_error_run_args(struct lt_config_app *cfg, return -1; } +static inline int lt_error_run_type(struct lt_config_app *cfg, + struct lt_error_app_run **run, + int type); +{ + return -1; +} + static inline int lt_error_app_init(struct lt_error_app *app) { return -1; @@ -181,7 +181,7 @@ int lt_fifo_recv(struct lt_config_shared *cfg, struct lt_thread *t, void *buf, int lt_fifo_msym_get(struct lt_config_shared *cfg, char *buf, int type, struct timeval *tv, char *symname, char *libto, - char *arg, char *argd) + char *arg, char *argd, long info) { struct lt_fifo_msym *m = (struct lt_fifo_msym*) buf; int len_data, len = sizeof(struct lt_fifo_msym); @@ -191,6 +191,8 @@ int lt_fifo_msym_get(struct lt_config_shared *cfg, char *buf, int type, m->h.tid = (pid_t) syscall(SYS_gettid); m->h.tv = *tv; + m->info = info; + m->sym = 0; m->lib = strlen(symname); m->arg = m->lib + strlen(libto) + 1; @@ -93,6 +93,9 @@ static inline int lt_list_empty(struct lt_list_head *head) #define lt_list_first_entry(head, type, member) \ lt_list_entry((head)->next, type, member) +#define lt_list_last_entry(head, type, member) \ + lt_list_entry((head)->prev, type, member) + #define lt_list_for_each_entry(pos, head, member) \ for (pos = lt_list_entry((head)->next, typeof(*pos), member); \ &(pos)->member != (head); \ 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; |