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. Change-Id: I159b2533932087087fb3049f4ff07a5f17a25a00
59 lines
2.2 KiB
C++
59 lines
2.2 KiB
C++
#ifndef __ADVANCED_MEMORY_IMPORTER_H__
|
|
#define __ADVANCED_MEMORY_IMPORTER_H__
|
|
|
|
#include <vector>
|
|
#include <deque>
|
|
#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<llvm::object::Binary> binary;
|
|
llvm::OwningPtr<fail::LLVMDisassembler> disas;
|
|
bool m_last_was_conditional_branch;
|
|
fail::guest_address_t m_ip_jump_not_taken;
|
|
std::vector<bool> branches_taken;
|
|
struct DelayedTraceEntry {
|
|
fail::simtime_t curtime;
|
|
instruction_count_t instr;
|
|
Trace_Event ev;
|
|
unsigned opcode;
|
|
unsigned branches_before;
|
|
};
|
|
std::deque<DelayedTraceEntry> 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
|