From 6c9bb21ab391daeaf2731c4ecc7bb332c0850c27 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Thu, 4 Jul 2013 13:39:02 +0200 Subject: [PATCH] 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 --- tools/import-trace/CMakeLists.txt | 1 + tools/import-trace/RandomJumpImporter.cc | 132 ++++++++++++++++++++++ tools/import-trace/RandomJumpImporter.hpp | 43 +++++++ tools/import-trace/main.cc | 15 +++ 4 files changed, 191 insertions(+) create mode 100644 tools/import-trace/RandomJumpImporter.cc create mode 100644 tools/import-trace/RandomJumpImporter.hpp diff --git a/tools/import-trace/CMakeLists.txt b/tools/import-trace/CMakeLists.txt index 43db2759..80fce373 100644 --- a/tools/import-trace/CMakeLists.txt +++ b/tools/import-trace/CMakeLists.txt @@ -7,6 +7,7 @@ if (BUILD_LLVM_DISASSEMBLER) set(SRCS ${SRCS} InstructionImporter.cc RegisterImporter.cc + RandomJumpImporter.cc ) include(FindLLVM) diff --git a/tools/import-trace/RandomJumpImporter.cc b/tools/import-trace/RandomJumpImporter.cc new file mode 100644 index 00000000..a7c05262 --- /dev/null +++ b/tools/import-trace/RandomJumpImporter.cc @@ -0,0 +1,132 @@ +#ifndef __puma +#include +#include +#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(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::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 diff --git a/tools/import-trace/RandomJumpImporter.hpp b/tools/import-trace/RandomJumpImporter.hpp new file mode 100644 index 00000000..088f58ca --- /dev/null +++ b/tools/import-trace/RandomJumpImporter.hpp @@ -0,0 +1,43 @@ +#ifndef __RANDOM_JUMP_IMPORTER_H__ +#define __RANDOM_JUMP_IMPORTER_H__ + +#include +#include "util/CommandLine.hpp" +#include "Importer.hpp" + +#ifndef __puma +#include "util/llvmdisassembler/LLVMDisassembler.hpp" +#endif + + +class RandomJumpImporter : public Importer { +#ifndef __puma + llvm::OwningPtr binary; + llvm::OwningPtr disas; +#endif + + fail::CommandLine::option_handle FROM, TO; + + fail::MemoryMap *m_mm_from, *m_mm_to; + std::vector 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 diff --git a/tools/import-trace/main.cc b/tools/import-trace/main.cc index 0f034326..877e85d2 100644 --- a/tools/import-trace/main.cc +++ b/tools/import-trace/main.cc @@ -11,6 +11,7 @@ #ifdef BUILD_LLVM_DISASSEMBLER #include "InstructionImporter.hpp" #include "RegisterImporter.hpp" +#include "RandomJumpImporter.hpp" #endif @@ -127,9 +128,14 @@ int main(int argc, char *argv[]) { } else if (imp == "InstructionImporter" || imp == "code") { LOG << "Using InstructionImporter" << endl; importer = new InstructionImporter(); + } else if (imp == "RegisterImporter" || imp == "regs") { LOG << "Using RegisterImporter" << endl; importer = new RegisterImporter(); + + } else if (imp == "RandomJumpImporter") { + LOG << "Using RandomJumpImporter" << endl; + importer = new RandomJumpImporter(); #endif } else { LOG << "Unkown import method: " << imp << endl; @@ -141,7 +147,16 @@ int main(int argc, char *argv[]) { importer = new MemoryImporter(); } + if (importer && !(importer->cb_commandline_init())) { + std::cerr << "Cannot call importers command line initialization!" << std::endl; + exit(-1); + } + 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(); exit(0); }