author | Alberto Bertogli
<albertito@blitiri.com.ar> 2009-06-15 06:08:28 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2009-06-16 15:44:58 UTC |
parent | ff676e1218b57d36c41df81d9b85ec3e89abd613 |
.gitignore | +2 | -0 |
preload/Makefile | +16 | -4 |
preload/run/Makefile | +49 | -0 |
preload/run/run.c | +129 | -0 |
diff --git a/.gitignore b/.gitignore index 39f12b9..fdfed27 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ preload/posix/*.o preload/posix/*.so preload/posix/modules/*.o preload/posix/modules/*.mod.c +preload/run/*.o +preload/run/*.so diff --git a/preload/Makefile b/preload/Makefile index 20698c7..a575d71 100644 --- a/preload/Makefile +++ b/preload/Makefile @@ -1,11 +1,11 @@ default: all -all: posix +all: posix run -install: posix_install +install: posix_install run_install -clean: posix_clean +clean: posix_clean run_clean posix: @@ -17,6 +17,18 @@ posix_clean: posix_install: $(MAKE) -C posix/ install +run: + $(MAKE) -C run/ -.PHONY: default clean install posix posix_clean posix_install +run_clean: + $(MAKE) -C run/ clean + +run_install: + $(MAKE) -C run/ install + + + +.PHONY: default clean install \ + posix posix_clean posix_install \ + run run_clean run_install diff --git a/preload/run/Makefile b/preload/run/Makefile new file mode 100644 index 0000000..7655a86 --- /dev/null +++ b/preload/run/Makefile @@ -0,0 +1,49 @@ + +CFLAGS += -std=c99 -Wall -O3 +ALL_CFLAGS = -D_XOPEN_SOURCE=500 -fPIC -DFIU_ENABLE=1 \ + -I. -I../../libfiu/ -L../../libfiu/ $(CFLAGS) + +ifdef DEBUG +ALL_CFLAGS += -g +endif + +ifdef PROFILE +ALL_CFLAGS += -g -pg -fprofile-arcs -ftest-coverage +endif + +# prefix for installing the binaries +PREFIX=/usr/local + + +OBJS = run.o + + +ifneq ($(V), 1) + NICE_CC = @echo " CC $@"; $(CC) +else + NICE_CC = $(CC) +endif + + +default: all + +all: fiu_run_preload.so + +.c.o: + $(NICE_CC) $(ALL_CFLAGS) -c $< -o $@ + +fiu_run_preload.so: $(OBJS) + $(NICE_CC) $(ALL_CFLAGS) -shared -fPIC $(OBJS) -lfiu -ldl \ + -o fiu_run_preload.so + +install: fiu_run_preload.so + install -d $(PREFIX)/lib + install -m 0755 fiu_run_preload.so $(PREFIX)/lib + +clean: + rm -f $(OBJS) fiu_run_preload.so + rm -f *.bb *.bbg *.da *.gcov *.gcda *.gcno gmon.out + +.PHONY: default install clean + + diff --git a/preload/run/run.c b/preload/run/run.c new file mode 100644 index 0000000..cf0dfa6 --- /dev/null +++ b/preload/run/run.c @@ -0,0 +1,129 @@ + +#include <stdio.h> /* printf() */ +#include <unistd.h> /* execve() */ +#include <string.h> /* strtok(), memset(), strncpy() */ +#include <stdlib.h> /* atoi(), atol() */ +#include <getopt.h> /* getopt() */ + +#include <fiu.h> +#include <fiu-control.h> + +/* Maximum size of parameters to the enable options */ +#define MAX_ENOPT 128 + +enum fp_type { + FP_ALWAYS = 1, + FP_PROB = 2, +}; + +struct enable_option { + char buf[MAX_ENOPT]; + enum fp_type type; + char *name; + int failnum; + unsigned long failinfo; + float probability; +}; + +/* Fills the enopt structure taking the values from the given string, which is + * assumed to be in of the form: + * + * name,probability,failnum,failinfo + * + * All fields are optional, except for the name. On error, enopt->name will be + * set to NULL. Probability is in percent, -1 indicates it should always be + * enabled. */ +static void parse_enable(const char *s, struct enable_option *enopt) +{ + char *tok; + char *state; + + enopt->name = NULL; + enopt->type = FP_ALWAYS; + enopt->failnum = 1; + enopt->failinfo = 0; + enopt->probability = 1; + + memset(enopt->buf, 0, MAX_ENOPT); + strncpy(enopt->buf, s, MAX_ENOPT); + + tok = strtok_r(enopt->buf, ",", &state); + if (tok == NULL) + return; + enopt->name = tok; + + tok = strtok_r(NULL, ",", &state); + if (tok == NULL) + return; + if (atoi(tok) >= 0) { + enopt->type = FP_PROB; + enopt->probability = atof(tok) / 100.0; + } + + tok = strtok_r(NULL, ",", &state); + if (tok == NULL) + return; + enopt->failnum = atoi(tok); + + tok = strtok_r(NULL, ",", &state); + if (tok == NULL) + return; + enopt->failinfo = atol(tok); +} + +/* We set the constructor with priority 300 so it runs after the other + * libfiu preloaders (if they're enabled), which use the 200 range */ +static void __attribute__((constructor(300))) fiu_run_init(void) +{ + int r; + struct enable_option enopt; + char *fiu_enable_env, *fiu_enable_s, *fiu_fifo_env; + char *tok, *state; + + fiu_init(0); + + fiu_fifo_env = getenv("FIU_CTRL_FIFO"); + if (fiu_fifo_env != NULL && *fiu_fifo_env != '\0') + fiu_rc_fifo(fiu_fifo_env); + + fiu_enable_env = getenv("FIU_ENABLE"); + if (fiu_enable_env == NULL) + return; + + /* copy fiu_enable_env to fiu_enable_s so we can strtok() it */ + fiu_enable_s = malloc(strlen(fiu_enable_env) + 1); + strcpy(fiu_enable_s, fiu_enable_env); + + state = NULL; + tok = strtok_r(fiu_enable_s, ":", &state); + while (tok != NULL) { + parse_enable(tok, &enopt); + if (enopt.name == NULL) { + fprintf(stderr, "fiu-run.so: " + "ignoring enable without name"); + tok = strtok_r(NULL, ":", &state); + continue; + } + + if (enopt.type == FP_ALWAYS) { + r = fiu_enable(enopt.name, enopt.failnum, + (void *) enopt.failinfo, 0); + } else { + r = fiu_enable_random(enopt.name, enopt.failnum, + (void *) enopt.failinfo, 0, + enopt.probability); + } + + if (r < 0) { + fprintf(stderr, "fiu-run.so: " + "couldn't enable failure %s\n", + enopt.name); + continue; + } + + tok = strtok_r(NULL, ":", &state); + } + + free(fiu_enable_s); +} +