Giter VIP home page Giter VIP logo

fault-injector's Introduction

Fault Injector for Hardware Injection

This project is compact version of llfi. (https://github.com/DependableSystemsLab/LLFI)

LLFI is too old to work with the latest version of LLVM. So we have created a simple Fault Injection Tool that can run on the latest version of LLVM.

Dependency

LLVM 7.0.0 (or Later)

Build

All you need is an appropriately built 'opt' to use our tools.

Copy 'FaultInjector.cpp' to 'llvm/tools/opt'.
Insert 'FaultInjector.cpp' in 'llvm/tools/opt/CMakeLists.txt:add_llvm_tool.
Make directory 'llvm/build'
Move 'llvm/build'
Build your opt using cmake.

You can also use loadable library.
Ref: https://llvm.org/docs/WritingAnLLVMPass.html#quick-start-writing-hello-world

Test

Make test folder under 'llvm/build'.
Copy 'rtl-core.c' to 'llvm/build/test'.
Write your own test file (or our a.c).
Then run this command lines.

--------

clang -S -emit-llvm a.c
./../opt -faultinject a.ll -S -o b.ll
llc -filetype=obj b.ll -o b.obj

clang -S -emit-llvm rtl-core.c
llc -filetype=obj rtl-core.ll -o rtl-core.obj

clang rtl-core.obj b.obj

Example a.c profile

#include <stdio.h>

int main(int argc, char *argv[])
{
  int a = 0, b = 0;
  for (int i = 0; i < argc; i++) {
    b += i;
  }

  printf("%d", b);
}

If you use a command line such as ./a 1 1 1 1 1, you will get the following outputs.

15

15 = 0 + 1 + 2 + 3 + 4 + 5

[Fault Injector] RTL-Core Init!
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=04, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=03, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=06, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=07, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=04, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=03, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=06, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=07, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000002
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000002
[Fault Injector] trace: f_index=04, index=04, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=03, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000002
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=06, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000002
[Fault Injector] trace: f_index=04, index=07, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=04, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=03, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=06, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=07, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000004
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000004
[Fault Injector] trace: f_index=04, index=04, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=03, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000004
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=0000000A
[Fault Injector] trace: f_index=04, index=06, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000004
[Fault Injector] trace: f_index=04, index=07, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000005
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000005
[Fault Injector] trace: f_index=04, index=04, reg_num=-1, dependency=-1, opcode=   load, size=32, value=0000000A
[Fault Injector] trace: f_index=04, index=03, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000005
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=0000000F
[Fault Injector] trace: f_index=04, index=06, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000005
[Fault Injector] trace: f_index=04, index=07, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=08, reg_num=-1, dependency=-1, opcode=   load, size=32, value=0000000F
[Fault Injector] RTL-Core Finish!
[Fault Injector] determine=54

Follow index 05th.

[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=0000000A
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=0000000F

Example a.c Fault Inject

setting file.

run_fault_injection 1
count_of_determine 54

result file.

[Fault Injector] RTL-Core Init!
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=04, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=03, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=06, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=07, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=04, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000000
[Fault Injector] trace: f_index=04, index=03, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=06, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=07, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000002
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000002
[Fault Injector] trace: f_index=04, index=04, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000001
[Fault Injector] trace: f_index=04, index=03, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000002
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=06, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000002
[Fault Injector] trace: f_index=04, index=07, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=04, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=03, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=05, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=06, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000003
[Fault Injector] trace: f_index=04, index=07, reg_num=-1, dependency=-1, opcode=    add, size=32, value=00000004
[Fault Injector] inject_before: f_index=04, index=02, reg_num=-1, dependency=-1, opcode=   icmp, size=01, value=1
[Fault Injector]  inject_after: f_index=04, index=02, reg_num=-1, dependency=-1, opcode=   icmp, size=01, value=0
[Fault Injector] trace: f_index=04, index=01, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] trace: f_index=04, index=00, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000004
[Fault Injector] trace: f_index=04, index=08, reg_num=-1, dependency=-1, opcode=   load, size=32, value=00000006
[Fault Injector] RTL-Core Finish!
[Fault Injector] determine=38

When i (reg_num=07) was 4 , the control flow changed, and loop escaped.

6

insertDetermineLogicForRawFaultInjection

Before injection

define dso_local i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 {
  %3 = icmp sgt i32 %0, 0
  br i1 %3, label %7, label %4

; <label>:4:                                      ; preds = %7, %2
  %5 = phi i32 [ 0, %2 ], [ %10, %7 ]
  %6 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @"??_C@_02DPKJAMEF@?$CFd?$AA@", i64 0, i64 0), i32 %5)
  ret i32 0

; <label>:7:                                      ; preds = %2, %7
  %8 = phi i32 [ %11, %7 ], [ 0, %2 ]
  %9 = phi i32 [ %10, %7 ], [ 0, %2 ]
  tail call void @__marking_faultinject_int(i32 %9) #3
  %10 = add nuw nsw i32 %8, %9
  %11 = add nuw nsw i32 %8, 1
  %12 = icmp eq i32 %11, %0
  br i1 %12, label %4, label %7
}

After injection

