diff --git a/LLVM_Instruction.md b/LLVM_Instruction.md new file mode 100644 index 0000000..e2fcaf7 --- /dev/null +++ b/LLVM_Instruction.md @@ -0,0 +1,9 @@ +You can obtain the Sources or the Pre-Built Binaries of LLVM and Clang from [here](http://llvm.org/releases/download.html). + +Installing LLVM and Clang from Pre-Built Binaries saves your time and trouble of directly compiling the Sources by yourself. You can follow the instruction [here](http://stackoverflow.com/questions/17045954/how-to-install-clang-using-precompiled-binaries) and [here](http://askubuntu.com/questions/89615/how-do-i-install-llvm-clang-3-0) to learn more about how to install the binaries. + +You can also install LLVM and Clang from the Sources, please check [here](http://llvm.org/docs/GettingStarted.html#requirements) for the requirements of building LLVM by yourself. If you are using Ubuntu or Debian, it is probably a good idea to install the `build-essential` package before you start, since it contains the required `gcc` and `make` utilities. After all the requirements are met, click [here](http://llvm.org/docs/GettingStarted.html#getting-started-with-llvm) for a very detailed instruction and some options you can configure when installing LLVM. +Please do note the following when you follow the instructions above: +1. The linking process of LLVM is very memory heavy, make sure your machine has enough memory and swap space before you compile LLVM Source Code. Otherwise you risk the chances of getting errors like `ld terminated with signal 9`, `Memory exhausted` or `ld returned exist status 1` which halts and fails the compilation process. Some helpful links on how to increase swap space can be found [here](https://www.maketecheasier.com/swap-partitions-on-linux/), [here](https://blog.inventic.eu/2012/07/linux-c-linker-ld-terminated-with-signal-9/) and [here](http://stackoverflow.com/questions/5682854/why-is-the-linker-terminating-on-me-when-i-build-clang). +2. You can also choose to build LLVM in Release mode instead of Debug mode to reduce the amount of memory required during compilation. See [here](http://llvm.org/docs/GettingStarted.html#local-llvm-configuration) and [here](http://llvm.org/docs/CMake.html#introduction) about how to change local LLVM configuration. +3. Instructions on installing LLVM and Clang without Root Privileges can be found [here](http://stackoverflow.com/questions/8681385/install-clang-as-user-no-root-privileges) and [here](http://llvm.org/docs/GettingStarted.html#local-llvm-configuration). diff --git a/README.md b/README.md index 0c6e9c7..00fe8a4 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ This project is partially supported by the Air Force Office of Scientific Resear # FlipIt Installation -1.) Follow Steps from http://clang.llvm.org/get_started.html to install LLVM and Clang +1.) Obtain a copy of LLVM and clang [here](http://llvm.org/releases/download.html). We have tested with LLVM 3.5.2 source and precompiled binaries. If you choose to build LLVM and clang from source, follow these [directions](http://clang.llvm.org/get_started.html). 2.) Get FlipIt: @@ -32,20 +32,23 @@ This project is partially supported by the Air Force Office of Scientific Resear git clone git@github.com:aperson40/FlipIt.git ``` -3.) Modify your bashrc file to add directory to path and set some environment variables. If you have a *Release+Asserts* build of LLVM, replace *Debug+Asserts* with it in the following: - +3.) Modify your bashrc file to add directory to path and set some environment variables that are used throughout FlipIt ``` - PATH=$PATH:/path/to/build/Debug+Asserts/bin - export PATH - export LLVM_BUILD_PATH=/path/to/build/ - export LLVM_REPO_PATH=/path/to/repo/llvm/ + export LLVM_BUILD_PATH=/path/to/llvm/ export FLIPIT_PATH=/path/to/flipit + + #only required if you want to use FlipIt as a library with other code + export LD_LIBRARY_PATH=/path/to/flipit/lib:$LD_LIBRARY_PATH + + #not required, but can make your fingers happy in you do not use the compiler wrapper + PATH=$PATH:/path/to/llvm/bin + export PATH ``` 4.) Run script to setup FlipIt with LLVM (Note: If you're not using LLVM version 3.4, the LLVM #include files in [faults.h](src/pass/faults.cpp) might not be correct. This is due to changes in the directory structure in LLVM between releases.): ``` -cd $FLIPIT_PATH/ +cd $FLIPIT_PATH ./setup ``` 5.) Test that everything works: diff --git a/src/corrupt/corrupt.c b/src/corrupt/corrupt.c index 04a892f..3c939c1 100644 --- a/src/corrupt/corrupt.c +++ b/src/corrupt/corrupt.c @@ -13,40 +13,50 @@ /* */ /***********************************************************************************************/ -#include "corrupt.h" +#include +#include +#include +#include "corrupt_new.h" +//NOTE: check again to see if all of these values need to 64bits or 32bits ?! /*Inject only once */ -static int FLIPIT_SingleInjection = 0; -static int FLIPIT_State = 0; +static uint32_t FLIPIT_SingleInjection = 0; +static uint32_t FLIPIT_State = 0; /*fault injection count*/ -static int FLIPIT_InjectionCount = 0; -static unsigned long FLIPIT_Attempts = 0; -static unsigned long FLIPIT_InjCountdown = 0; -static unsigned long FLIPIT_TotalInsts = 0; +static uint32_t FLIPIT_InjectionCount = 0; +static uint64_t FLIPIT_Attempts = 0; +static uint64_t FLIPIT_InjCountdown = 0; +static uint64_t FLIPIT_TotalInsts = 0; /*Fault Injection Statistics*/ -static unsigned long* FLIPIT_Histogram; -static int FLIPIT_MAX_LOC = 20000; +static uint64_t * FLIPIT_Histogram; +static uint32_t FLIPIT_MAX_LOC = 20000; + +/***************MODIFIED***************/ +static uint32_t FLIPIT_MAX_INJECT_LINES = 33554432; +static uint32_t FLIPIT_REMAIN_INJECT_COUNT = 1; //NOTE: this value should be initialized! +static uint32_t FLIPIT_char_type_size = sizeof(char); +/***************MODIFIED***************/ /* MPI injections */ -static int FLIPIT_Rank = 0; -static int FLIPIT_RankInject = 0; +static uint32_t FLIPIT_Rank = 0; +static uint32_t FLIPIT_RankInject = 0; /* Selective Injections */ -static int* FLIPIT_FaultSites = NULL; -static int FLIPIT_NumFaultSites = -1; - +static uint32_t * FLIPIT_FaultSites = NULL; +static uint32_t FLIPIT_NumFaultSites = -1; static void (*FLIPIT_CustomLogger)(FILE*) = NULL; static void (*FLIPIT_CountdownCustomLogger)(FILE*) = NULL; static double (*FLIPIT_FaultProb)() = NULL; static void flipit_parseArgs(int argc, char** argv); -static int flipit_shouldInject(int fault_index, int inject_once); -static void flipit_print_injectedErr(char* type, unsigned int bPos, int fault_index, double prob, - double p); +/***************MODIFIED***************/ +static uint8_t flipit_shouldInjectNoCheck(); +static uint8_t flipit_shouldInjectCheck(uint32_t fault_index); +/***************MODIFIED***************/ static double flipit_countdown(); static void flipit_countdownLogger(FILE*); @@ -65,17 +75,20 @@ void FLIPIT_Init(int myRank, int argc, char** argv, unsigned long long seed) { printf("Fault injector seed: %llu\n", seed+myRank); home = getenv("HOME"); - path = (char*) malloc(strlen(home) + strlen("/.FlipItState")+1); + path = (char*) malloc(strlen(home) + strlen("/.FlipItState")+1); strcpy(path, home); strcat(path, "/.FlipItState"); infile = fopen(path, "r"); - if (infile) { ammount = fscanf(infile, "%d", &FLIPIT_MAX_LOC); fclose(infile); } FLIPIT_Histogram = (unsigned long*) calloc(FLIPIT_MAX_LOC, sizeof(unsigned long)); - + + /***************MODIFIED***************/ + FLIPIT_FaultSites = calloc(FLIPIT_MAX_INJECT_LINES, FLIPIT_char_type_size); + /***************MODIFIED***************/ + #ifdef FLIPIT_DEBUG printf("Rank %d alloced an FLIPIT_Histogram of length: %d\n", FLIPIT_Rank, FLIPIT_MAX_LOC); #endif @@ -153,6 +166,7 @@ int FLIPIT_GetInjectionCount() { /***********************************************************************************************/ /* User callable function for FORTRAN wrapper */ /***********************************************************************************************/ + int flipit_init_ftn_(int* myRank, int* argc, char*** argv, unsigned long long* seed) { if (argv == NULL) FLIPIT_Init(*myRank, 0, NULL, *seed); @@ -194,11 +208,14 @@ int flipit_countdowntimer_ftn_(unsigned long* numInstructions) { /* The functions below this are used internally by FlipIt */ /***********************************************************************************************/ - +/*CAN WE USE GETOPT, IT IS MORE STANDARIZED TO USE*/ static void flipit_parseArgs(int argc, char** argv) { int i, j; int numFaulty = -1; + //TODO + //Probably Initialize the FLIPIT_REMAIN_INJECT_COUNT here? + for (i = 1; i < argc; i++){ if (strcmp("--numberFaulty", argv[i]) == 0 || strcmp("-nF", argv[i]) == 0) numFaulty = atoi(argv[++i]); @@ -212,7 +229,7 @@ static void flipit_parseArgs(int argc, char** argv) { else if (strcmp("--numberFaultLoc", argv[i]) == 0 || strcmp("-nLOC", argv[i]) == 0) FLIPIT_NumFaultSites = atoi(argv[++i]); else if (strcmp("--faultyLoc", argv[i]) == 0 || strcmp("-fLOC", argv[i]) == 0) { - FLIPIT_FaultSites = (int*) malloc( sizeof(int) * FLIPIT_NumFaultSites); + FLIPIT_FaultSites = malloc( sizeof(int) * FLIPIT_NumFaultSites); for(j = 0; j < FLIPIT_NumFaultSites; j++) FLIPIT_FaultSites[j] = atoi(argv[i + j + 1]); i += j; @@ -240,52 +257,29 @@ static void flipit_parseArgs(int argc, char** argv) { } -static int flipit_shouldInject(int fault_index, int inject_once) { - int i; - int inject = (FLIPIT_State && FLIPIT_RankInject) ? 1 : 0; - FLIPIT_TotalInsts++; - if (!inject) - return 0; - /* check fault index site */ - inject = 0; - if (FLIPIT_FaultSites != NULL) { - for (i = 0; i < FLIPIT_NumFaultSites; i++) - if (FLIPIT_FaultSites[i] == fault_index) { - inject = 1; - break; - } - } - else - inject = 1; - - /* inject only once */ - if(inject_once == 1) - FLIPIT_SingleInjection = 1; - if(FLIPIT_SingleInjection == 1 && FLIPIT_InjectionCount > 0) - { - inject = 0; - FLIPIT_RankInject = 0; - } - FLIPIT_Attempts += inject; - return inject; +/***************MODIFIED***************/ +static uint8_t flipit_shouldInjectNoCheck() { + FLIPIT_TotalInsts++; //CS + if ((0 == FLIPIT_State) + || (0 == FLIPIT_RankInject) + || (0 == FLIPIT_REMAIN_INJECT_COUNT)) //CS + return 0; + FLIPIT_Attempts++; //CS + return 1; } -static void flipit_print_injectedErr(char* type, unsigned int bPos, int fault_index, double prob, - double p) { - printf("\n/*********************************Start**************************************/\n" - "\nSuccessfully injected %s error!!\nRank: %d\n" - "Total # faults injected: %d\n" - "Bit position is: %u\n" - "Index of the fault site: %d\n" - "Fault site probability: %e\n" - "Chosen random probability is: %e\n" - "Attempts since last injection: %lu\n", type, FLIPIT_Rank, FLIPIT_InjectionCount, - bPos, fault_index, - prob, p, FLIPIT_Attempts); - if (FLIPIT_CustomLogger != NULL) - FLIPIT_CustomLogger(stdout); - printf("\n/*********************************End**************************************/\n"); +static uint8_t flipit_shouldInjectCheck(uint32_t fault_index) { + + FLIPIT_TotalInsts++; //CS + if ((0 == FLIPIT_State) || (0 == FLIPIT_RankInject) || (0 == FLIPIT_REMAIN_INJECT_COUNT)) //CS + return 0; + + uint32_t index = fault_index / FLIPIT_char_type_size; + uint8_t bit = fault_index % FLIPIT_char_type_size; + uint8_t inject = (FLIPIT_FaultSites[index] & (0x1 << (bit))) >> (bit); + FLIPIT_Attempts += inject; //CS + return inject; } static double flipit_countdown() { @@ -302,277 +296,156 @@ static void flipit_countdownLogger(FILE* outfile) { /* The functions below this are inserted by the compiler pass to flip a bit */ /***********************************************************************************************/ -char corruptIntData_8bit(int fault_index, int inject_once, double prob, int byte_val, - char inst_data) { - unsigned int bPos; - double p; - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_data; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_data; - - bPos = rand()%8; +/***************MODIFIED***************/ +#define FAULT_IDX_MASK 0x00FFFFFF +uint64_t corruptIntData_64bit(uint32_t parameter, float prob, uint64_t inst_data) { - FLIPIT_InjectionCount++; - flipit_print_injectedErr("8-bit Integer Data", bPos, fault_index, prob, p); - FLIPIT_Attempts = 0; - return inst_data ^ ((char) 0x1 << bPos); -} +#ifdef FLIPIT_HISTOGRAM + // extract fault_index, byte_val from parameter + uint32_t fault_index = (uint32_t) (parameter & FAULT_IDX_MASK); + FLIPIT_Histogram[fault_index]++; +#endif + if (0 == flipit_shouldInjectNoCheck()) return inst_data; -short corruptIntData_16bit(int fault_index, int inject_once, double prob, int byte_val, short inst_data) { - unsigned int bPos; - double p; - - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_data; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_data; +#ifndef FLIPIT_HISTOGRAM + uint32_t fault_index = (uint32_t) (parameter & FAULT_IDX_MASK); +#endif - if (byte_val == -1 || byte_val > 1) - byte_val = rand()%2; - bPos=(8*byte_val)+rand()%8; + float p = FLIPIT_FaultProb(); + if (p > prob) return inst_data; + + // determine which bit & byte should be flipped + char bit = ((parameter >> 24) & 0xF); + char byte = ((parameter >> 28) & 0xF); + if (bit == 0xF) bit = rand() % 8; + if (byte == 0xF) byte = rand() % 8; + FLIPIT_InjectionCount++; - flipit_print_injectedErr("16-bit Integer Data", bPos, fault_index, prob, p); + FLIPIT_REMAIN_INJECT_COUNT--; + // turns off the injector for this rank (MPI term for process). + if (0 == FLIPIT_REMAIN_INJECT_COUNT) FLIPIT_RankInject = 0; + + // print out error info + printf("\n/*********************************Start**************************************/\n" + "\nSuccessfully injected 1 bit data error at byte %u!!\nRank: %d\n" + "Total # faults injected: %d\n" + "Bit position is: %u\n" + "Index of the fault site: %d\n" + "Fault site probability: %e\n" + "Chosen random probability is: %e\n" + "Attempts since last injection: %lu\n", + byte, FLIPIT_Rank, FLIPIT_InjectionCount, bit, fault_index, prob, p, FLIPIT_Attempts); + if (FLIPIT_CustomLogger != NULL) + FLIPIT_CustomLogger(stdout); + printf("\n/*********************************End**************************************/\n"); + FLIPIT_Attempts = 0; - return inst_data ^ ((short) 0x1 << bPos); -} + return inst_data ^ (((uint64_t)0x1 << (byte * FLIPIT_char_type_size)) << bit); +} +float corruptFloatData_32bit(uint32_t parameter, float prob, float inst_data) { -int corruptIntData_32bit(int fault_index, int inject_once, double prob, int byte_val, int inst_data) { - unsigned int bPos; - double p; +#ifdef FLIPIT_HISTOGRAM + // extract fault_index, byte_val from parameter + uint32_t fault_index = (uint32_t) (parameter & FAULT_IDX_MASK); FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_data; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_data; - - if (byte_val == -1 || byte_val > 3) - byte_val = rand()%4; - bPos=(8*byte_val)+rand()%8; - - FLIPIT_InjectionCount++; -flipit_print_injectedErr("32-bit Integer Data", bPos, fault_index, prob, p); - FLIPIT_Attempts = 0; - return inst_data ^ ((int) 0x1 << bPos); -} +#endif -float corruptFloatData_32bit(int fault_index, int inject_once, double prob, int byte_val, float inst_data) { - unsigned int bPos; - double p; - - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_data; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_data; + if (0 == flipit_shouldInjectNoCheck()) return inst_data; - if (byte_val == -1 || byte_val > 3) - byte_val = rand()%4; - bPos=(8*byte_val)+rand()%8; +#ifndef FLIPIT_HISTOGRAM + uint32_t fault_index = (uint32_t) (parameter & FAULT_IDX_MASK); +#endif - FLIPIT_InjectionCount++; - flipit_print_injectedErr("32-bit IEEE Float Data", bPos, fault_index, prob, p); - FLIPIT_Attempts = 0; + float p = FLIPIT_FaultProb(); + if (p > prob) return inst_data; - int* ptr = (int* ) &inst_data; - int tmp = (*ptr ^ (0x1 << bPos)); - float*pf = (float*)&tmp; - return *pf; - -} + // determine which bit & byte should be flipped + char bit = ((parameter >> 24) & 0xF); + char byte = ((parameter >> 28) & 0xF); -long long corruptIntData_64bit(int fault_index, int inject_once, double prob, int byte_val, long long inst_data) { - unsigned int bPos; - double p; - - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_data; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_data; - - if (byte_val == -1) - byte_val = rand()%8; - bPos=(8*byte_val)+rand()%8; + if (bit == 0xF) bit = rand() % 8; + if (byte == 0xF || byte > 3) byte = rand() % 4; + FLIPIT_InjectionCount++; - flipit_print_injectedErr("64-bit Integer Data", bPos, fault_index, prob, p); - FLIPIT_Attempts = 0; - return inst_data ^ ((long long) 0x1L << bPos); -} - -long long corruptPtr2Int_64bit(int fault_index, int inject_once, double prob, int byte_val, long long inst_data) { - unsigned int bPos; - double p; + FLIPIT_REMAIN_INJECT_COUNT--; + // turns off the injector for this rank (MPI term for process). + if (0 == FLIPIT_REMAIN_INJECT_COUNT) FLIPIT_RankInject = 0; + + // print out error info + printf("\n/*********************************Start**************************************/\n" + "\nSuccessfully injected 1 bit data error at byte %u!!\nRank: %d\n" + "Total # faults injected: %d\n" + "Bit position is: %u\n" + "Index of the fault site: %d\n" + "Fault site probability: %e\n" + "Chosen random probability is: %e\n" + "Attempts since last injection: %lu\n", + byte, FLIPIT_Rank, FLIPIT_InjectionCount, bit, fault_index, prob, p, FLIPIT_Attempts); + if (FLIPIT_CustomLogger != NULL) + FLIPIT_CustomLogger(stdout); + printf("\n/*********************************End**************************************/\n"); - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_data; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_data; - - if (byte_val == -1) - byte_val = rand()%8; - bPos=(8*byte_val)+rand()%8; - FLIPIT_InjectionCount++; - flipit_print_injectedErr("Converted Pointer", bPos, fault_index, prob, p); - FLIPIT_Attempts = 0; - return inst_data ^ ((long long) 0x1L << bPos); -} - -double corruptFloatData_64bit(int fault_index, int inject_once, double prob, int byte_val, double inst_data) { - unsigned int bPos; - double p; - - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_data; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_data; - - if (byte_val == -1) - byte_val = rand()%8; - bPos=(8*byte_val)+rand()%8; - FLIPIT_InjectionCount++; - flipit_print_injectedErr("64-bit IEEE Float Data", bPos, fault_index, prob, p); FLIPIT_Attempts = 0; - long long* ptr = (long long* ) &inst_data; - long long tmp = (*ptr ^ (0x1L << bPos)); - double *pf = (double*)&tmp; + int* ptr = (int* ) &inst_data; + int tmp = (*ptr ^ (0x1 << (bit + byte * 8))); + float*pf = (float*)&tmp; return *pf; } +double corruptFloatData_64bit(uint32_t parameter, float prob, double inst_data) { -char* corruptIntAdr_8bit(int fault_index, int inject_once, double prob, int byte_val, char* inst_add) { - unsigned int bPos; - double p; - +#ifdef FLIPIT_HISTOGRAM + // extract fault_index, byte_val from parameter + uint32_t fault_index = (uint32_t) (parameter & FAULT_IDX_MASK); FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_add; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_add; - - if (byte_val == -1) - byte_val = rand()%8; - bPos=(8*byte_val)+rand()%8; - FLIPIT_InjectionCount++; - flipit_print_injectedErr("8-bit Integer pointer", bPos, fault_index, prob, p); - FLIPIT_Attempts = 0; - return (char*) ((long long) inst_add ^ ((long long) 0x1L << bPos)); -} +#endif -short* corruptIntAdr_16bit(int fault_index, int inject_once, double prob, int byte_val, short* inst_add) { - unsigned int bPos; - double p; + if (0 == flipit_shouldInjectNoCheck()) return inst_data; - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_add; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_add; - - if (byte_val == -1) - byte_val = rand()%8; - bPos=(8*byte_val)+rand()%8; - FLIPIT_InjectionCount++; - flipit_print_injectedErr("16-bit Integer pointer", bPos, fault_index, prob, p); - FLIPIT_Attempts = 0; - return (short*) ((long long) inst_add ^ ((long long) 0x1L << bPos)); -} +#ifndef FLIPIT_HISTOGRAM + uint32_t fault_index = (uint32_t) (parameter & FAULT_IDX_MASK); +#endif -int* corruptIntAdr_32bit(int fault_index, int inject_once, double prob, int byte_val, int* inst_add) { - unsigned int bPos; - double p; - - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_add; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_add; - - if (byte_val == -1) - byte_val = rand()%8; - bPos=(8*byte_val)+rand()%8; - FLIPIT_InjectionCount++; - flipit_print_injectedErr("32-bit Integer pointer", bPos, fault_index, prob, p); - FLIPIT_Attempts = 0; - return (int*) ((long long) inst_add ^ ((long long) 0x1L << bPos)); -} + float p = FLIPIT_FaultProb(); + if (p > prob) return inst_data; -long long* corruptIntAdr_64bit(int fault_index, int inject_once, double prob, int byte_val, long long* inst_add) { - unsigned int bPos; - double p; + // determine which bit & byte should be flipped + char bit = ((parameter >> 24) & 0xF); + char byte = ((parameter >> 28) & 0xF); - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_add; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_add; - - if (byte_val == -1) - byte_val = rand()%8; - bPos=(8*byte_val)+rand()%8; + if (bit == 0xF) bit = rand() % 8; + if (byte == 0xF) byte = rand() % 8; FLIPIT_InjectionCount++; - flipit_print_injectedErr("64-bit Integer pointer", bPos, fault_index, prob, p); + FLIPIT_REMAIN_INJECT_COUNT--; + // turns off the injector for this rank (MPI term for process). + if (0 == FLIPIT_REMAIN_INJECT_COUNT) FLIPIT_RankInject = 0; + + // print out error info + printf("\n/*********************************Start**************************************/\n" + "\nSuccessfully injected 1 bit data error at byte %u!!\nRank: %d\n" + "Total # faults injected: %d\n" + "Bit position is: %u\n" + "Index of the fault site: %d\n" + "Fault site probability: %e\n" + "Chosen random probability is: %e\n" + "Attempts since last injection: %lu\n", + byte, FLIPIT_Rank, FLIPIT_InjectionCount, bit, fault_index, prob, p, FLIPIT_Attempts); + if (FLIPIT_CustomLogger != NULL) + FLIPIT_CustomLogger(stdout); + printf("\n/*********************************End**************************************/\n"); + FLIPIT_Attempts = 0; - return (long long*) ((long long) inst_add ^ ((long long) 0x1L << bPos)); -} - -float* corruptFloatAdr_32bit(int fault_index, int inject_once, double prob, int byte_val, float* inst_add) { - unsigned int bPos; - double p; - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_add; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_add; - - if (byte_val == -1) - byte_val = rand()%8; - bPos=(8*byte_val)+rand()%8; - FLIPIT_InjectionCount++; - flipit_print_injectedErr("32-bit IEEE Float pointer", bPos, fault_index, prob, p); - FLIPIT_Attempts = 0; - return (float*) ((long long) inst_add ^ ((long long) 0x1L << bPos)); + int tmp = (*ptr ^ (0x1 << (bit + byte * 8))); + double*pf = (double*)&tmp; + return *pf; } -double* corruptFloatAdr_64bit(int fault_index, int inject_once, double prob, int byte_val, double* inst_add) { - unsigned int bPos; - double p; - FLIPIT_Histogram[fault_index]++; - if (!flipit_shouldInject(fault_index, inject_once)) - return inst_add; - p = FLIPIT_FaultProb(); - if (p > prob) - return inst_add; - - if (byte_val == -1) - byte_val = rand()%8; - bPos=(8*byte_val)+rand()%8; - FLIPIT_InjectionCount++; - flipit_print_injectedErr("64-bit IEEE Float pointer", bPos, fault_index, prob, p); - FLIPIT_Attempts = 0; - return (double *) ((long long) inst_add ^ ((long long) 0x1L << bPos)); -} + diff --git a/src/corrupt/corrupt.h b/src/corrupt/corrupt.h index b51436d..2faf395 100644 --- a/src/corrupt/corrupt.h +++ b/src/corrupt/corrupt.h @@ -1,3 +1,4 @@ + /***********************************************************************************************/ /* This file is licensed under the University of Illinois/NCSA Open Source License. */ /* See LICENSE.TXT for details. */ @@ -20,7 +21,7 @@ extern "C" { #ifndef CORRUPTH #define CORRUPTH - +#include #include #include #include @@ -48,25 +49,12 @@ int flipit_init_ftn_(int* myRank, int* argc, char*** argv, unsigned long long* s int flipit_finalize_ftn_(char** filename); int flipit_setinjector_ftn_(int* state); int flipit_setrankinject_ftn_(int* state); -/* void flipit_setfaultprobability_ftn_(double(faultProb)()); */ -/* void flipit_setcustomlogger_ftn_(void (customLogger)(FILE*)); */ int flipit_countdowntimer_ftn_(unsigned long* numInstructions); /* corrupt the data */ -char corruptIntData_8bit (int fault_index, int inject_once, double prob, int byte_val, char inst_data); -short corruptIntData_16bit (int fault_index, int inject_once, double prob, int byte_val, short inst_data); -int corruptIntData_32bit (int fault_index, int inject_once, double prob, int byte_val, int inst_data); -float corruptFloatData_32bit (int fault_index, int inject_once, double prob, int byte_val, float inst_data); -long long corruptIntData_64bit (int fault_index, int inject_once, double prob, int byte_val, long long inst_data); -long long corruptPtr2Int_64bit (int fault_index, int inject_once, double prob, int byte_val, long long inst_data); -double corruptFloatData_64bit (int fault_index, int inject_once, double prob, int byte_val, double inst_data); - -char* corruptIntAdr_8bit (int fault_index, int inject_once, double prob, int byte_val, char* inst_data); -short* corruptIntAdr_16bit (int fault_index, int inject_once, double prob, int byte_val, short* inst_data); -int* corruptIntAdr_32bit (int fault_index, int inject_once, double prob, int byte_val, int* inst_add); -long long* corruptIntAdr_64bit (int fault_index, int inject_once, double prob, int byte_val, long long* inst_add); -float* corruptFloatAdr_32bit (int fault_index, int inject_once, double prob, int byte_val, float* inst_add); -double* corruptFloatAdr_64bit (int fault_index, int inject_once, double prob, int byte_val, double* inst_add); +float corruptFloatData_32bit (uint32_t parameter, float prob, float inst_data); +uint64_t corruptIntData_64bit (uint32_t parameter, float prob, uint64_t inst_data); +double corruptFloatData_64bit (uint32_t parameter, float prob, double inst_data); #endif diff --git a/src/pass/Makefile b/src/pass/Makefile index 7fcab31..2afb5cc 100644 --- a/src/pass/Makefile +++ b/src/pass/Makefile @@ -19,12 +19,14 @@ LDFLAGS = $(shell $(LLVM_CONFIG) --ldflags) ifeq ($(shell uname),Darwin) SHARED_LIB_OPT = -bundle -undefined dynamic_lookup else -SHARED_LIB_OPT = -shared -Wl, -O1 +SHARED_LIB_OPT = -shared -Wl, endif -all: libFlipItPass.so libFlipIt.so +all: libFlipItPass.so +#all: libFlipItPass.so libFlipIt.so -libFlipItPass.so:faults.cpp +#libFlipItPass.so:faults.cpp +libFlipItPass.so:faults_new.cpp $(CXX) $(CXXFLAGS) -DCOMPILE_PASS $(LDFLAGS) -o $@ $(SHARED_LIB_OPT) $< libFlipIt.so:faults.cpp diff --git a/src/pass/faults.cpp b/src/pass/faults.cpp index 22b32a7..f69e4e7 100644 --- a/src/pass/faults.cpp +++ b/src/pass/faults.cpp @@ -14,10 +14,7 @@ /* */ /***********************************************************************************************/ -#include "./faults.h" -//#include -//#include -//#include +#include "faults.h" #ifdef COMPILE_PASS FlipIt::DynamicFaults::DynamicFaults() : ModulePass(FlipIt::DynamicFaults::ID) { @@ -27,6 +24,7 @@ FlipIt::DynamicFaults::DynamicFaults(Module* M) { configPath = "FlipIt.config"; siteProb = 1e-8; byte_val = -1; + bit_val = -1; singleInj = 1; arith_err = true; ctrl_err = true; @@ -54,12 +52,12 @@ FlipIt::DynamicFaults::DynamicFaults(Module* M) { } #ifdef COMPILE_PASS FlipIt::DynamicFaults::DynamicFaults(string _funcList, string _configPath, double _siteProb, - int _byte_val, int _singleInj, bool _arith_err, + int _byte_val, int _bit_val, int _singleInj, bool _arith_err, bool _ctrl_err, bool _ptr_err, std::string _srcFile, Module* Mod): ModulePass(ID) #else FlipIt::DynamicFaults::DynamicFaults(string _funcList, string _configPath, double _siteProb, - int _byte_val, int _singleInj, bool _arith_err, + int _byte_val, int _bit_val, int _singleInj, bool _arith_err, bool _ctrl_err, bool _ptr_err, std::string _srcFile, Module* Mod) #endif { @@ -68,6 +66,7 @@ FlipIt::DynamicFaults::DynamicFaults(string _funcList, string _configPath, doubl configPath = _configPath; siteProb = _siteProb; byte_val = _byte_val; + bit_val = _bit_val; singleInj = _singleInj; arith_err = _arith_err; ctrl_err = _ctrl_err; @@ -100,16 +99,6 @@ bool FlipIt::DynamicFaults::runOnModule(Module &Mod) { M = &Mod; srand(time(NULL)); - if (byte_val < -1 || byte_val > 7) - byte_val = rand() % 8; - - /* Check for assertion violation(s) */ - assert(byte_val <= 7 && byte_val >= -1); - assert(siteProb >= 0. && siteProb < 1.); - assert(singleInj == 1 || singleInj == 0); - assert(ptr_err == 1 || ptr_err == 0); - assert(arith_err == 1 || arith_err == 0); - assert(ptr_err == 1 || ptr_err == 0); //Module::FunctionListType &functionList = M.getFunctionList(); @@ -136,6 +125,8 @@ bool FlipIt::DynamicFaults::runOnModule(Module &Mod) { Value *in = &(*I); if (in == NULL) continue; + // isa(in) determine whether it's a instruction call + // Grab the name of the function being called if ( (isa(in) || isa(in) || isa(in) || isa(in) || isa(in) || isa(in) @@ -201,7 +192,35 @@ bool FlipIt::DynamicFaults::viableFunction(std::string func, std::vector 7) + + // This will not provide a random value that is within the range of 0-8 + byte_val = rand() % 8; + + /* Check for assertion violation(s) */ + if (bit_val < -1 || bit_val > 63) + + bit_val = rand() % 63; + + if (bit_val != -1) { + if (byte_val == -1) byte_val = bit_val / 8; + bit_val = bit_val % 8; + } + + assert(byte_val <= 7 && byte_val >= -1); + assert(bit_val <= 7 && bit_val >= -1); + assert(siteProb >= 0. && siteProb < 1.); + assert(singleInj == 1 || singleInj == 0); + assert(ptr_err == 1 || ptr_err == 0); + assert(arith_err == 1 || arith_err == 0); + assert(ptr_err == 1 || ptr_err == 0); + + unsigned int t_byte_val = (byte_val << 28) & 0xF0000000; + unsigned int t_bit_val = (bit_val << 24) & 0x0F000000; + unsigned int t_faultIdx = faultIdx & 0x00FFFFFF; + parameter = t_byte_val | t_bit_val | t_faultIdx; + readConfig(configPath); /*Cache function references of the function defined in Corrupt.c to all inserting of *call instructions to them */ @@ -209,30 +228,26 @@ void FlipIt::DynamicFaults::init() { // TODO: get stateFile from config faultIdx = updateStateFile("FlipItState"/*stateFile*/, sum); - displayIdx = faultIdx; logfile = new LogFile(srcFile, faultIdx); -/* - ifstream infile; - string path(getenv("HOME")); - path += "/.FlipItState"; - - infile.open(path.c_str()); - if (infile.is_open()) { - infile >> faultIdx >> displayIdx; - oldFaultIdx = faultIdx; - } else { - faultIdx = 0; - displayIdx = 0; + + //set up args to be used in corrupt calls + args.reserve(3); + for (int i = 0; i < 3; i++) + args.push_back(NULL); + + // create constant ints for each byte position + for (int i=-1; i<8; i++) { + byteVal[i] = ConstantInt::get(IntegerType::getInt32Ty( + getGlobalContext()), i); } - infile.close(); -*/ + i64Ty = Type::getInt64Ty(getGlobalContext()); } void FlipIt::DynamicFaults::readConfig(string path) { std::ifstream infile; string line; infile.open(path.c_str()); - //errs() << "reading config file " << path << "\n"; + // read inst probs getline(infile, line); // INSTRUCTIONS: getline(infile, line); @@ -240,22 +255,34 @@ void FlipIt::DynamicFaults::readConfig(string path) { unsigned long found = line.find("="); if (found != string::npos) { - instProbs.insert(std::pair(line.substr(0, found), atof(line.substr(found+1).c_str()))); + auto constFP = ConstantFP::get(Type::getFloatTy( + getGlobalContext()), atof(line.substr(found+1).c_str())); + instProbs.insert(std::pair( + line.substr(0, found), constFP)); //instProbs[line.substr(0, found)] = atof(line.substr(found+1).c_str()); } getline(infile, line); } + // default injection probability + instProbs["default"] = ConstantFP::get(Type::getFloatTy( + getGlobalContext()), siteProb); + // read func probs while (infile) { unsigned long found = line.find("="); if (found != string::npos && line[0] != '#') { - funcProbs.insert(std::pair(line.substr(0, found), atof(line.substr(found+1).c_str()))); + auto constFP = ConstantFP::get(Type::getFloatTy( + getGlobalContext()), atof(line.substr(found+1).c_str())); + funcProbs.insert(std::pair( + line.substr(0, found), constFP)); //funcProbs[line.substr(0, found)] = atof(line.substr(found+1).c_str()); } getline(infile, line); } + funcProbs["zero"] = ConstantFP::get(Type::getFloatTy( + getGlobalContext()), 0); infile.close(); } @@ -263,19 +290,6 @@ void FlipIt::DynamicFaults::readConfig(string path) { bool FlipIt::DynamicFaults::finalize() { logfile->close(); //delete logfile; - /* - std::ofstream outfile; - string path(getenv("HOME")); - path += "/.FlipItState"; - - outfile.open(path.c_str() , ios::trunc); - if (!outfile.is_open()) { - errs() << "WARNING: unable to update injector state file at path: " << path << "\n"; - } else { - outfile << faultIdx << " " << displayIdx; - } - outfile.close(); -*/ return oldFaultIdx != faultIdx; } @@ -283,16 +297,16 @@ vector FlipIt::DynamicFaults::splitAtSpace(string spltStr) { std::vector strLst; std::istringstream isstr(spltStr); copy(std::istream_iterator(isstr), std::istream_iterator(), - std::back_inserter >(strLst)); + std::back_inserter>(strLst)); return strLst; } -double FlipIt::DynamicFaults::getInstProb(Instruction* I) { +Value* FlipIt::DynamicFaults::getInstProb(Instruction* I) { /*First check if it is a call to a function listed in the config file*/ if (CallInst *callInst = dyn_cast(I)) { if (callInst->getCalledFunction() == NULL) /* function pointers will be null */ - return 0; + return funcProbs["zero"]; string funcName = callInst->getCalledFunction()->getName().str(); if (funcProbs.find(funcName) != funcProbs.end()) @@ -302,7 +316,7 @@ double FlipIt::DynamicFaults::getInstProb(Instruction* I) { /* Get the probability from the instruction's type from the config file or the default probabilty given as a command line argument */ string type = I->getOpcodeName(); - return instProbs.find(type) != instProbs.end() ? instProbs[type] : siteProb; + return instProbs.find(type) != instProbs.end() ? instProbs[type] : instProbs["default"]; } unsigned long FlipIt::DynamicFaults::updateStateFile(const char* stateFile, unsigned long sum) @@ -320,7 +334,7 @@ unsigned long FlipIt::DynamicFaults::updateStateFile(const char* stateFile, unsi std::fstream file(stateFilePath); if (!file.is_open()) { - errs() << "Error opening state file: " << stateFilePath << " Assuming fault index of 0"; + file.close(); file.open(stateFilePath, std::fstream::out); if (!file.is_open()) { @@ -345,796 +359,248 @@ unsigned long FlipIt::DynamicFaults::updateStateFile(const char* stateFile, unsi return startNum; } -bool FlipIt::DynamicFaults::injectControl(Instruction* I) { - if (I == NULL) - return false; - - /* Locate the instruction I in the basic block BB */ - BasicBlock *BB = I->getParent(); - BasicBlock::iterator BI; - for (BI = BB->begin(); BI != BB->end(); BI++) - if (BI == *I) - break; +bool FlipIt::DynamicFaults::injectControl_NEW(Instruction* I) { /* Build argument list before calling Corrupt function */ - CallInst* CallI = NULL; - std::vector args; - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), faultIdx)); - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), singleInj)); - args.push_back(ConstantFP::get(Type::getDoubleTy(getGlobalContext()), getInstProb(I))); - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), byte_val)); + args[0] = ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), parameter); + + args[1] = getInstProb(I); /* Choose a fault site in CmpInst and insert Corrupt function call */ if (isa(I)) { - //injectionType = "Control-Branch"; + /* select a random arg to corrupt because corrupting the result will yeild a + 50% chance of branching incorrectly */ + unsigned int opPos = rand() % 2; + + /* LLVM doesn't like attempting to corrupt NULL */ + if (I->getOperand(opPos) == NULL) + opPos = (opPos+1) % 2; injectionType = CONTROL_BRANCH; - return inject_Compare(I, args, CallI); + return injectInOperand(I, opPos); } /* check to see if instruction modifies a looping variable such as i++ if so we need to inject into it and mark the injection type 'control' */ - if (!isa(I) && !isa(I)) - if (I->getName().str().find("indvars") == 0 - || I->getName().str().substr(0, 3) == "inc") + if (isa(I)) { + if (I->getOperand(0)->getName().str().find("indvars") == 0 + || I->getOperand(0)->getName().str().substr(0, 3) == "inc") { - //injectionType = "Control-Loop"; injectionType = CONTROL_LOOP; - return inject_Generic(I, args, CallI, BB); + return injectInOperand(I, 0); // value to be store } + } + if (I->getName().str().find("indvars") == 0 + || I->getName().str().substr(0, 3) == "inc") + { + injectionType = CONTROL_LOOP; + return injectResult(I); + } + + /* TODO: Add support of PHI Instruction */ return false; } - -bool FlipIt::DynamicFaults::injectArithmetic(Instruction* I) { - if (I == NULL) - return false; - - /* Locate the instruction I in the basic block BB */ - BasicBlock *BB = I->getParent(); - BasicBlock::iterator BI; - for (BI = BB->begin(); BI != BB->end(); BI++) - if (BI == *I) - break; - +bool FlipIt::DynamicFaults::injectArithmetic_NEW(Instruction* I) +{ /* Build argument list before calling Corrupt function */ - CallInst* CallI = NULL; - std::vector args; - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), faultIdx)); - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), singleInj)); - args.push_back(ConstantFP::get(Type::getDoubleTy(getGlobalContext()), getInstProb(I))); - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), byte_val)); - + args[0] = ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), parameter); + args[1] = getInstProb(I); + /* We handle these in a special way */ if (isa(I)) return false; - /* store instruction required differnt injection logic than binary operators - * (add mul div) and loads */ - if (isa(I)) - return inject_Store_Data(I, args, CallI); - if (!isa(I) && !isa(I)) { - return inject_Generic(I, args, CallI, BB); + /* store instruction required differnt injection logic than binary operators */ + if (isa(I)) { + if (I->getOperand(0)->getType()->isIntegerTy() + || I->getOperand(0)->getType()->isFloatingPointTy()) + { + bool ret = injectInOperand(I, 0); + comment = VALUE; + return ret; + } + } + + if (!isa(I)) { + if (I->getType()->isIntegerTy() + || I->getType()->isFloatingPointTy()) + { + bool ret = injectResult(I); + if (isa(I)) + comment = VALUE; + return ret; + } } return false; } -bool FlipIt::DynamicFaults::injectPointer(Instruction* I) { - if (I == NULL) - return false; - - CallInst* CallI = NULL; +bool FlipIt::DynamicFaults::injectPointer_NEW(Instruction* I) +{ /*Build argument list before calling Corrupt function*/ - std::vector args; - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), faultIdx)); - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), singleInj)); - args.push_back(ConstantFP::get(Type::getDoubleTy(getGlobalContext()), getInstProb(I))); - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), byte_val)); - - /*Locate the instruction I in the basic block BB*/ - BasicBlock *BB = I->getParent(); - BasicBlock::iterator BI, BINext; - for (BI = BB->begin(); BI != BB->end(); BI++) - if (BI == *I) - break; - - if (isa(I)) - return inject_Store_Ptr(I, args, CallI); - - if (isa(I)) - return inject_Load_Ptr(I, args, CallI, BI, BB); - - if (isa(I)) - return inject_Alloc_Ptr(I, args, CallI, BI, BB); - - if (isa(I)) - return inject_GetElementPtr_Ptr(I, args, CallI, BI, BB); + args[0] = ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), parameter); + args[1] = getInstProb(I); + auto type = isa(I) ? I->getOperand(0)->getType() : I->getType(); + + if (type->isPointerTy()) { + if (isa(I)) { + bool ret = injectInOperand(I, 0); //Value + comment = VALUE; + return ret; + } + bool ret = injectResult(I); + if (isa(I)) { + comment = VALUE; + } + return ret; + } return false; } -bool FlipIt::DynamicFaults::injectCall(Instruction* I) { - if (I == NULL) - return false; - - CallInst* CallI = NULL; +bool FlipIt::DynamicFaults::injectCall_NEW(Instruction* I) +{ /*Build argument list before calling Corrupt function*/ - std::vector args; - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), faultIdx)); - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), singleInj)); - args.push_back(ConstantFP::get(Type::getDoubleTy(getGlobalContext()), getInstProb(I))); - args.push_back(ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), byte_val)); - - /*Locate the instruction I in the basic block BB*/ - BasicBlock *BB = I->getParent(); - BasicBlock::iterator BI, BINext; - for (BI = BB->begin(); BI != BB->end(); BI++) - if (BI == *I) - break; - - if (isa(I)) - return inject_Call(I, args, CallI, BI, BB); + args[0] = ConstantInt::get(IntegerType::getInt32Ty(getGlobalContext()), parameter); + args[1] = getInstProb(I); + + if (!isa(I)) + return false; + if (dyn_cast(I)->getNumArgOperands() == 0) + { + bool ret = injectResult(I); + comment = RESULT; + return ret; + } + int opNum = selectArgument(dyn_cast(I)); + if (opNum == -1) + return false; - return false; + return injectInOperand(I, opNum); } -bool FlipIt::DynamicFaults::inject_Store_Data(Instruction* I, std::vector& args, CallInst* CallI) { - args.push_back(I->getOperand(0)); // value stored +bool FlipIt::DynamicFaults::injectResult(Instruction* I) { + + args[2] = I; + BasicBlock::iterator INext(I); + INext++; + Value* corruptVal = NULL; + Value* call = NULL; + //CallInst* call = NULL; + auto type = I->getType(); /*Integer Data*/ - if (I->getOperand(0)->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntData_8bit, args, "call_corruptIntData_8bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(0)->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntData_16bit, args, "call_corruptIntData_16bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(0)->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntData_32bit, args, "call_corruptIntData_32bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(0)->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntData_64bit, args, "call_corruptIntData_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(0)->getType()->isFloatTy()) { - /*Float Data*/ - CallI = CallInst::Create(func_corruptFloatData_32bit, args, - "call_corruptFloatData_32bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(0)->getType()->isDoubleTy()) { - CallI = CallInst::Create(func_corruptFloatData_64bit, args, - "call_corruptFloatData_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - return false; - } - if (CallI) { - Value* corruptVal = &(*CallI); - I->setOperand(0, corruptVal); - -#ifdef OLD_WAY - comment = "Value"; -#endif - comment = VALUE; - skipAmount = 0; - } - return true; -} + if (type->isIntegerTy()) { + if (! (type->isIntegerTy(64))) { + args[2] = new ZExtInst(I, i64Ty, "zxt", INext); + } + call = CallInst::Create(func_corruptIntData_64bit, args, + "call_corruptIntData_64bit", INext); + dyn_cast(call)->setCallingConv(CallingConv::C); + if (!(type->isIntegerTy(64))) { + call = new TruncInst(call, type, "trunc", INext); + } -bool FlipIt::DynamicFaults::inject_Compare(Instruction* I, std::vector& args, CallInst* CallI) { - /* select a random arg to corrupt because corrupting the result will yeild a - 50% chance of branching incorrectly */ - unsigned int opPos = rand() % 2; - PtrToIntInst* p2iI = NULL; - IntToPtrInst* i2pI = NULL; - Value* corruptVal = NULL; - Type* i64Ty = Type::getInt64Ty(I->getContext()); - - /* LLVM doesn't like attempting to corrupt NULL */ - if (I->getOperand(opPos) == NULL) - opPos = (opPos+1) % 2; - - args.push_back(I->getOperand(opPos)); - - - /*integer data*/ - if (I->getOperand(opPos)->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntData_8bit, args, "call_corruptIntData_8bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opPos)->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntData_16bit, args, "call_corruptIntData_16bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opPos)->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntData_32bit, args, "call_corruptIntData_32bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opPos)->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntData_64bit, args, "call_corruptIntData_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opPos)->getType()->isFloatTy()) { + } else if (type->isFloatTy()) { /*Float Data*/ - CallI = CallInst::Create(func_corruptFloatData_32bit, args, - "call_corruptFloatData_32bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opPos)->getType()->isDoubleTy()) { - CallI = CallInst::Create(func_corruptFloatData_64bit, args, - "call_corruptFloatData_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - /* We are comparing non-scalar data a.k.a pointers. Let's convert the pointer to a 64-bit - * integer corrupt that and cast back to the pointer type. */ - /* Value to corrupt is no longer correct */ - args.pop_back(); - + call = CallInst::Create(func_corruptFloatData_32bit, args, + "call_corruptFloatData_32bit", INext); + dyn_cast(call)->setCallingConv(CallingConv::C); + } else if (type->isDoubleTy()) { + call = CallInst::Create(func_corruptFloatData_64bit, args, + "call_corruptFloatData_64bit", INext); + dyn_cast(call)->setCallingConv(CallingConv::C); + }else if (type->isPointerTy()) { /* Convert ptr to int64 */ - p2iI = new PtrToIntInst(I->getOperand(opPos), i64Ty, "convert_ptr2i64", I); - assert(p2iI); + auto p2iI = new PtrToIntInst(I, i64Ty, "convert_ptr2i64", INext); /* Corrupt */ - args.push_back(p2iI); - CallI = CallInst::Create(func_corruptPtr2Int_64bit, args, "call_corruptPtr2Int_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - corruptVal = &(*CallI); + args[2] = p2iI; + call = CallInst::Create(func_corruptPtr2Int_64bit, args, + "call_corruptPtr2Int_64bit", INext); + dyn_cast(call)->setCallingConv(CallingConv::C); /* convert int64 to ptr */ - i2pI = new IntToPtrInst(corruptVal, I->getOperand(opPos)->getType(), "convert_i642ptr", I); - assert(i2pI); - } - - /* make sure everyone is using corrupt value */ - if (CallI) { - if (i2pI == NULL) - corruptVal = &(*CallI); - else - corruptVal = &(*i2pI); - I->setOperand(opPos, corruptVal); - comment = opPos + 1; -#ifdef OLD_WAY - strStream << "Operand # " << opPos; - comment = strStream.str(); - strStream.str(""); -#endif - skipAmount = 0; + corruptVal = new IntToPtrInst(call, I->getType(), "convert_i642ptr", INext); } - return true; -} - - -bool FlipIt::DynamicFaults::inject_Generic(Instruction* I, std::vector& args, CallInst* CallI, - BasicBlock* BB) { - Instruction* INext = NULL; - BasicBlock::iterator BI = *I; - args.push_back(&(*I)); - /* Corrupt result of instruction I */ - if (BI == BB->end()) { - - /*Integer Data*/ - if (I->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntData_8bit, args, - "call_corruptIntData_8bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntData_16bit, args, - "call_corruptIntData_16bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntData_32bit, args, - "call_corruptIntData_32bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntData_64bit, args, - "call_corruptIntData_64bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isFloatTy()) { - /*Float Data*/ - CallI = CallInst::Create(func_corruptFloatData_32bit, args, - "call_corruptFloatData_32bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isDoubleTy()) { - CallI = CallInst::Create(func_corruptFloatData_64bit, args, - "call_corruptFloatData_64bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - return false; - } - } else { - BasicBlock::iterator BINext = BI; - BINext++; - INext = &*BINext; - assert(INext); - - /*Integer Data*/ - if (I->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntData_8bit, args, - "call_corruptIntData_8bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntData_16bit, args, - "call_corruptIntData_16bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntData_32bit, args, - "call_corruptIntData_32bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntData_64bit, args, - "call_corruptIntData_64bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isFloatTy()) { - /*Float Data*/ - CallI = CallInst::Create(func_corruptFloatData_32bit, args, - "call_corruptFloatData_32bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isDoubleTy()) { - CallI = CallInst::Create(func_corruptFloatData_64bit, args, - "call_corruptFloatData_64bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - return false; - } + if (corruptVal == NULL) { + corruptVal = call; } - - if (CallI) { - Value* corruptVal = &(*CallI); + if (corruptVal) { I->replaceAllUsesWith(corruptVal); /* Because of the preceeding method invocation, we messed up last argument in the call instruction. We need to manually set this value to the result of Insturction I */ - BasicBlock::iterator BINext = BI; - BINext++; - INext = &*BINext; - INext->setOperand(4, I); // hard coded. If like others, it says we have an extra argument - comment = RESULT; -#ifdef OLD_WAY - comment = "Result"; -#endif - skipAmount = 1; - } - return true; -} - - -bool FlipIt::DynamicFaults::inject_Store_Ptr(Instruction* I, std::vector& args, CallInst* CallI) { - - PtrToIntInst* p2iI = NULL; - IntToPtrInst* i2pI = NULL; - Value* corruptVal = NULL; - Type* i64Ty = Type::getInt64Ty(I->getContext()); - /* Make sure we corrupt an pointer. First attempt to corupt the value being stored, - * but if that isn't a pointer let's inject into the address.*/ - int opNum = 0; - comment = VALUE; -#ifdef OLD_WAY - comment = "Value"; -#endif - if (!I->getType()->isPointerTy()) { - comment = ADDRESS; -#ifdef OLD_WAY - comment = "Address"; -#endif - opNum = 1; - } - - /*Corrupt operand*/ - args.push_back(I->getOperand(opNum)); - - if (I->getOperand(opNum)->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntAdr_8bit, args, "call_corruptIntAdr_8bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opNum)->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntAdr_16bit, args, "call_corruptIntAdr_16bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opNum)->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntAdr_32bit, args, "call_corruptIntAdr_32bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opNum)->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntAdr_64bit, args, "call_corruptIntAdr_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opNum)->getType()->isFloatTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_32bit, args, "call_corruptFloatAdr_32bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opNum)->getType()->isDoubleTy()){ - CallI = CallInst::Create(func_corruptFloatAdr_64bit, args, "call_corruptFloatAdr_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - args.pop_back(); - - /* Convert ptr to int64 */ - p2iI = new PtrToIntInst(I->getOperand(opNum), i64Ty, "convert_ptr2i64", I); - assert(p2iI); - - /* Corrupt */ - args.push_back(p2iI); - CallI = CallInst::Create(func_corruptPtr2Int_64bit, args, "call_corruptPtr2Int_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - corruptVal = &(*CallI); - - /* convert int64 to ptr */ - i2pI = new IntToPtrInst(corruptVal, I->getOperand(opNum)->getType(), "convert_i642ptr", I); - assert(p2iI); - - } - - /* make sure everyone is using corrupt value */ - if (CallI) { - if (i2pI == NULL) - corruptVal = &(*CallI); + INext = I; + INext++; + if (isa(INext)) + INext->setOperand(2, I); // hard coded. If like others, it says we have an extra argument else - corruptVal = &(*i2pI); - I->setOperand(opNum, corruptVal); - - comment = opNum + 1; -#ifdef OLD_WAY - strStream << "Operand # " << opNum; - comment = strStream.str(); - strStream.str(""); -#endif + INext->setOperand(0, I); + comment = RESULT; + return true; } - return true; + return false; } -bool FlipIt::DynamicFaults::inject_Load_Ptr(Instruction* I, std::vector& args, CallInst* CallI, BasicBlock::iterator BI, BasicBlock* BB) { +bool FlipIt::DynamicFaults::injectInOperand(Instruction* I, int operand) +{ - Instruction* INext; - PtrToIntInst* p2iI = NULL; - IntToPtrInst* i2pI = NULL; + /* We assume that operand is vaild */ + args[2] = I->getOperand(operand); // value stored Value* corruptVal = NULL; - Type* i64Ty = Type::getInt64Ty(I->getContext()); - - /* Make sure we corrupt an pointer. First attempt to corupt the value being loaded, - * but if that isn't a pointer let's inject into the address */ - Value* ptr = &(*I); -#ifdef OLD_WAY - comment = "Value"; -#endif - comment = VALUE; - if (!I->getType()->isPointerTy()) { - ptr = dyn_cast(I)->getPointerOperand(); -#ifdef OLD_WAY - comment = "Address"; -#endif - comment = ADDRESS; - } - args.push_back(ptr); - - if (ptr->getType()->getPointerElementType()->isVectorTy() || ptr->getType()->getPointerElementType()->isIntegerTy(1)) - return false; - - /* Depending on if we are injecting into the result of an operand we need to handle things differenlty */ -#ifdef OLD_WAY - if (comment == "Value") { -#endif - if (comment == VALUE) { - if (BI == BB->end()) { - if (ptr->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntAdr_8bit, args, "call_corruptIntAdr_8bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntAdr_16bit, args, "call_corruptIntAdr_16bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntAdr_32bit, args, "call_corruptIntAdr_32bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntAdr_64bit, args, "call_corruptIntAdr_64bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isFloatTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_32bit, args, "call_corruptFloatAdr_32bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isDoubleTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_64bit, args, "call_corruptFloatAdr_64bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - args.pop_back(); - /* Convert ptr to int64 */ - p2iI = new PtrToIntInst(ptr, i64Ty, "convert_ptr2i64", BB); - assert(p2iI); - - /* Corrupt */ - args.push_back(p2iI); - CallI = CallInst::Create(func_corruptPtr2Int_64bit, args, "call_corruptPtr2Int_64bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - corruptVal = &(*CallI); - - /* convert int64 to ptr */ - i2pI = new IntToPtrInst(corruptVal, ptr->getType(), "convert_i642ptr", BB); - assert(i2pI); - } - } else { - BasicBlock::iterator BINext = BI; - BINext++; - INext = &*BINext; - assert(INext); - - if (ptr->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntAdr_8bit, args, "call_corruptIntAdr_8bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntAdr_16bit, args, "call_corruptIntAdr_16bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntAdr_32bit, args, "call_corruptIntAdr_32bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntAdr_64bit, args, "call_corruptIntAdr_64bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isFloatTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_32bit, args, "call_corruptFloatAdr_32bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isDoubleTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_64bit, args, "call_corruptFloatAdr_64bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - args.pop_back(); - /* Convert ptr to int64 */ - p2iI = new PtrToIntInst(ptr, i64Ty, "convert_ptr2i64", INext); - assert(p2iI); - - /* Corrupt */ - args.push_back(p2iI); - CallI = CallInst::Create(func_corruptPtr2Int_64bit, args, "call_corruptPtr2Int_64bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - corruptVal = &(*CallI); - - /* convert int64 to ptr */ - i2pI = new IntToPtrInst(corruptVal, ptr->getType(), "convert_i642ptr", INext); - assert(i2pI); - } - } - } else { - /* if (comment == "Address") */ - if (ptr->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntAdr_8bit, args, "call_corruptIntAdr_8bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntAdr_16bit, args, "call_corruptIntAdr_16bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntAdr_32bit, args, "call_corruptIntAdr_32bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntAdr_64bit, args, "call_corruptIntAdr_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isFloatTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_32bit, args, "call_corruptFloatAdr_32bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (ptr->getType()->isDoubleTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_64bit, args, "call_corruptFloatAdr_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - args.pop_back(); - - BasicBlock::iterator BINext = BI; - BINext++; - Instruction* INext = &*BINext; - - assert(INext); - - /* Convert ptr to int64 */ - p2iI = new PtrToIntInst(ptr, i64Ty, "convert_ptr2i64", I); - assert(p2iI); - - /* Corrupt */ - args.push_back(p2iI); - CallI = CallInst::Create(func_corruptPtr2Int_64bit, args, "call_corruptPtr2Int_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - corruptVal = &(*CallI); - - /* convert int64 to ptr */ - i2pI = new IntToPtrInst(corruptVal, ptr->getType(), "convert_i642ptr", I); - assert(p2iI); + Value* call = NULL; + auto type = I->getOperand(operand)->getType(); + /*Integer Data*/ + if (type->isIntegerTy()) { + if (! (type->isIntegerTy(64))) { + args[2] = new ZExtInst(I->getOperand(operand), i64Ty, "zxt", I); } - } - if (CallI) { -#ifdef OLD_WAY - if (comment == "Value") { -#endif - if (comment == VALUE) { - - if (i2pI == NULL) - corruptVal = &(*CallI); - else - corruptVal = &(*i2pI); - I->replaceAllUsesWith(corruptVal); - - /* Because of the preceeding method invocation, we messed up last argument in the call instruction. - We need to manually set this value to the result of Insturction I */ - BasicBlock::iterator BINext = BI; - BINext++; - INext = &*BINext; - INext->setOperand(/*4*/INext->getNumOperands() - 1, I); - } else { - /* if (comment == "Address") */ - if (i2pI == NULL) - corruptVal = &(*CallI); - else - corruptVal = &(*i2pI); - I->setOperand(0, corruptVal); - + call = CallInst::Create(func_corruptIntData_64bit, args, + "call_corruptIntData_64bit", I); + dyn_cast(call)->setCallingConv(CallingConv::C); + if (!(type->isIntegerTy(64))) { + call = new TruncInst(call, type, "trunc", I); } - } - return true; -} - -bool FlipIt::DynamicFaults::inject_Alloc_Ptr(Instruction* I, std::vector& args, CallInst* CallI, BasicBlock::iterator BI, BasicBlock* BB) { - - Instruction* INext = NULL; - PtrToIntInst* p2iI = NULL; - IntToPtrInst* i2pI = NULL; - Value* corruptVal = NULL; - Type* i64Ty = Type::getInt64Ty(I->getContext()); - - /* we are corrupting the pointer returned from the allocation */ - args.push_back(I); - if (BI == BB->end()) { - if (I->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntAdr_8bit, args, "call_corruptIntAdr_8bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntAdr_16bit, args, "call_corruptIntAdr_16bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntAdr_32bit, args, "call_corruptIntAdr_32bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntAdr_64bit, args, "call_corruptIntAdr_64bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isFloatTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_32bit, args, "call_corruptFloatAdr_32bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isDoubleTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_64bit, args, "call_corruptFloatAdr_64bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - args.pop_back(); - /* Convert ptr to int64 */ - p2iI = new PtrToIntInst(I, i64Ty, "convert_ptr2i64", BB); - assert(p2iI); - - /* Corrupt */ - args.push_back(p2iI); - CallI = CallInst::Create(func_corruptPtr2Int_64bit, args, "call_corruptPtr2Int_64bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - corruptVal = &(*CallI); - - /* convert int64 to ptr */ - i2pI = new IntToPtrInst(corruptVal, I->getType(), "convert_i642ptr", BB); - assert(i2pI); - } - } else { - BasicBlock::iterator BINext = BI; - BINext++; - INext = &*BINext; - assert(INext); - - if (I->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntAdr_8bit, args, "call_corruptIntAdr_8bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntAdr_16bit, args, "call_corruptIntAdr_16bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntAdr_32bit, args, "call_corruptIntAdr_32bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntAdr_64bit, args, "call_corruptIntAdr_64bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isFloatTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_32bit, args, "call_corruptFloatAdr_32bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getType()->isDoubleTy()) { - CallI = CallInst::Create(func_corruptFloatAdr_64bit, args, "call_corruptFloatAdr_64bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - args.pop_back(); - /* Convert ptr to int64 */ - p2iI = new PtrToIntInst(I, i64Ty, "convert_ptr2i64", INext); - assert(p2iI); + } else if (type->isFloatTy()) { + /*Float Data*/ + call = CallInst::Create(func_corruptFloatData_32bit, args, + "call_corruptFloatData_32bit", I); + dyn_cast(call)->setCallingConv(CallingConv::C); + } else if (type->isDoubleTy()) { + call = CallInst::Create(func_corruptFloatData_64bit, args, + "call_corruptFloatData_64bit", I); + dyn_cast(call)->setCallingConv(CallingConv::C); + } + else if (type->isPointerTy()) { + auto p2iI = new PtrToIntInst(args[2], i64Ty, "convert_ptr2i64", I); /* Corrupt */ - args.push_back(p2iI); - CallI = CallInst::Create(func_corruptPtr2Int_64bit, args, "call_corruptPtr2Int_64bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - corruptVal = &(*CallI); + args[2] = p2iI; + call = CallInst::Create(func_corruptPtr2Int_64bit, args, + "call_corruptPtr2Int_64bit", I); + dyn_cast(call)->setCallingConv(CallingConv::C); /* convert int64 to ptr */ - i2pI = new IntToPtrInst(corruptVal, I->getType(), "convert_i642ptr", INext); - assert(i2pI); - } + corruptVal = new IntToPtrInst(call, type, "convert_i642ptr", I); } - - /* make sure everyone is using corrupt value */ - if (CallI) { - - if (i2pI == NULL) - corruptVal = &(*CallI); - else - corruptVal = &(*i2pI); - I->replaceAllUsesWith(corruptVal); - - /* Because of the preceeding method invocation, we messed up last argument in the call instruction. - We need to manually set this value to the result of Insturction I */ - BasicBlock::iterator BINext = BI; - BINext++; - INext = &*BINext; - INext->setOperand(/*4*/INext->getNumOperands() - 1, I); -#ifdef OLD_WAY - comment = "Result"; -#endif - comment = RESULT; + if (corruptVal == NULL) { + corruptVal = call; + } + if (corruptVal) { + I->setOperand(operand, corruptVal); + comment = operand + 1; + return true; } - return true; + return false; } + int FlipIt::DynamicFaults::selectArgument(CallInst* callInst) { int arg = -1; int possArgLen = callInst->getNumArgOperands(); @@ -1179,7 +645,7 @@ int FlipIt::DynamicFaults::selectArgument(CallInst* callInst) { || v->getName().str().substr(0, 3) == "inc") { arg = a; injectionType = CONTROL_LOOP; - //injectionType = "Control-Loop"; + argFound = true; } } else if (arith_err && (callInst->getArgOperand(a)->getType()->isIntegerTy() @@ -1193,12 +659,12 @@ int FlipIt::DynamicFaults::selectArgument(CallInst* callInst) { || callInst->getArgOperand(a)->getType()->isDoubleTy()) { injectionType = ARITHMETIC_FP; } - //injectionType = "Arithmetic"; + argFound = true; } else if (ptr_err) { arg = a; injectionType = POINTER; - //injectionType = "Pointer"; + argFound = true; } argPos.erase(argPos.begin() + a); @@ -1207,198 +673,26 @@ int FlipIt::DynamicFaults::selectArgument(CallInst* callInst) { return arg; } -bool FlipIt::DynamicFaults::inject_Call(Instruction* I, std::vector& args, CallInst* CallI, - BasicBlock::iterator BI, BasicBlock* BB) { - PtrToIntInst* p2iI = NULL; - IntToPtrInst* i2pI = NULL; - Value* corruptVal = NULL; - Type* i64Ty = Type::getInt64Ty(I->getContext()); - if (dyn_cast(I)->getNumArgOperands() == 0) - return false; - - int opNum = selectArgument(dyn_cast(I)); - if (opNum == -1) - return false; - - args.push_back(I->getOperand(opNum)); - - /* corrupting scalar values */ - if (I->getOperand(opNum)->getType()->isIntegerTy(8)) { - CallI = CallInst::Create(func_corruptIntData_8bit, args, "call_corruptIntData_8bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opNum)->getType()->isIntegerTy(16)) { - CallI = CallInst::Create(func_corruptIntData_16bit, args, "call_corruptIntData_16bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opNum)->getType()->isIntegerTy(32)) { - CallI = CallInst::Create(func_corruptIntData_32bit, args, "call_corruptIntData_32bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opNum)->getType()->isIntegerTy(64)) { - CallI = CallInst::Create(func_corruptIntData_64bit, args, "call_corruptIntData_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opNum)->getType()->isFloatTy()) { - CallI = CallInst::Create(func_corruptFloatData_32bit, args, - "call_corruptFloatData_32bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else if (I->getOperand(opNum)->getType()->isDoubleTy()) { - CallI = CallInst::Create(func_corruptFloatData_64bit, args, - "call_corruptFloatData_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - } else { - args.pop_back(); - - /* Convert ptr to int64 */ - p2iI = new PtrToIntInst(I->getOperand(opNum), i64Ty, "convert_ptr2i64", I); - assert(p2iI); - - /* Corrupt */ - args.push_back(p2iI); - CallI = CallInst::Create(func_corruptPtr2Int_64bit, args, "call_corruptPtr2Int_64bit", I); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - corruptVal = &(*CallI); - - /* convert int64 to ptr */ - i2pI = new IntToPtrInst(corruptVal, I->getOperand(opNum)->getType(), "convert_i642ptr", I); - assert(p2iI); - } - - /* make sure everyone is using corrupt value */ - if (CallI != NULL) { - if (i2pI == NULL) - corruptVal = &(*CallI); - else - corruptVal = &(*i2pI); - BI->setOperand(opNum, corruptVal); - comment = opNum +1; -#ifdef OLD_WAY - strStream << "Arg # " << opNum; - comment = strStream.str(); - strStream.str(""); -#endif - } - return true; -} - -bool FlipIt::DynamicFaults::inject_GetElementPtr_Ptr(Instruction* I, std::vector& args, - CallInst* CallI, BasicBlock::iterator BI, - BasicBlock* BB) { - Instruction* INext = NULL; - PtrToIntInst* p2iI = NULL; - IntToPtrInst* i2pI = NULL; - Value* corruptVal = NULL; - BI = *I; - Type* i64Ty = Type::getInt64Ty(I->getContext()); - - if (BI == BB->end()) { - /* Convert ptr to int64 */ - p2iI = new PtrToIntInst(I, i64Ty, "convert_ptr2i64", BB); - assert(p2iI); - - /* Corrupt */ - args.push_back(p2iI); - CallI = CallInst::Create(func_corruptPtr2Int_64bit, args, "call_corruptPtr2Int_64bit", BB); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - corruptVal = &(*CallI); - - /* convert int64 to ptr */ - i2pI = new IntToPtrInst(corruptVal, I->getType(), "convert_i642ptr", BB); - assert(i2pI); - } else { - BasicBlock::iterator BINext = BI; - BINext++; - INext = &*BINext; - assert(INext); - - /* Convert ptr to int64 */ - p2iI = new PtrToIntInst(I, i64Ty, "convert_ptr2i64", INext); - assert(p2iI); - - /* Corrupt */ - args.push_back(p2iI); - assert(func_corruptPtr2Int_64bit); - CallI = CallInst::Create(func_corruptPtr2Int_64bit, args, - "call_corruptPtr2Int_64bit", INext); - assert(CallI); - CallI->setCallingConv(CallingConv::C); - corruptVal = &(*CallI); - - /* convert int64 to ptr */ - i2pI = new IntToPtrInst(corruptVal, I->getType(), "convert_i642ptr", INext); - assert(i2pI); - } - - /* make sure everyone is using corrupt value */ - if (CallI) { - corruptVal = &(*i2pI); - I->replaceAllUsesWith(corruptVal); - - /* Because of the preceeding method invocation, we messed up last argument in - * the call instruction. We need to manually set this value */ - BasicBlock::iterator BINext = BI; - BINext++; - INext = &*BINext; - INext->setOperand(/*4*/INext->getNumOperands() -1, I); - -#ifdef OLD_WAY - comment = "Result"; -#endif - comment = RESULT; - } - return true; -} - unsigned long FlipIt::DynamicFaults::cacheFunctions() { //Module::FunctionListType &functionList) { unsigned long sum = 0; // # insts in module for (auto F = M->getFunctionList().begin(), E = M->getFunctionList().end(); F != E; F++) { string cstr = F->getName().str(); - if (cstr.find("corruptIntData_8bit") != std::string::npos) { - func_corruptIntData_8bit =&*F; - } else if (cstr.find("corruptIntData_16bit") != std::string::npos) { - func_corruptIntData_16bit =&*F; - } else if (cstr.find("corruptIntData_32bit") != std::string::npos) { - func_corruptIntData_32bit =&*F; - } else if (cstr.find("corruptIntData_64bit") != std::string::npos) { + if (cstr.find("corruptIntData_64bit") != std::string::npos) { func_corruptIntData_64bit =&*F; - } else if (cstr.find("corruptPtr2Int_64bit") != std::string::npos) { func_corruptPtr2Int_64bit =&*F; } else if (cstr.find("corruptFloatData_32bit") != std::string::npos) { func_corruptFloatData_32bit =&*F; } else if (cstr.find("corruptFloatData_64bit") != std::string::npos) { func_corruptFloatData_64bit =&*F; - } else if (cstr.find("corruptIntAdr_8bit") != std::string::npos) { - func_corruptIntAdr_8bit =&*F; - } else if (cstr.find("corruptIntAdr_16bit") != std::string::npos) { - func_corruptIntAdr_16bit =&*F; - } else if (cstr.find("corruptIntAdr_32bit") != std::string::npos) { - func_corruptIntAdr_32bit =&*F; - } else if (cstr.find("corruptIntAdr_64bit") != std::string::npos) { - func_corruptIntAdr_64bit =&*F; - } else if (cstr.find("corruptFloatAdr_32bit") != std::string::npos) { - func_corruptFloatAdr_32bit =&*F; - } else if (cstr.find("corruptFloatAdr_64bit") != std::string::npos) { - func_corruptFloatAdr_64bit =&*F; - } - /* TODO: check for function viability */ + }/* TODO: check for function viability */ if (F->begin() != F->end()/* && viableFunction(cstr, flist) */) for (auto BB = F->begin(), BBe = F->end(); BB != BBe; BB++) sum += BB->size(); }/*end for*/ - assert(func_corruptIntData_8bit != NULL && func_corruptIntData_16bit != NULL - && func_corruptIntData_32bit != NULL && func_corruptIntData_64bit != NULL - && func_corruptPtr2Int_64bit != NULL && func_corruptFloatData_32bit != NULL - && func_corruptFloatData_64bit != NULL && func_corruptIntAdr_8bit != NULL - && func_corruptIntAdr_16bit != NULL && func_corruptIntAdr_32bit != NULL - && func_corruptIntAdr_64bit != NULL && func_corruptFloatAdr_32bit != NULL - && func_corruptFloatAdr_64bit != NULL); + assert(func_corruptIntData_64bit != NULL && func_corruptPtr2Int_64bit != NULL + && func_corruptFloatData_32bit != NULL && func_corruptFloatData_64bit != NULL); return sum; } @@ -1408,21 +702,17 @@ bool FlipIt::DynamicFaults::corruptInstruction(Instruction* I) { } bool FlipIt::DynamicFaults::injectFault(Instruction* I) { - bool ret = false; -#ifdef OLD_WAY - comment = ""; - injectionType = ""; -#endif + bool inj = false; + + comment = 0; injectionType = 0; - skipAmount = 0; - if (ctrl_err && injectControl(I)) { - ret = true; - //injectionType = "Control"; - } else if (arith_err && injectArithmetic(I)) { - ret = true; -#ifdef OLD_WAY - injectionType = "Arithmetic"; -#endif + if (ctrl_err && injectControl_NEW(I)) { + + inj = true; + + } else if (arith_err && injectArithmetic_NEW(I)) { + + inj = true; Value* tmp = I; if (isa(I)) { tmp = I->getOperand(0); // value @@ -1433,37 +723,24 @@ bool FlipIt::DynamicFaults::injectFault(Instruction* I) { || tmp->getType()->isDoubleTy()) { injectionType = ARITHMETIC_FP; } - } else if (ptr_err && injectPointer(I)) { - ret = true; -#ifdef OLD_WAY - injectionType = "Pointer"; -#endif + } else if (ptr_err && injectPointer_NEW(I)) { + inj = true; injectionType = POINTER; - } else if ( (ctrl_err || arith_err || ptr_err) && injectCall(I) ) { - ret = true; - } - /* - else { - errs() << "Warning: Didn't injection into \"" << *inst << "\"\n"; + } else if ( (ctrl_err || arith_err || ptr_err) && injectCall_NEW(I) ) { + inj = true; } - */ - if (ret) { + + + + + + if (inj) { // Site #, injection type, comment, inst logfile->logInst(faultIdx++, injectionType, comment, I); -#ifdef OLD_WAY - errs() << '#' << faultIdx++ << '\t' << injectionType << '\t' << comment << "\t"; - if (MDNode *N = I->getMetadata("dbg")) { - DILocation Loc(N); - unsigned line = Loc.getLineNumber(); - StringRef file = Loc.getFilename(); - //StringRef dir = Loc.getDirectory(); - errs() << /*dir << "/" <<*/ file << ":" << line << "\n"; - } else { - errs() << *I << '\n'; - } -#endif } - return ret; + + + return inj; } /****************************************************************************************/ diff --git a/src/pass/faults.h b/src/pass/faults.h index 5858f16..e735e53 100644 --- a/src/pass/faults.h +++ b/src/pass/faults.h @@ -49,17 +49,14 @@ #include #include -#include #include #include #include -#include -#include -#include +#include +#include #include #include - using namespace llvm; @@ -68,11 +65,13 @@ static cl::opt funcList("funcList", cl::desc("Name(s) of the function(s) static cl::opt configPath("config", cl::desc("Path to the FlipIt Config file"), cl::value_desc("/path/to/FlipIt.config"), cl::init("FlipIt.config")); static cl::opt siteProb("prob", cl::desc("Probability that instrution is faulty"), cl::value_desc("Any value [0,1)"), cl::init(1e-8), cl::ValueRequired); static cl::opt byte_val("byte", cl::desc("Which byte to consider for fault injection"), cl::value_desc("-1-7"), cl::init(-1), cl::ValueRequired); +static cl::opt bit_val("bit", cl::desc("Which bit to consider for fault injection"), cl::value_desc("-1-63"), cl::init(-1), cl::ValueRequired); static cl::opt singleInj("singleInj", cl::desc("Inject Error Only Once"), cl::value_desc("0/1"), cl::init(1), cl::ValueRequired); static cl::opt arith_err("arith", cl::desc("Inject Faults Into Arithmetic Instructions"), cl::value_desc("0/1"), cl::init(1), cl::ValueRequired); static cl::opt ctrl_err("ctrl", cl::desc("Inject Faults Into Control Instructions"), cl::value_desc("0/1"), cl::init(1), cl::ValueRequired); static cl::opt ptr_err("ptr", cl::desc("Inject Faults Into Pointer Instructions"), cl::value_desc("0/1"), cl::init(1), cl::ValueRequired); static cl::opt srcFile("srcFile", cl::desc("Name of the source file being compiled"), cl::value_desc("e.g. foo.c, foo.cpp, or foo.f90"), cl::init("UNKNOWN"), cl::ValueRequired); +static cl::opt stateFile("stateFile", cl::desc("Name of the state file being updated when compiled. Used to provide unique fault site indexes."), cl::value_desc("FlipItState"), cl::init("FlipItState"), cl::ValueRequired); #endif @@ -88,25 +87,27 @@ namespace FlipIt { std::string configPath; double siteProb; int byte_val; + int bit_val; int singleInj; bool arith_err; bool ctrl_err; bool ptr_err; std::string srcFile; + std::string stateFile; #endif public: static char ID; #ifdef COMPILE_PASS DynamicFaults(); - DynamicFaults(string funcList, string configPath, double siteProb, int byte_val, int singleInj, bool arith_err, bool ctrl_err, bool ptr_err, std::string srcFile, Module* M); + DynamicFaults(string funcList, string configPath, double siteProb, + int byte_val, int bit_val, int singleInj, bool arith_err, + bool ctrl_err, bool ptr_err, std::string srcFile, Module* M); #else DynamicFaults(Module* M); - DynamicFaults(string funcList, string configPath, double siteProb, int byte_val, int singleInj, bool arith_err, bool ctrl_err, bool ptr_err, std::string srcFile, Module* M); + DynamicFaults(string funcList, string configPath, double siteProb, int byte_val, int bit_val, int singleInj, bool arith_err, bool ctrl_err, bool ptr_err, std::string srcFile, std::string stateFile, Module* M); #endif - //~DynamicFaults() - // { finalize(); } virtual ~DynamicFaults() { finalize(); } virtual bool runOnModule(Module &M); @@ -117,27 +118,35 @@ namespace FlipIt { void init(); bool finalize(); std::vector splitAtSpace(std::string spltStr); + void splitAtSpace(); int selectArgument(CallInst* callInst); void readConfig(string path); - double getInstProb(Instruction* I); + Value* getInstProb(Instruction* I); std::string demangle(std::string name); - bool viableFunction(std::string name, std::vector flist); + bool viableFunction(std::string name, std::vector& flist); unsigned long updateStateFile(const char* stateFile, unsigned long sum); bool injectControl(Instruction* I); bool injectArithmetic(Instruction* I); bool injectPointer(Instruction* I); bool injectCall(Instruction* I); + + bool injectControl_NEW(Instruction* I); + bool injectArithmetic_NEW(Instruction* I); + bool injectPointer_NEW(Instruction* I); + bool injectCall_NEW(Instruction* I); + bool injectResult(Instruction* I); + bool injectInOperand(Instruction* I, int operand); + + bool inject_Store_Data(Instruction* I, CallInst* CallI); + bool inject_Compare(Instruction* I, CallInst* CallI); + bool inject_Generic(Instruction* I, CallInst* CallI, BasicBlock* BB); - bool inject_Store_Data(Instruction* I, std::vector args, CallInst* CallI); - bool inject_Compare(Instruction* I, std::vector args, CallInst* CallI); - bool inject_Generic(Instruction* I, std::vector args, CallInst* CallI, BasicBlock* BB); - - bool inject_Store_Ptr(Instruction* I, std::vector args, CallInst* CallI); - bool inject_Load_Ptr(Instruction* I, std::vector args, CallInst* CallI, BasicBlock::iterator BI, BasicBlock* BB); - bool inject_Alloc_Ptr(Instruction* I, std::vector args, CallInst* CallI, BasicBlock::iterator BI, BasicBlock* BB); - bool inject_Call(Instruction* I, std::vector args, CallInst* CallI, BasicBlock::iterator BI, BasicBlock* BB); - bool inject_GetElementPtr_Ptr(Instruction* I, std::vector args, CallInst* CallI, BasicBlock::iterator BI, BasicBlock* BB); + bool inject_Store_Ptr(Instruction* I, CallInst* CallI); + bool inject_Load_Ptr(Instruction* I, CallInst* CallI, BasicBlock* BB); + bool inject_Alloc_Ptr(Instruction* I, CallInst* CallI, BasicBlock* BB); + bool inject_Call(Instruction* I, CallInst* CallI, BasicBlock* BB); + bool inject_GetElementPtr_Ptr(Instruction* I, CallInst* CallI, BasicBlock* BB); unsigned long cacheFunctions(); bool injectFault(Instruction* I); @@ -160,17 +169,19 @@ namespace FlipIt { Value* func_corruptFloatAdr_64bit; // used for display and analysis - std::map funcProbs; - std::map instProbs; + Type* i64Ty; + std::vector args; + std::map byteVal; + std::map funcProbs; + std::map instProbs; int comment; int injectionType; - //string comment; - //string injectionType; std::stringstream strStream; unsigned int oldFaultIdx; unsigned int faultIdx; unsigned int displayIdx; - unsigned int skipAmount; + unsigned int parameter; + std::vector flist; };/*end class definition*/ }/*end namespace*/