diff --git a/src/experiments/l4-sys/CMakeLists.txt b/src/experiments/l4-sys/CMakeLists.txt index 3dca273b..a2240579 100644 --- a/src/experiments/l4-sys/CMakeLists.txt +++ b/src/experiments/l4-sys/CMakeLists.txt @@ -10,6 +10,7 @@ set(MY_PROTOS ) set(MY_CAMPAIGN_SRCS + aluinstr.hpp experiment.hpp experiment.cc campaign.hpp diff --git a/src/experiments/l4-sys/aluinstr.hpp b/src/experiments/l4-sys/aluinstr.hpp index 361e6cd1..60d828bd 100644 --- a/src/experiments/l4-sys/aluinstr.hpp +++ b/src/experiments/l4-sys/aluinstr.hpp @@ -1,12 +1,14 @@ #ifndef __L4SYS_ALUINSTR_HPP__ #define __L4SYS_ALUINSTR_HPP__ +#if 0 /** * Forward declaration of the Bochs instruction decode table. * This is necessary because, inconveniently, it is not declared in a header file. */ #include "cpu/fetchdecode.h" static const BxOpcodeInfo_t *BxOpcodeInfo32; +#endif /** * Trying to order X86 ALU instructions. @@ -54,7 +56,10 @@ struct BochsALUInstr { Bit8u opcode; /** * the reg part of the modr/m field (known as nnn in bxInstruction_c) - * A value of 8 or higher marks this field unused. + * it is used to + * a) further subdivide the functionality of a given opcode + * b) specify a register the instruction is supposed to use + * In this class, a value of 8 or higher marks this field unused. */ Bit8u reg; /** @@ -63,7 +68,7 @@ struct BochsALUInstr { * to their opcode. It is necessary to store this separately for * several reasons, one being the ability to separate * ALU input latch faults from ALU instruction latch faults. - * A value of 8 or higher marks this field unused. + * In this class, a value of 8 or higher marks this field unused. */ Bit8u opcodeRegisterOffset; /** @@ -141,90 +146,77 @@ const BochsALUInstr aluInstructions [] = { #undef SHIFTOPS /* --- \\\ SHIFT OPERATIONS /// --- */ - /** - * - * The remaining instructions, roughly ordered, - * in the form of a (probably obsolete) experiment method - * /** - * Assigns a given opcode a class of ALU instructions - * @param opcode the opcode to examine - * @returns an enum AluClass object + /* --- /// BINARY OPERATIONS \\\ --- */ - X86AluClass isALUInstruction(unsigned opcode); - * - * X86AluClass L4SysExperiment::isALUInstruction(unsigned opcode) { - switch (opcode) { - case BX_IA_ADC_EbGb: - case BX_IA_ADC_EdGd: - case BX_IA_ADC_EwGw: - case BX_IA_ADD_EbGb: - case BX_IA_ADD_EdGd: - case BX_IA_ADD_EwGw: - case BX_IA_AND_EbGb: - case BX_IA_AND_EdGd: - case BX_IA_AND_EwGw: - case BX_IA_CMP_EbGb: - case BX_IA_CMP_EdGd: - case BX_IA_CMP_EwGw: - case BX_IA_OR_EbGb: - case BX_IA_OR_EdGd: - case BX_IA_OR_EwGw: - case BX_IA_SBB_EbGb: - case BX_IA_SBB_EdGd: - case BX_IA_SBB_EwGw: - case BX_IA_SUB_EbGb: - case BX_IA_SUB_EdGd: - case BX_IA_SUB_EwGw: - case BX_IA_XOR_EbGb: - case BX_IA_XOR_EdGd: - case BX_IA_XOR_EwGw: - case BX_IA_ADC_ALIb: - case BX_IA_ADC_AXIw: - case BX_IA_ADC_EAXId: - case BX_IA_ADD_EbIb: - case BX_IA_OR_EbIb: - case BX_IA_ADC_EbIb: - case BX_IA_SBB_EbIb: - case BX_IA_AND_EbIb: - case BX_IA_SUB_EbIb: - case BX_IA_XOR_EbIb: - case BX_IA_CMP_EbIb: - case BX_IA_ADD_EwIw: - case BX_IA_OR_EwIw: - case BX_IA_ADC_EwIw: - case BX_IA_SBB_EwIw: - case BX_IA_AND_EwIw: - case BX_IA_SUB_EwIw: - case BX_IA_XOR_EwIw: - case BX_IA_CMP_EwIw: - case BX_IA_ADD_EdId: - case BX_IA_OR_EdId: - case BX_IA_ADC_EdId: - case BX_IA_SBB_EdId: - case BX_IA_AND_EdId: - case BX_IA_SUB_EdId: - case BX_IA_XOR_EdId: - case BX_IA_CMP_EdId: - case BX_IA_ADC_GbEb: - case BX_IA_ADC_GwEw: - case BX_IA_ADC_GdEd: - case BX_IA_ADD_ALIb: - case BX_IA_ADD_AXIw: - case BX_IA_ADD_EAXId: - case BX_IA_ADD_GbEb: - case BX_IA_ADD_GwEw: - case BX_IA_ADD_GdEd: - case BX_IA_AND_ALIb: - case BX_IA_AND_AXIw: - case BX_IA_AND_EAXId: - case BX_IA_AND_GbEb: - case BX_IA_AND_GwEw: - case BX_IA_AND_GdEd: - default: - return ALU_UNDEF; - } -} - * - */ + // reg, immediate + + // a macro to reduce copy-paste overhead +#define BINOPS(IACODE, OPCODE8, OPCODE16) \ + { BX_IA_##IACODE##_ALIb, OPCODE8, 8, 8, ALU_IMM8_REG }, \ + { BX_IA_##IACODE##_AXIw, OPCODE16, 8, 8, ALU_IMM16_REG }, \ + { BX_IA_##IACODE##_EAXId, OPCODE16, 8, 8, ALU_IMM32_REG } + + // register ax, immediate + BINOPS(ADC, 0x14, 0x15), + BINOPS(ADD, 0x04, 0x05), + BINOPS(AND, 0x24, 0x25), + BINOPS(CMP, 0x3C, 0x3D), + BINOPS(OR, 0x0C, 0x0D), + BINOPS(SBB, 0x1C, 0x1D), + BINOPS(SUB, 0x2C, 0x2D), + BINOPS(XOR, 0x34, 0x35), +#undef BINOPS + + // a macro to reduce copy-paste overhead +#define BINOPS(IACODE, OPCODE8, OPCODE16) \ + { BX_IA_##IACODE##_EbGb, OPCODE8, 7, 8, ALU_IMM8_RM8 }, \ + { BX_IA_##IACODE##_EwGw, OPCODE16, 7, 8, ALU_IMM16_RM16 }, \ + { BX_IA_##IACODE##_EdGd, OPCODE16, 7, 8, ALU_IMM32_RM32 } + // r/m, arbitrary register + BINOPS(ADC, 0x10, 0x11), + BINOPS(ADD, 0x00, 0x01), + BINOPS(AND, 0x20, 0x21), + BINOPS(CMP, 0x38, 0x39), + BINOPS(OR, 0x08, 0x09), + BINOPS(SBB, 0x18, 0x19), + BINOPS(SUB, 0x28, 0x29), + BINOPS(XOR, 0x30, 0x31), +#undef BINOPS + +#define BINOPS(IACODE, OPCODE8, OPCODE16) \ + { BX_IA_##IACODE##_GbEb, OPCODE8, 7, 8, ALU_IMM8_RM8 }, \ + { BX_IA_##IACODE##_GwEw, OPCODE16, 7, 8, ALU_IMM16_RM16 }, \ + { BX_IA_##IACODE##_GdEd, OPCODE16, 7, 8, ALU_IMM32_RM32 } + // arbitrary register, r/m + BINOPS(ADC, 0x12, 0x13), + BINOPS(ADD, 0x02, 0x03), + BINOPS(AND, 0x22, 0x23), + BINOPS(CMP, 0x3a, 0x3b), + BINOPS(OR, 0x0a, 0x0b), + BINOPS(SBB, 0x1a, 0x1b), + BINOPS(SUB, 0x2a, 0x2b), + BINOPS(XOR, 0x32, 0x33), +#undef BINOPS + + // a macro to reduce copy-paste overhead +#define BINOPS(OPCODE, WDE, WDI, CLASS) \ + { BX_IA_ADC_E##WDE##I##WDI, OPCODE, 2, 8, CLASS }, \ + { BX_IA_ADD_E##WDE##I##WDI, OPCODE, 0, 8, CLASS }, \ + { BX_IA_AND_E##WDE##I##WDI, OPCODE, 4, 8, CLASS }, \ + { BX_IA_CMP_E##WDE##I##WDI, OPCODE, 7, 8, CLASS }, \ + { BX_IA_OR_E##WDE##I##WDI, OPCODE, 1, 8, CLASS }, \ + { BX_IA_SBB_E##WDE##I##WDI, OPCODE, 3, 8, CLASS }, \ + { BX_IA_SUB_E##WDE##I##WDI, OPCODE, 5, 8, CLASS }, \ + { BX_IA_XOR_E##WDE##I##WDI, OPCODE, 6, 8, CLASS } + + BINOPS(80, b, b, ALU_IMM8_RM8), + BINOPS(81, w, w, ALU_IMM16_RM16), + BINOPS(81, d, d, ALU_IMM32_RM32), + BINOPS(83, w, w, ALU_IMM8_RM16), + BINOPS(83, d, d, ALU_IMM8_RM32), +#undef BINOPS + + /* --- \\\ BINARY OPERATIONS /// --- */ }; + #endif // __L4SYS_ALUINSTR_HPP__ diff --git a/src/experiments/l4-sys/campaign.cc b/src/experiments/l4-sys/campaign.cc index bcecac67..3bf46b99 100644 --- a/src/experiments/l4-sys/campaign.cc +++ b/src/experiments/l4-sys/campaign.cc @@ -63,7 +63,7 @@ bool L4SysCampaign::run() { srand(time(NULL)); for (int i = 0; i < 25; ++i) { L4SysExperimentData *d = new L4SysExperimentData; - d->msg.set_exp_type(d->msg.GPRFLIP); + d->msg.set_exp_type(d->msg.IDCFLIP); // modify for a random instruction int instr_offset = rand() % L4SYS_NUMINSTR; d->msg.set_instr_offset(instr_offset); diff --git a/src/experiments/l4-sys/experiment.cc b/src/experiments/l4-sys/experiment.cc index caf794d5..a3881e46 100644 --- a/src/experiments/l4-sys/experiment.cc +++ b/src/experiments/l4-sys/experiment.cc @@ -20,10 +20,6 @@ #include "l4sys.pb.h" -// FIXME libudis86 test -- remove me -#include -void foo() { ud_t x; ud_init(&x); } - using namespace std; using namespace fail; @@ -160,34 +156,24 @@ bool L4SysExperiment::run() { log << "startup" << endl; - struct stat teststruct; +#if PREPARATION_STEP == 1 // STEP 1: run until interesting function starts, and save state - if (stat(L4SYS_STATE_FOLDER, &teststruct) == -1) { - bp.setWatchInstructionPointer(L4SYS_FUNC_ENTRY); - simulator.addListenerAndResume(&bp); - - log << "test function entry reached, saving state" << endl; - log << "EIP = " << hex << bp.getTriggerInstructionPointer() << " or " - << simulator.getRegisterManager().getInstructionPointer() - << endl; - simulator.save(L4SYS_STATE_FOLDER); - } + bp.setWatchInstructionPointer(L4SYS_FUNC_ENTRY); + simulator.addListenerAndResume(&bp); + log << "test function entry reached, saving state" << endl; + log << "EIP = " << hex << bp.getTriggerInstructionPointer() << " or " + << simulator.getRegisterManager().getInstructionPointer() + << endl; + simulator.save(L4SYS_STATE_FOLDER); +#elif PREPARATION_STEP == 2 // STEP 2: determine instructions executed -#ifdef PREPARE_EXPERIMENT - log << "restoring state" << endl; - simulator.restore(L4SYS_STATE_FOLDER); - log << "EIP = " << hex - << simulator.getRegisterManager().getInstructionPointer() - << endl; - // make sure the timer interrupt doesn't disturb us - simulator.addSuppressedInterrupt(0); - - int count; - int ul = 0, kernel = 0; + // count the first instruction which has already been executed + int count = 1; + int ul = 1, kernel = 0; bp.setWatchInstructionPointer(ANY_ADDR); - for (count = 0; bp.getTriggerInstructionPointer() != L4SYS_FUNC_EXIT; ++count) { + for (; bp.getTriggerInstructionPointer() != L4SYS_FUNC_EXIT; ++count) { simulator.addListenerAndResume(&bp); if(bp.getTriggerInstructionPointer() < 0xC0000000) { ul++; @@ -198,7 +184,35 @@ bool L4SysExperiment::run() { } log << "test function calculation position reached after " << dec << count << " instructions; " << "ul: " << ul << ", kernel: " << kernel << endl; -#else +#elif PREPARATION_STEP == 3 + // STEP 3: determine the output of a "golden run" + log << "restoring state" << endl; + simulator.restore(L4SYS_STATE_FOLDER); + log << "EIP = " << hex + << simulator.getRegisterManager().getInstructionPointer() + << endl; + + ofstream golden_run_file(L4SYS_CORRECT_OUTPUT); + bp.setWatchInstructionPointer(L4SYS_FUNC_EXIT); + bp.setCounter(L4SYS_ITERATION_COUNT); + simulator.addListener(&bp); + BaseListener* ev = waitIOOrOther(true); + if (ev == &bp) { + golden_run.assign(output.c_str()); + golden_run_file << output.c_str(); + log << "Output successfully logged!" << endl; + } else { + log + << "Obviously, there is some trouble with the events registered - aborting simulation!" + << endl; + golden_run_file.close(); + simulator.terminate(10); + } + simulator.clearListeners(); + bp.setCounter(1); + log << "saving output generated during normal execution" << endl; + golden_run_file.close(); + #if 0 // the files currently get too big. /* I do not really have a clever idea to solve this. @@ -260,38 +274,13 @@ bool L4SysExperiment::run() { } #endif - // STEP 3: determine the output of a "golden run" - if (stat(L4SYS_CORRECT_OUTPUT, &teststruct) == -1) { - log << "restoring state" << endl; - simulator.restore(L4SYS_STATE_FOLDER); - log << "EIP = " << hex - << simulator.getRegisterManager().getInstructionPointer() - << endl; - - // make sure the timer interrupt doesn't disturb us - simulator.addSuppressedInterrupt(0); - - ofstream golden_run_file(L4SYS_CORRECT_OUTPUT); - bp.setWatchInstructionPointer(L4SYS_FUNC_EXIT); - bp.setCounter(L4SYS_ITERATION_COUNT); - simulator.addListener(&bp); - BaseListener* ev = waitIOOrOther(true); - if (ev == &bp) { - golden_run.assign(output.c_str()); - golden_run_file << output.c_str(); - log << "Output successfully logged!" << endl; - } else { - log - << "Obviously, there is some trouble with the events registered - aborting simulation!" - << endl; - golden_run_file.close(); - simulator.terminate(10); - } - simulator.clearListeners(); - bp.setCounter(1); - log << "saving output generated during normal execution" << endl; - golden_run_file.close(); - } else { +#elif PREPARATION_STEP == 0 + // LAST STEP: The actual experiment. + struct stat teststruct; + if (stat(L4SYS_STATE_FOLDER, &teststruct) == -1 || stat(L4SYS_CORRECT_OUTPUT, &teststruct) == -1) { + log << "Important data missing - call \"prepare\" first." << endl; + simulator.terminate(1); + } ifstream golden_run_file(L4SYS_CORRECT_OUTPUT); golden_run.reserve(teststruct.st_size); @@ -303,9 +292,7 @@ bool L4SysExperiment::run() { //the generated output probably has a similar length output.reserve(teststruct.st_size); - } - // STEP 4: The actual experiment. log << "restoring state" << endl; simulator.restore(L4SYS_STATE_FOLDER); @@ -366,7 +353,7 @@ bool L4SysExperiment::run() { // this is a twisted one // initial definitions - bxICacheEntry_c *cache_entry = simulator.getCPUContext()->getICacheEntry(); + bxICacheEntry_c *cache_entry = simulator.getICacheEntry(); unsigned length_in_bits = cache_entry->i->ilen() << 3; // get the instruction in plain text in inject the error there diff --git a/src/experiments/l4-sys/experiment.hpp b/src/experiments/l4-sys/experiment.hpp index bea47e1c..70d853aa 100644 --- a/src/experiments/l4-sys/experiment.hpp +++ b/src/experiments/l4-sys/experiment.hpp @@ -6,8 +6,7 @@ #include "efw/ExperimentFlow.hpp" #include "efw/JobClient.hpp" #include "util/Logger.hpp" -// not implemented yet -// #include "aluinstr.hpp" +#include "aluinstr.hpp" class L4SysExperimentData; diff --git a/src/experiments/l4-sys/experimentInfo.hpp b/src/experiments/l4-sys/experimentInfo.hpp index 88b968f5..ddd91895 100644 --- a/src/experiments/l4-sys/experimentInfo.hpp +++ b/src/experiments/l4-sys/experimentInfo.hpp @@ -6,9 +6,10 @@ // the bounds of the program #define L4SYS_ADDRESS_SPACE 0x203d000 -#define L4SYS_FUNC_ENTRY 0x1000400 -#define L4SYS_FUNC_EXIT 0x10005b0 -#define L4SYS_NUMINSTR 56052774 +#define L4SYS_FUNC_ENTRY 0x10025ca +#define L4SYS_FUNC_EXIT 0x1002810 +#define L4SYS_NUMINSTR 83084798 +// kernel: 3599694, userland: 79485104 #define L4SYS_ITERATION_COUNT 1 @@ -20,6 +21,8 @@ // flags #define HEADLESS_EXPERIMENT -//#define PREPARE_EXPERIMENT +// 0 - preparation complete +// >0 - next step to execute +#define PREPARATION_STEP 3 #endif // __EXPERIMENT_INFO_HPP__