define dso_local i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 {
  %xor_marker = alloca i32
  store i32 4, i32* %xor_marker
  %3 = icmp sgt i32 %0, 0
  br i1 %3, label %7, label %4

; <label>:4:                                      ; preds = %7, %2
  %5 = phi i32 [ 0, %2 ], [ %10, %7 ]
  %6 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @"??_C@_02DPKJAMEF@?$CFd?$AA@", i64 0, i64 0), i32 %5)
  ret i32 0

; <label>:7:                                      ; preds = %7, %2
  %8 = phi i32 [ %11, %7 ], [ 0, %2 ]
  %9 = phi i32 [ %10, %7 ], [ 0, %2 ]
  tail call void @__marking_faultinject_int(i32 %9) #3
  %xor_val = load i32, i32* %xor_marker
  %rfi = xor i32 %9, %xor_val
  store i32 0, i32* %xor_marker
  %10 = add nuw nsw i32 %8, %rfi
  %11 = add nuw nsw i32 %8, 1
  %12 = icmp eq i32 %11, %0
  br i1 %12, label %4, label %7
}

How to work?

0. Why are Pass and RTL separated?

It is very inefficient to provide a customized program based on user needs, so we provide RTL for profiling directly from the program.

1. LLVM Fault Injection Pass

The role of LLVM Fault Injection Pass is to find instructions or register to inject Fault and to link with runtime library core. Since the actual linking is done in the linker, the major role is to create the appropriate object file.

1.1. Inject fault-injection code

1.1.1. Select instructions and registers
1.1.2. Register bypassing and inject 'inject_fault#num' function
1.1.3. Insert 'fault_inject_trace' function

1.2. Insert meta functions

1.2.1. Insert 'fault_inject_init' function
1.2.2. Insert 'fault_inject_finish' function
1.2.3. Insert 'inject_fault#num' function

2. Runtime Library Core

The runtime library contains the core code that performs the actual injection operation and the log function that records various changes.

Run Options (RTL Options)

Select instruction

Select register

Select function

Select variable (require dependency-check pass)

About dependency-check pass, go to https://github.com/rollrat/runnable-llvm.

Select basic block

Control fault probability

Set zero probability for profile

Set drawing lots probability

Set an unconditional single injection per running

fault-injector's People

Contributors

rollrat avatar

Stargazers

 avatar

Watchers

 avatar  avatar

fault-injector's Issues

Fault injection not working on some sigma examples when after O2 optimization

#include <stdio.h>
| 2
.. (up a dir) | 3 extern void __marking_faultinject_ptr(int*);
</llvm-7.0.1.src/build/bin/ | 4
a.c | 5 int main(int argc, char argv[]) {
a.ll | 6 int a,b;
a.out
| 7 __marking_faultinject_ptr(&b);
b.c | 8 for (a = 0; a < argc; a++)
b.ll | 9 {
bubble.c | 10 b+=a;
c.ll | 11 }
llvm-lit* | 12 printf("%d", b);
llvm-tblgen* | 13 }
opt* |~

a

static void insertDetermineLogicForRawFaultInjection(Module &M, Function &F, Instruction *I, Instruction *T, std::mt19937& R) {
// Create XOR setter and xor operand resetter

// ENTRY:
// %xor_marker = alloca i32, align 4
// store i32 (0~31 random number), %xor_marker, align 4
// CORE:
// %t = xor %target, %xor_marker
// store i32 0, %xor_marker

// pick random bits
std::uniform_int_distribution<std::mt19937::result_type> dist(0, 31);
int loc = dist(R);

IntegerType *type = Type::getInt32Ty(M.getContext());
AllocaInst *xor_marker =
  new AllocaInst(type, M.getDataLayout().getProgramAddressSpace(),
    "xor_marker", &*F.getEntryBlock().begin());
//Value *num = ConstantInt::get(type, loc, true);
//new StoreInst(num, xor_marker, &*++F.getEntryBlock().begin());
//new CallInst()

CallInst *CI = CallInst::Create(M.getOrInsertFunction("__faultinject_xor_marker_caller", 
  FunctionType::get(type, false)), "", 
  &*++F.getEntryBlock().begin());
new StoreInst(CI, xor_marker, &*++F.getEntryBlock().begin());

// Create xor and resetter
Value *num_zero = ConstantInt::get(type, 0, true);
StoreInst *resetter = new StoreInst(num_zero, xor_marker, I->getNextNode());
LoadInst *val = new LoadInst(xor_marker, "xor_val", resetter);
BinaryOperator *fi = BinaryOperator::CreateXor(I, val, "rfi", val->getNextNode());

/*for (int i = 0; i < I->getNumOperands(); i++)
  if (I->getOperand(i) == T)
    I->setOperand(i, fi);*/

std::list<User *> inst_uses;
for (Value::user_iterator user_it = I->user_begin();
  user_it != I->user_end(); ++user_it) {
  User *user = *user_it;
  if (user != I && user != fi) inst_uses.push_back(user);
}
for (std::list<User *>::iterator use_it = inst_uses.begin();
  use_it != inst_uses.end(); ++use_it) {
  User *user = *use_it;
  user->replaceUsesOfWith(I, fi);
}

F.print(errs());

}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.