Skip to content

How to Create a Custom Instruction or Register Selector

Sittipol (Phil) Tribunyatkul edited this page Aug 26, 2015 · 10 revisions

How to create a custom instruction selector

Before creating a custom instruction selector, you may need to think about the fault model first. Is it simulating a hardware fault, or is it injecting a software fault to test the behavior of the system under test. This is because instruction selectors/register selectors represents the fault model.

Usually following fields (string type) are required for an custom instruction selector. Note the content of these strings will be printed out in llfi.config.compiletime.txt in the targeting IR directory. These are used for user to collect information about the fault injection experiment and GUI, so that these are not mandatory.

  • failure_class = HardwareFault/API/Data/< custom class >/ ...
  • failure_mode = SpecifiedFunctions/BufferOverflow/DataCorruption/< custom mode >/...
  • targets = < function names >/< instruction names >/< custom targets >/...
  • injector = < fi_type >/ChangeValueInjector/ < custom injector >/...

For Hardware Faults, we need to create a class that is the child of class HardwareFIInstSelector. For Software Faults, we need inherit class SoftwareFIInstSelector.

###Hardware Fault Instruction Selector.

  1. Inherit class HardwareFIInstSelector

  2. Implement bool isInstFITarget(Instruction *inst) You are required to implement the bool isInstFITarget(Instruction *inst) in your class. The method returns true if the input inst is the intended fault injection targets. If the selection criteria is purely based on the characteristics of the specified instruction, this is good enough. However, if your selection criteria is based on the relative order of instructions (e.g. a instruction is fault injection target only when it is after a specific instruction), you (also) need to rewrite the getInitFIInsts() method. The selector can also accepts command line options through LLVM command line options.

  3. Implement void getCompileTimeInfo(std::map<std::string, std::string>& info) Another method: void getCompileTimeInfo(std::map<std::string, std::string>& info) is also required to be implemented. You need to assign content to following keys: failure_class, failure_mode, targets, and injector. Here is an example we used for llfiindex instruction selector:

info["failure_class"] = "HardwareFault"; //brief description of the instSeletor info["failure_mode"] = "SpecifiedLLFIIndex"; //brief description of the targets. Here the targets are defined in input.yaml. info["targets"] = ""; //brief description of the fi_type. Here the fi_type is defined in input.yaml. info["injector"] = "<fi_type>"; ``` For Hardware Faults, usually the input.yaml is already enough to describe the fault model, so we can simply label here (with whatever string you like) to let the user knows to refer to the input.yaml.

  1. Register the class with RegisterFIInstSelector(). In the registration, you also provide the name to find the selector.

  2. Build the llvm_passes/. Add the created file(s) to CMakeLists.txt in llvm_passes/. Go to < LLFI_DST_ROOT > and run make.

  3. Run passes with the custom instruction selector. You need to use the option -custominstselector -fiinstselectorname <name given in step 2> to invoke the custom instruction selector.

###Software Fault Instruction Selector

  1. Inherit SoftwareFIInstSelector

  2. Implement bool isInstFITarget(Instruction *inst) Same as Hardware Fault Instruction Selector

  3. Implement void getCompileTimeInfo(std::map<std::string, std::string>& info) For Software Fault Instruction Selectors, we may need more information here since the custom instruction selector may not be configurable through input.yaml, so that one can not have enough description about the fault model from input.yaml. In this case, it is programmer's responsibility to expose the description of the fault model and this method is where generate such information. Here is an example from a software fault instruction selector shipped with LLFI:

info["failure_class"] = "API"; info["failure_mode"] = "BufferOverflow"; info["targets"] = "fread()/fwrite()"; info["injector"] = "ChangeValueInjector"; ``` 4. Register the class with RegisterFIInstSelector(). In the registration, you also provide the name to find the selector.

  1. Build the llvm_passes/. Add the created file(s) to CMakeLists.txt in llvm_passes/. Go to < LLFI_DST_ROOT > and run make.

  2. Run passes with the custom instruction selector. You need to use the option -custominstselector -fiinstselectorname <name given in step 2> to invoke the custom instruction selector.

Note for both Hardware and Software Fault Instruction Selectors, info["injector"] is only used for the ease of user, LLFI won't select fault type (fi_type) depends on the content under this key.

There is a sample instruction selector in SampleFIInstselector.cpp, and a LLFI index based instruction selector in LLFIIndexFIInstSelector.cpp. Play with them first to get an idea.

[GUI] To get the custom instruction selector to show up in the LLFI GUI, add the name of the selector, exactly as registered, to the file LLFI_SRC_ROOT/gui/config/customInstruction_list.txt (for Hardware Fault) or LLFI_SRC_ROOT/gui/config/customSoftwareFault_list.txt (for Software Fault).

[FIDL] Alternatively, use the FIDL tool to generate a Custom Software Fault Injector and a Custom Instruction Selector instead.

How to create a custom register selector

  1. Under < LLFI_SRC_ROOT >/llvm_passes/, create a class that is the child of class HardwareFIRegSelector or class SoftwareFIRegSelector. You have to implement the bool isRegofInstFITarget(Value *reg, Instruction *inst) in your class. The method returns true if the input reg of inst is the intended fault injection targets.

  2. Register the class with RegisterFIRegSelector(). In the registration, you also provide the name to find the selector.

  3. Build the llvm_passes/. Add the created file(s) to CMakeLists.txt in llvm_passes/. Go to < LLFI_DST_ROOT > and run make.

  4. Run passes with the custom register selector. You need to use the option -customregselector -firegselectorname <name given in step 2> to invoke the custom register selector.

  5. There is a sample register selector in SampleFIRegSelector.cpp. Play it first to get an idea.

  6. [GUI] To get the custom register selector to show up in the LLFI GUI, add the name of the selector, exactly as registered, to the file LLFI_SRC_ROOT/gui/config/customRegister_list.txt (hardware injection only).

Clone this wiki locally