import-trace: introduce InstructionImporter
The InstructionImporter does disassemble the binary and generate read traces for every instruction byte executed. Change-Id: I6b8697c711c009e106ed733c74c6ff8f9bbf8ac5
This commit is contained in:
@ -48,6 +48,8 @@ void ElfReader::setup(const char* path) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_filename = std::string(path);
|
||||
|
||||
// Evaluate headers
|
||||
Elf32_Ehdr ehdr;
|
||||
Elf32_Shdr sec_hdr;
|
||||
|
||||
@ -75,7 +75,6 @@ namespace fail {
|
||||
*/
|
||||
|
||||
class ElfReader {
|
||||
|
||||
public:
|
||||
typedef ElfSymbol entry_t;
|
||||
typedef std::vector<entry_t> container_t;
|
||||
@ -153,9 +152,11 @@ namespace fail {
|
||||
container_t::const_iterator sec_begin() { return m_sectiontable.begin(); }
|
||||
container_t::const_iterator sec_end() { return m_sectiontable.end(); }
|
||||
|
||||
const std::string & getFilename() { return m_filename; }
|
||||
|
||||
private:
|
||||
Logger m_log;
|
||||
std::string m_filename;
|
||||
|
||||
void setup(const char*);
|
||||
int process_symboltable(int sect_num, FILE* fp);
|
||||
|
||||
@ -3,6 +3,32 @@ set(SRCS
|
||||
MemoryImporter.cc
|
||||
)
|
||||
|
||||
if (BUILD_LLVM_DISASSEMBLER)
|
||||
set(SRCS ${SRCS}
|
||||
InstructionImporter.cc
|
||||
)
|
||||
|
||||
include(FindLLVM)
|
||||
|
||||
# llvm-config does add -fno-exception to the command line. But this
|
||||
# breaks some boost libraries.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS} -fexceptions")
|
||||
endif(BUILD_LLVM_DISASSEMBLER)
|
||||
|
||||
|
||||
|
||||
add_executable(import-trace main.cc ${SRCS})
|
||||
target_link_libraries(import-trace ${PROTOBUF_LIBRARY} -lmysqlclient fail-util fail-sal fail-comm)
|
||||
|
||||
target_link_libraries(import-trace
|
||||
${PROTOBUF_LIBRARY}
|
||||
-lmysqlclient
|
||||
fail-util
|
||||
fail-comm
|
||||
fail-sal)
|
||||
|
||||
if (BUILD_LLVM_DISASSEMBLER)
|
||||
target_link_libraries(import-trace fail-llvmdisassembler fail-sal ${LLVM_LIBS} ${LLVM_LDFLAGS})
|
||||
endif (BUILD_LLVM_DISASSEMBLER)
|
||||
|
||||
|
||||
install(TARGETS import-trace RUNTIME DESTINATION bin)
|
||||
|
||||
@ -78,7 +78,8 @@ public:
|
||||
const Trace_Event &ev) = 0;
|
||||
|
||||
|
||||
void set_elf_file(fail::ElfReader *elf) { m_elf = elf; }
|
||||
void set_elf(fail::ElfReader *elf) { m_elf = elf; }
|
||||
|
||||
void set_memorymap(fail::MemoryMap *mm) { m_mm = mm; }
|
||||
void set_faultspace_rightmargin(char accesstype) { m_faultspace_rightmargin = accesstype; }
|
||||
void set_sanitychecks(bool enabled) { m_sanitychecks = enabled; }
|
||||
|
||||
80
tools/import-trace/InstructionImporter.cc
Normal file
80
tools/import-trace/InstructionImporter.cc
Normal file
@ -0,0 +1,80 @@
|
||||
#ifndef __puma
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include "InstructionImporter.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
using namespace fail;
|
||||
|
||||
|
||||
static Logger LOG("InstructionImporter");
|
||||
|
||||
bool InstructionImporter::handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||
const Trace_Event &ev) {
|
||||
if (!binary) {
|
||||
/* Disassemble the binary if necessary */
|
||||
llvm::InitializeAllTargetInfos();
|
||||
llvm::InitializeAllTargetMCs();
|
||||
llvm::InitializeAllDisassemblers();
|
||||
|
||||
if (error_code ec = createBinary(m_elf->getFilename(), binary)) {
|
||||
LOG << m_elf->getFilename() << "': " << ec.message() << ".\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectFile *obj = dyn_cast<ObjectFile>(binary.get());
|
||||
|
||||
disas.reset(new LLVMDisassembler(obj));
|
||||
disas->disassemble();
|
||||
LLVMDisassembler::InstrMap &instr_map = disas->getInstrMap();
|
||||
LOG << "instructions disassembled: " << instr_map.size() << " Triple: " << disas->GetTriple() << std::endl;
|
||||
}
|
||||
|
||||
const LLVMDisassembler::InstrMap &instr_map = disas->getInstrMap();
|
||||
const LLVMDisassembler::Instr &opcode = instr_map.at(ev.ip());
|
||||
|
||||
address_t from = ev.ip(), to = ev.ip() + opcode.length;
|
||||
|
||||
// Iterate over all accessed bytes
|
||||
for (address_t data_address = from; data_address < to; ++data_address) {
|
||||
// skip events outside a possibly supplied memory map
|
||||
if (m_mm && !m_mm->isMatching(data_address)) {
|
||||
continue;
|
||||
}
|
||||
margin_info_t left_margin = getOpenEC(data_address);
|
||||
margin_info_t right_margin;
|
||||
right_margin.time = curtime;
|
||||
right_margin.dyninstr = instr; // !< The current instruction
|
||||
right_margin.ip = ev.ip();
|
||||
|
||||
// skip zero-sized intervals: these can occur when an instruction
|
||||
// accesses a memory location more than once (e.g., INC, CMPXCHG)
|
||||
if (left_margin.dyninstr > right_margin.dyninstr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// we now have an interval-terminating R/W event to the memaddr
|
||||
// we're currently looking at; the EC is defined by
|
||||
// data_address, dynamic instruction start/end, the absolute PC at
|
||||
// the end, and time start/end
|
||||
access_info_t access;
|
||||
access.access_type = 'R'; // instruction fetch is always a read
|
||||
access.data_address = data_address;
|
||||
access.data_width = 1; // exactly one byte
|
||||
if (!add_trace_event(left_margin, right_margin, access)) {
|
||||
LOG << "add_trace_event failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// next interval must start at next instruction; the aforementioned
|
||||
// skipping mechanism wouldn't work otherwise
|
||||
newOpenEC(data_address, curtime + 1, instr + 1, ev.ip());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif // !__puma
|
||||
27
tools/import-trace/InstructionImporter.hpp
Normal file
27
tools/import-trace/InstructionImporter.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef __INSTRUCTION_IMPORTER_H__
|
||||
#define __INSTRUCTION_IMPORTER_H__
|
||||
|
||||
#include "Importer.hpp"
|
||||
|
||||
#ifndef __puma
|
||||
#include "util/llvmdisassembler/LLVMDisassembler.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
class InstructionImporter : public Importer {
|
||||
#ifndef __puma
|
||||
llvm::OwningPtr<llvm::object::Binary> binary;
|
||||
llvm::OwningPtr<fail::LLVMDisassembler> disas;
|
||||
#endif
|
||||
|
||||
public:
|
||||
virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||
const Trace_Event &ev);
|
||||
virtual bool handle_mem_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||
const Trace_Event &ev) {
|
||||
/* ignore on purpose */
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,5 +1,3 @@
|
||||
#include "util/optionparser/optionparser.h"
|
||||
#include "util/optionparser/optionparser_ext.hpp"
|
||||
#include "util/CommandLine.hpp"
|
||||
#include "util/Database.hpp"
|
||||
#include "util/ElfReader.hpp"
|
||||
@ -8,9 +6,12 @@
|
||||
#include "util/Logger.hpp"
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "MemoryImporter.hpp"
|
||||
|
||||
#ifdef BUILD_LLVM_DISASSEMBLER
|
||||
#include "InstructionImporter.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
using namespace fail;
|
||||
using std::cerr;
|
||||
@ -118,9 +119,14 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
if (cmd[IMPORTER].count() > 0) {
|
||||
std::string imp(cmd[IMPORTER].first()->arg);
|
||||
if (imp == "BasicImporter" || imp == "MemoryImporter") {
|
||||
if (imp == "BasicImporter" || imp == "MemoryImporter" || imp == "memory" || imp == "mem") {
|
||||
LOG << "Using MemoryImporter" << endl;
|
||||
importer = new MemoryImporter();
|
||||
#ifdef BUILD_LLVM_DISASSEMBLER
|
||||
} else if (imp == "InstructionImporter" || imp == "code") {
|
||||
LOG << "Using InstructionImporter" << endl;
|
||||
importer = new InstructionImporter();
|
||||
#endif
|
||||
} else {
|
||||
LOG << "Unkown import method: " << imp << endl;
|
||||
exit(-1);
|
||||
@ -160,7 +166,7 @@ int main(int argc, char *argv[]) {
|
||||
if (cmd[ELF_FILE].count() > 0) {
|
||||
elf_file = new ElfReader(cmd[ELF_FILE].first()->arg);
|
||||
}
|
||||
importer->set_elf_file(elf_file);
|
||||
importer->set_elf(elf_file);
|
||||
|
||||
if (cmd[MEMORYMAP].count() > 0) {
|
||||
memorymap = new MemoryMap();
|
||||
|
||||
Reference in New Issue
Block a user