import-trace: introduce RandomJumpImporter
The random jump importer defines trace events, that indicate all
possible jumps into a specific instruction range. The region where
jumps should start can be defined by a memory map given with
--jump-from. For each instruction declared in that memory range, all
possible jumps to a memory region specified by with --jump-to are
inserted. The target of the jump is saved in the data_address
field. So all database tools work as expected.
for each event E \in region(--jump-from):
foreach Instruction in region(--jump-to):
insert_trace(injection_instr = E.IP(), data_address = Instruction.addr)
Change-Id: Ie163968acae47fc6c946fc77774c47ee07950bab
This commit is contained in:
@ -7,6 +7,7 @@ if (BUILD_LLVM_DISASSEMBLER)
|
|||||||
set(SRCS ${SRCS}
|
set(SRCS ${SRCS}
|
||||||
InstructionImporter.cc
|
InstructionImporter.cc
|
||||||
RegisterImporter.cc
|
RegisterImporter.cc
|
||||||
|
RandomJumpImporter.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
include(FindLLVM)
|
include(FindLLVM)
|
||||||
|
|||||||
132
tools/import-trace/RandomJumpImporter.cc
Normal file
132
tools/import-trace/RandomJumpImporter.cc
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#ifndef __puma
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include "util/Logger.hpp"
|
||||||
|
#include "RandomJumpImporter.hpp"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
using namespace llvm::object;
|
||||||
|
using namespace fail;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static Logger LOG("RandomJumpImporter");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function that can be used to add command line options
|
||||||
|
* to the campaign
|
||||||
|
*/
|
||||||
|
bool RandomJumpImporter::cb_commandline_init() {
|
||||||
|
CommandLine &cmd = CommandLine::Inst();
|
||||||
|
|
||||||
|
FROM = cmd.addOption("", "jump-from", Arg::Required,
|
||||||
|
"--jump-from\t RandomJump: Which addresses should be jumped from\n");
|
||||||
|
TO = cmd.addOption("", "jump-to", Arg::Required,
|
||||||
|
"--jump-to\t RandomJump: Where to jump (a memory map>\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RandomJumpImporter::handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev) {
|
||||||
|
if (!binary) {
|
||||||
|
// Parse command line again, for jump-from and jump-to
|
||||||
|
// operations
|
||||||
|
CommandLine &cmd = CommandLine::Inst();
|
||||||
|
if (!cmd.parse()) {
|
||||||
|
std::cerr << "Error parsing arguments." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read FROM memory file
|
||||||
|
if (cmd[FROM].count() > 0) {
|
||||||
|
m_mm_from = new MemoryMap();
|
||||||
|
for (option::Option *o = cmd[FROM]; o; o = o->next()) {
|
||||||
|
if (!m_mm_from->readFromFile(o->arg)) {
|
||||||
|
LOG << "failed to load memorymap " << o->arg << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd[TO].count() > 0) {
|
||||||
|
m_mm_to = new MemoryMap();
|
||||||
|
for (option::Option *o = cmd[TO]; o; o = o->next()) {
|
||||||
|
if (!m_mm_to->readFromFile(o->arg)) {
|
||||||
|
LOG << "failed to load memorymap " << o->arg << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG << "Please give at least one --jump-to memory map" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* Collect all addresses we want to jump to */
|
||||||
|
for (LLVMDisassembler::InstrMap::const_iterator instr = instr_map.begin();
|
||||||
|
instr != instr_map.end(); ++instr) {
|
||||||
|
if (m_mm_to->isMatching(instr->first)) {
|
||||||
|
m_jump_to_addresses.push_back(instr->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG << "we will jump to " << m_jump_to_addresses.size() << " addresses" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// skip events that are outside the memory map. -m instruction map
|
||||||
|
if (m_mm && !m_mm->isMatching(ev.ip())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip events that are outside the --jump-from memory map.
|
||||||
|
if (!m_mm_from->isMatching(ev.ip())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (std::vector<guest_address_t>::const_iterator it = m_jump_to_addresses.begin();
|
||||||
|
it != m_jump_to_addresses.end(); ++it) {
|
||||||
|
guest_address_t to_addr = *it;
|
||||||
|
/* Do not add a jump to the same instruction */
|
||||||
|
if (to_addr == ev.ip())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
margin_info_t margin;
|
||||||
|
margin.time = curtime;
|
||||||
|
margin.dyninstr = instr; // !< The current instruction
|
||||||
|
margin.ip = ev.ip();
|
||||||
|
|
||||||
|
// 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 = to_addr;
|
||||||
|
access.data_width = 4; // exactly one byte
|
||||||
|
if (!add_trace_event(margin, margin, access)) {
|
||||||
|
LOG << "add_trace_event failed" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !__puma
|
||||||
43
tools/import-trace/RandomJumpImporter.hpp
Normal file
43
tools/import-trace/RandomJumpImporter.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef __RANDOM_JUMP_IMPORTER_H__
|
||||||
|
#define __RANDOM_JUMP_IMPORTER_H__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "util/CommandLine.hpp"
|
||||||
|
#include "Importer.hpp"
|
||||||
|
|
||||||
|
#ifndef __puma
|
||||||
|
#include "util/llvmdisassembler/LLVMDisassembler.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
class RandomJumpImporter : public Importer {
|
||||||
|
#ifndef __puma
|
||||||
|
llvm::OwningPtr<llvm::object::Binary> binary;
|
||||||
|
llvm::OwningPtr<fail::LLVMDisassembler> disas;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fail::CommandLine::option_handle FROM, TO;
|
||||||
|
|
||||||
|
fail::MemoryMap *m_mm_from, *m_mm_to;
|
||||||
|
std::vector<fail::guest_address_t> m_jump_to_addresses;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Callback function that can be used to add command line options
|
||||||
|
* to the campaign
|
||||||
|
*/
|
||||||
|
virtual bool cb_commandline_init();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void open_unused_ec_intervals() {
|
||||||
|
/* empty, Memory Map has a different meaning in this importer */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -11,6 +11,7 @@
|
|||||||
#ifdef BUILD_LLVM_DISASSEMBLER
|
#ifdef BUILD_LLVM_DISASSEMBLER
|
||||||
#include "InstructionImporter.hpp"
|
#include "InstructionImporter.hpp"
|
||||||
#include "RegisterImporter.hpp"
|
#include "RegisterImporter.hpp"
|
||||||
|
#include "RandomJumpImporter.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -127,9 +128,14 @@ int main(int argc, char *argv[]) {
|
|||||||
} else if (imp == "InstructionImporter" || imp == "code") {
|
} else if (imp == "InstructionImporter" || imp == "code") {
|
||||||
LOG << "Using InstructionImporter" << endl;
|
LOG << "Using InstructionImporter" << endl;
|
||||||
importer = new InstructionImporter();
|
importer = new InstructionImporter();
|
||||||
|
|
||||||
} else if (imp == "RegisterImporter" || imp == "regs") {
|
} else if (imp == "RegisterImporter" || imp == "regs") {
|
||||||
LOG << "Using RegisterImporter" << endl;
|
LOG << "Using RegisterImporter" << endl;
|
||||||
importer = new RegisterImporter();
|
importer = new RegisterImporter();
|
||||||
|
|
||||||
|
} else if (imp == "RandomJumpImporter") {
|
||||||
|
LOG << "Using RandomJumpImporter" << endl;
|
||||||
|
importer = new RandomJumpImporter();
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
LOG << "Unkown import method: " << imp << endl;
|
LOG << "Unkown import method: " << imp << endl;
|
||||||
@ -141,7 +147,16 @@ int main(int argc, char *argv[]) {
|
|||||||
importer = new MemoryImporter();
|
importer = new MemoryImporter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (importer && !(importer->cb_commandline_init())) {
|
||||||
|
std::cerr << "Cannot call importers command line initialization!" << std::endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd[HELP]) {
|
if (cmd[HELP]) {
|
||||||
|
// Since the importer might have added command line options,
|
||||||
|
// we need to reparse all arguments in order to prevent a
|
||||||
|
// segfault within optionparser
|
||||||
|
cmd.parse();
|
||||||
cmd.printUsage();
|
cmd.printUsage();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user