summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjolsa@redhat.com <jolsa@redhat.com>2011-11-01 16:37:03 +0100
committerJiri Olsa <Jiri Olsa jolsa@redhat.com>2012-01-11 20:06:34 +0100
commitdaafe68255b0fbae2d7c1d4c696538327037b067 (patch)
tree075bf6f26c4464dbd983e240d5d227a7693d95db
parent363e9f3169f985b1ab2d9b22ffca1f2458581dcd (diff)
downloadlatrace-daafe68255b0fbae2d7c1d4c696538327037b067.tar.gz
latrace-daafe68255b0fbae2d7c1d4c696538327037b067.tar.xz
latrace-daafe68255b0fbae2d7c1d4c696538327037b067.zip
error simulation: automated changes
-rw-r--r--TODO3
-rw-r--r--etc/latrace.d/latrace.conf.in32
-rw-r--r--src/args.c4
-rw-r--r--src/args.h2
-rw-r--r--src/audit-error.c148
-rw-r--r--src/audit-init.c14
-rw-r--r--src/audit.c13
-rw-r--r--src/config-bison.y38
-rw-r--r--src/config-flex.l7
-rw-r--r--src/config.c3
-rw-r--r--src/config.h19
-rw-r--r--src/error.c574
-rw-r--r--src/error.h85
-rw-r--r--src/fifo.c4
-rw-r--r--src/list.h3
-rw-r--r--src/symbol.c6
16 files changed, 686 insertions, 269 deletions
diff --git a/TODO b/TODO
index f29957c..67722f1 100644
--- a/TODO
+++ b/TODO
@@ -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
# -------------------
diff --git a/src/args.c b/src/args.c
index 4fd06f4..8272a7f 100644
--- a/src/args.c
+++ b/src/args.c
@@ -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;
diff --git a/src/args.h b/src/args.h
index 439fb79..0a2b176 100644
--- a/src/args.h
+++ b/src/args.h
@@ -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;
diff --git a/src/fifo.c b/src/fifo.c
index c586fa1..cb6b899 100644
--- a/src/fifo.c
+++ b/src/fifo.c
@@ -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;
diff --git a/src/list.h b/src/list.h
index 027fcdc..a683346 100644
--- a/src/list.h
+++ b/src/list.h
@@ -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;