#ifndef __ADVANCED_MEMORY_IMPORTER_H__ #define __ADVANCED_MEMORY_IMPORTER_H__ #include #include #include "MemoryImporter.hpp" #include "util/llvmdisassembler/LLVMDisassembler.hpp" /** * A MemoryImporter that additionally imports Relyzer-style conditional branch * history, instruction opcodes, and a virtual duration = time2 - time1 + 1 * column (MariaDB 5.2+ only!) for fault-space pruning purposes. * * Initially this was implemented by directly passing through trace events to * the MemoryImporter, keeping a record of conditional jumps and opcodes, and * UPDATEing all inserted rows in a second pass when the MemoryImporter is * finished. * * Unfortunately, UPDATE is very slow, and keeping all information in memory * till the end doesn't scale indefinitely. Therefore the implementation now * delays passing memory access events upwards to the MemoryImporter only until * enough branch history is aggregated, and taps into Importer's database * operations with a set of new virtual functions that are called downwards. */ class AdvancedMemoryImporter : public MemoryImporter { llvm::OwningPtr binary; llvm::OwningPtr disas; bool m_last_was_conditional_branch; fail::guest_address_t m_ip_jump_not_taken; std::vector branches_taken; struct DelayedTraceEntry { fail::simtime_t curtime; instruction_count_t instr; Trace_Event ev; unsigned opcode; unsigned branches_before; }; std::deque delayed_entries; static const unsigned BRANCH_WINDOW_SIZE = 16; //!< increasing this requires changing the underlying data types unsigned m_cur_branchmask; void insert_delayed_entries(bool finalizing); public: AdvancedMemoryImporter() : m_last_was_conditional_branch(false) {} virtual std::string database_additional_columns(); virtual void database_insert_columns(std::string& sql, unsigned& num_columns); virtual bool database_insert_data(Trace_Event &ev, MYSQL_BIND *bind, unsigned num_columns, bool is_fake); virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr, Trace_Event &ev); virtual bool handle_mem_event(fail::simtime_t curtime, instruction_count_t instr, Trace_Event &ev); virtual bool trace_end_reached(); }; #endif