summaryrefslogtreecommitdiffstats
path: root/src/audit-error.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/audit-error.c')
-rw-r--r--src/audit-error.c141
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);