From 7ca55b8202c04d906110e45032c8243ecaf28fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Berkay=20=C3=9Cr=C3=BCn?= Date: Mon, 4 Mar 2024 15:43:58 +0100 Subject: [PATCH 1/2] Variable length instructions for single faults --- controller.py | 3 --- goldenrun.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/controller.py b/controller.py index 5f564db..8c645a7 100755 --- a/controller.py +++ b/controller.py @@ -198,9 +198,6 @@ def build_fault_list(conf_list, combined_faults, ret_faults): for tcounter in build_ranges(faultdev["trigger_counter"]): for numbytes in build_ranges(faultdev["num_bytes"]): if isinstance(fmask, dict): - assert ( - wildcard_fault - ), "only wildcard faults can be evaluated, if fault.mask is a dict" assert ftype == detect_type( "instruction" ), "fault.type has to be 'instruction', if fault.mask is a dict" diff --git a/goldenrun.py b/goldenrun.py index c38dc81..8ece09d 100644 --- a/goldenrun.py +++ b/goldenrun.py @@ -108,6 +108,7 @@ def run_goldenrun( tbexec = pd.DataFrame(experiment["data"]["tbexec"]) tbinfo = pd.DataFrame(experiment["data"]["tbinfo"]) process_wildcard_faults(faultconfig, tbexec, tbinfo) + process_single_faults(faultconfig, tbexec, tbinfo) calculate_trigger_addresses(faultconfig, tbexec, tbinfo) faultconfig = checktriggers_in_tb(faultconfig, experiment["data"]) @@ -418,3 +419,45 @@ def process_wildcard_faults(faultconfig, tbexec, tbinfo): new_fault_entry["faultlist"] = [wildcard_faults[i]] new_fault_entry["delete"] = False faultconfig.append(new_fault_entry) + + +def process_single_faults(faultconfig, tbexec, tbinfo): + remove_list = [] + for faultentry in faultconfig: + for fault in faultentry["faultlist"]: + if not isinstance(fault.mask, dict): + continue + + tbinfo_tb_indexed = tbinfo.set_index("id") + for tb in tqdm(tbexec["tb"], leave=False): + tb_info_asm = tbinfo_tb_indexed.at[tb, "assembler"] + tb_info_total_size = tbinfo_tb_indexed.at[tb, "size"] + + tb_info_asm = [ + int(instr.split("]")[0], 16) + for instr in tb_info_asm.split("[ ")[1:] + ] + if fault.address not in tb_info_asm: + continue + + tb_info_size = list(numpy.diff(tb_info_asm)) + tb_info_size.append( + tb_info_total_size - sum(tb_info_size) + ) # calculate the last instr size + + fault_idx = tb_info_asm.index(fault.address) + + try: + fault.mask = fault.mask[str(tb_info_size[fault_idx])] + fault.num_bytes = tb_info_size[fault_idx] + except (ValueError, KeyError): + logger.info( + f"No matching fault mask could be found for fault entry {faultentry['index']}, " + f"removing the fault entry..." + ) + remove_list.append(faultentry) + + break + + for faultentry in remove_list: + faultconfig.remove(faultentry) From 1830d1f3a87267b0124cf11b1e97bc7a9ed9e1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Berkay=20=C3=9Cr=C3=BCn?= Date: Mon, 4 Mar 2024 16:39:00 +0100 Subject: [PATCH 2/2] Update readme for instr length dicts --- fault-readme.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/fault-readme.md b/fault-readme.md index 51bfcbb..a47619a 100644 --- a/fault-readme.md +++ b/fault-readme.md @@ -186,14 +186,14 @@ For example when you want to shift a bit mask, you can use the type "shift" as f The shift corresponds to a left shift. In the above case, the number 3 is subsequently shifted by 7, 8, 9 to the left (binary representation). Another example of a dictionary is the use of instruction width dependent fault masks. -This only works in combination with the wildcard mode, the instruction fault type, and the overwrite fault model. +This only works in combination with the instruction fault type and the overwrite fault model. Below is an example fault configuration. This example targets an ARM Cortex M4 processor. The scenario is to apply an instruction skip. Therefore, the fault_mask contains opcodes for a 16-bit and 32-bit NOP instruction. Note that the num_bytes must not be set as this changes depending on the targeted instruction. -Example: +Example 1: ``` { "fault_address" : ["*"], @@ -206,6 +206,18 @@ Example: } ``` +Example 2: +``` +{ + "fault_address" : [0x08000056], + "fault_type" : "instruction", + "fault_model" : "overwrite", + "fault_lifespan" : [100], + "fault_mask" : {"type": "dict", "dict": {"2": 0xbf00, "4": 0x8000f3af}}, + "trigger_address" : [0x08000040], + "trigger_counter" : [1] +} +``` ##### trigger_address Defines the trigger instruction, i.e., when this instruction has been executed, the faults (defined in fault mask) are inserted into the respective fault address. The trigger_address must be an executed instruction! For every fault address, there is a separate test, i.e., experiment.