diff --git a/src/core/util/ElfReader.cc b/src/core/util/ElfReader.cc index a3018ac0..76669864 100644 --- a/src/core/util/ElfReader.cc +++ b/src/core/util/ElfReader.cc @@ -97,7 +97,7 @@ void ElfReader::setup(const char* path) { printf("Error: wrong Section to read\n"); } else { process_section(&sec_hdr, buff); - } + } } free(buff); @@ -218,6 +218,7 @@ bool ElfReader::read_ELF_file_header(FILE *fp, Elf64_Ehdr *filehdr) return false; } + m_machine = filehdr32.e_machine; m_elfclass = filehdr32.e_ident[EI_CLASS]; if (m_elfclass == ELFCLASS32) { Elf32to64_Ehdr(&filehdr32, filehdr); diff --git a/src/core/util/ElfReader.hpp b/src/core/util/ElfReader.hpp index b7babbdd..d6712b93 100644 --- a/src/core/util/ElfReader.hpp +++ b/src/core/util/ElfReader.hpp @@ -81,6 +81,8 @@ public: typedef container_t::const_iterator symbol_iterator; typedef container_t::const_iterator section_iterator; + int m_machine; + int m_elfclass; /** * Constructor. @@ -157,7 +159,6 @@ public: private: Logger m_log; std::string m_filename; - int m_elfclass; void setup(const char*); bool process_symboltable(FILE *fp, Elf64_Ehdr const *ehdr, int sect_num); diff --git a/tools/import-trace/AdvancedMemoryImporter.cc b/tools/import-trace/AdvancedMemoryImporter.cc index eb36cd33..61eaead8 100644 --- a/tools/import-trace/AdvancedMemoryImporter.cc +++ b/tools/import-trace/AdvancedMemoryImporter.cc @@ -2,8 +2,10 @@ #include #include "AdvancedMemoryImporter.hpp" +#ifdef BUILD_LLVM_DISASSEMBLER using namespace llvm; using namespace llvm::object; +#endif using namespace fail; static fail::Logger LOG("AdvancedMemoryImporter"); @@ -98,6 +100,35 @@ bool AdvancedMemoryImporter::handle_ip_event(fail::simtime_t curtime, instructio // (delayed) trace entries insert_delayed_entries(false); +#if defined(BUILD_CAPSTONE_DISASSEMBLER) + if (!isDisassembled) { + if (!m_elf) { + LOG << "Please give an ELF binary as parameter (-e/--elf)." << std::endl; + return false; + } + + disas.reset(new CapstoneDisassembler(m_elf)); + + disas->disassemble(); + CapstoneDisassembler::InstrMap &instr_map = disas->getInstrMap(); + LOG << "instructions disassembled: " << std::dec << instr_map.size() << std::endl; +#if 0 + for (CapstoneDisassembler::InstrMap::const_iterator it = instr_map.begin(); + it != instr_map.end(); ++it) { + LOG << "DIS " << std::hex << it->second.address << " " << (int) it->second.length << std::endl; + } +#endif + } + + const CapstoneDisassembler::InstrMap &instr_map = disas->getInstrMap(); + const CapstoneDisassembler::InstrMap::const_iterator it = instr_map.find(ev.ip()); + if (it == instr_map.end()) { + LOG << "WARNING: CapstoneDisassembler hasn't disassembled instruction at 0x" + << ev.ip() << " -- are you using Capstone < 4.0?" << std::endl; + return true; // probably weird things will happen now + } + const CapstoneDisassembler::Instr &opcode = it->second; +#elif defined(BUILD_LLVM_DISASSEMBLER) if (!binary) { /* Disassemble the binary if necessary */ llvm::InitializeAllTargetInfos(); @@ -144,6 +175,7 @@ bool AdvancedMemoryImporter::handle_ip_event(fail::simtime_t curtime, instructio return true; // probably weird things will happen now } const LLVMDisassembler::Instr &opcode = it->second; +#endif /* Now we've got the opcode and know whether it's a conditional branch. If * it is, the next IP event will tell us whether it was taken or not. */ @@ -161,8 +193,13 @@ bool AdvancedMemoryImporter::handle_ip_event(fail::simtime_t curtime, instructio bool AdvancedMemoryImporter::handle_mem_event(fail::simtime_t curtime, instruction_count_t instr, Trace_Event &ev) { +#if defined(BUILD_CAPSTONE_DISASSEMBLER) + const CapstoneDisassembler::InstrMap &instr_map = disas->getInstrMap(); + const CapstoneDisassembler::Instr &opcode = instr_map.at(ev.ip()); +#elif defined(BUILD_LLVM_DISASSEMBLER) const LLVMDisassembler::InstrMap &instr_map = disas->getInstrMap(); const LLVMDisassembler::Instr &opcode = instr_map.at(ev.ip()); +#endif DelayedTraceEntry entry = { curtime, instr, ev, opcode.opcode, (unsigned) branches_taken.size() }; delayed_entries.push_back(entry); diff --git a/tools/import-trace/AdvancedMemoryImporter.hpp b/tools/import-trace/AdvancedMemoryImporter.hpp index 183418b0..1165d2b0 100644 --- a/tools/import-trace/AdvancedMemoryImporter.hpp +++ b/tools/import-trace/AdvancedMemoryImporter.hpp @@ -5,7 +5,11 @@ #include #include "MemoryImporter.hpp" +#if defined(BUILD_CAPSTONE_DISASSEMBLER) +#include "util/capstonedisassembler/CapstoneDisassembler.hpp" +#elif defined(BUILD_LLVM_DISASSEMBLER) #include "util/llvmdisassembler/LLVMDisassembler.hpp" +#endif /** * A MemoryImporter that additionally imports Relyzer-style conditional branch @@ -24,8 +28,13 @@ * operations with a set of new virtual functions that are called downwards. */ class AdvancedMemoryImporter : public MemoryImporter { +#if defined(BUILD_CAPSTONE_DISASSEMBLER) + bool isDisassembled = false; + std::unique_ptr disas; +#elif defined(BUILD_LLVM_DISASSEMBLER) llvm::object::Binary *binary = 0; std::unique_ptr disas; +#endif bool m_last_was_conditional_branch; fail::guest_address_t m_ip_jump_not_taken; std::vector branches_taken; diff --git a/tools/import-trace/CMakeLists.txt b/tools/import-trace/CMakeLists.txt index 93ab3603..dc1f6f13 100644 --- a/tools/import-trace/CMakeLists.txt +++ b/tools/import-trace/CMakeLists.txt @@ -28,9 +28,26 @@ if (BUILD_LLVM_DISASSEMBLER) find_package(LibDwarf REQUIRED) include_directories(${LIBELF_INCLUDE_DIRS}) include_directories(${LIBDWARF_INCLUDE_DIRS}) - endif(BUILD_LLVM_DISASSEMBLER) +if (BUILD_CAPSTONE_DISASSEMBLER) + set(SRCS ${SRCS} + InstructionImporter.cc + RegisterImporter.cc + RandomJumpImporter.cc + AdvancedMemoryImporter.cc + ElfImporter.cc + ) + + include(FindCapstone) + + # libelf and libdwarf required by ElfImporter + find_package(LibElf REQUIRED) + find_package(LibDwarf REQUIRED) + include_directories(${LIBELF_INCLUDE_DIRS}) + include_directories(${LIBDWARF_INCLUDE_DIRS}) +endif(BUILD_CAPSTONE_DISASSEMBLER) + find_package(MySQL REQUIRED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MYSQL_CFLAGS}") @@ -48,5 +65,9 @@ if (BUILD_LLVM_DISASSEMBLER) target_link_libraries(import-trace fail-llvmdisassembler fail-sal ${LLVM_LIBS} ${LLVM_LDFLAGS} ${Boost_LIBRARIES}) endif (BUILD_LLVM_DISASSEMBLER) +if (BUILD_CAPSTONE_DISASSEMBLER) + target_link_libraries(import-trace fail-capstonedisassembler fail-sal) +endif (BUILD_CAPSTONE_DISASSEMBLER) + install(TARGETS import-trace RUNTIME DESTINATION bin) install(PROGRAMS import-symbols.sh DESTINATION bin) diff --git a/tools/import-trace/ElfImporter.cc b/tools/import-trace/ElfImporter.cc index 329980ab..e2e91ce4 100644 --- a/tools/import-trace/ElfImporter.cc +++ b/tools/import-trace/ElfImporter.cc @@ -9,9 +9,10 @@ #include #endif - +#ifdef BUILD_LLVM_DISASSEMBLER using namespace llvm; using namespace llvm::object; +#endif using namespace fail; using namespace std; diff --git a/tools/import-trace/ElfImporter.hpp b/tools/import-trace/ElfImporter.hpp index 13c8106b..4b64c6a1 100644 --- a/tools/import-trace/ElfImporter.hpp +++ b/tools/import-trace/ElfImporter.hpp @@ -7,7 +7,13 @@ #include "libelf.h" #include "Importer.hpp" + +#if defined(BUILD_CAPSTONE_DISASSEMBLER) +#include "util/capstonedisassembler/CapstoneDisassembler.hpp" +#elif defined(BUILD_LLVM_DISASSEMBLER) #include "util/llvmdisassembler/LLVMDisassembler.hpp" +#endif + #include "util/CommandLine.hpp" #include "util/DwarfReader.hpp" @@ -27,8 +33,11 @@ into the database. */ class ElfImporter : public Importer { - std::unique_ptr binary; +#if defined(BUILD_CAPSTONE_DISASSEMBLER) + std::unique_ptr disas; +#elif defined(BUILD_LLVM_DISASSEMBLER) std::unique_ptr disas; +#endif fail::CommandLine::option_handle OBJDUMP; fail::CommandLine::option_handle SOURCECODE; diff --git a/tools/import-trace/InstructionImporter.cc b/tools/import-trace/InstructionImporter.cc index c0eab477..60243cf4 100644 --- a/tools/import-trace/InstructionImporter.cc +++ b/tools/import-trace/InstructionImporter.cc @@ -3,8 +3,10 @@ #include "InstructionImporter.hpp" #include "util/Logger.hpp" +#ifdef BUILD_LLVM_DISASSEMBLER using namespace llvm; using namespace llvm::object; +#endif using namespace fail; @@ -12,6 +14,28 @@ static Logger LOG("InstructionImporter"); bool InstructionImporter::handle_ip_event(fail::simtime_t curtime, instruction_count_t instr, Trace_Event &ev) { +#if defined(BUILD_CAPSTONE_DISASSEMBLER) + if (!isDisassembled) { + if (!m_elf) { + LOG << "Please give an ELF binary as parameter (-e/--elf)." << std::endl; + return false; + } + + disas.reset(new CapstoneDisassembler(m_elf)); + + disas->disassemble(); + CapstoneDisassembler::InstrMap &instr_map = disas->getInstrMap(); + LOG << "instructions disassembled: " << instr_map.size() << std::endl; + isDisassembled = true; + } + const CapstoneDisassembler::InstrMap &instr_map = disas->getInstrMap(); + if (instr_map.find(ev.ip()) == instr_map.end()) { + LOG << "Could not find instruction for IP " << std::hex << ev.ip() + << ", skipping" << std::endl; + return true; + } + const CapstoneDisassembler::Instr &opcode = instr_map.at(ev.ip()); +#elif defined(BUILD_LLVM_DISASSEMBLER) if (!binary) { /* Disassemble the binary if necessary */ llvm::InitializeAllTargetInfos(); @@ -46,6 +70,7 @@ bool InstructionImporter::handle_ip_event(fail::simtime_t curtime, instruction_c const LLVMDisassembler::InstrMap &instr_map = disas->getInstrMap(); const LLVMDisassembler::Instr &opcode = instr_map.at(ev.ip()); +#endif address_t from = ev.ip(), to = ev.ip() + opcode.length; diff --git a/tools/import-trace/InstructionImporter.hpp b/tools/import-trace/InstructionImporter.hpp index 27391a30..9640e230 100644 --- a/tools/import-trace/InstructionImporter.hpp +++ b/tools/import-trace/InstructionImporter.hpp @@ -3,11 +3,20 @@ #include "Importer.hpp" +#if defined(BUILD_CAPSTONE_DISASSEMBLER) +#include "util/capstonedisassembler/CapstoneDisassembler.hpp" +#elif defined(BUILD_LLVM_DISASSEMBLER) #include "util/llvmdisassembler/LLVMDisassembler.hpp" +#endif class InstructionImporter : public Importer { +#if defined(BUILD_CAPSTONE_DISASSEMBLER) + bool isDisassembled = false; + std::unique_ptr disas; +#elif defined(BUILD_LLVM_DISASSEMBLER) llvm::object::Binary *binary = 0; std::unique_ptr disas; +#endif protected: virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr, diff --git a/tools/import-trace/RandomJumpImporter.cc b/tools/import-trace/RandomJumpImporter.cc index d426f12c..a92af9d9 100644 --- a/tools/import-trace/RandomJumpImporter.cc +++ b/tools/import-trace/RandomJumpImporter.cc @@ -3,8 +3,10 @@ #include "util/Logger.hpp" #include "RandomJumpImporter.hpp" +#ifdef BUILD_LLVM_DISASSEMBLER using namespace llvm; using namespace llvm::object; +#endif using namespace fail; using namespace std; @@ -60,6 +62,22 @@ bool RandomJumpImporter::handle_ip_event(fail::simtime_t curtime, instruction_co return false; } +#if defined(BUILD_CAPSTONE_DISASSEMBLER) + disas.reset(new CapstoneDisassembler(m_elf)); + + disas->disassemble(); + CapstoneDisassembler::InstrMap &instr_map = disas->getInstrMap(); + LOG << "instructions disassembled: " << instr_map.size() << std::endl; + + /* Collect all addresses we want to jump to */ + for (CapstoneDisassembler::InstrMap::const_iterator instr = instr_map.begin(); + instr != instr_map.end(); ++instr) { + if (m_mm_to && m_mm_to->isMatching(instr->first)) { + m_jump_to_addresses.push_back(instr->first); + } + } + binary = true; +#elif defined(BUILD_LLVM_DISASSEMBLER) /* Disassemble the binary if necessary */ llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); @@ -92,6 +110,7 @@ bool RandomJumpImporter::handle_ip_event(fail::simtime_t curtime, instruction_co m_jump_to_addresses.push_back(instr->first); } } +#endif LOG << "we will jump to " << m_jump_to_addresses.size() << " addresses" << endl; } diff --git a/tools/import-trace/RandomJumpImporter.hpp b/tools/import-trace/RandomJumpImporter.hpp index c48c7b38..48096bd3 100644 --- a/tools/import-trace/RandomJumpImporter.hpp +++ b/tools/import-trace/RandomJumpImporter.hpp @@ -5,11 +5,20 @@ #include "util/CommandLine.hpp" #include "Importer.hpp" +#if defined(BUILD_CAPSTONE_DISASSEMBLER) +#include "util/capstonedisassembler/CapstoneDisassembler.hpp" +#elif defined(BUILD_LLVM_DISASSEMBLER) #include "util/llvmdisassembler/LLVMDisassembler.hpp" +#endif class RandomJumpImporter : public Importer { +#if defined(BUILD_CAPSTONE_DISASSEMBLER) + bool binary = false; + std::unique_ptr disas; +#elif defined(BUILD_LLVM_DISASSEMBLER) llvm::object::Binary *binary = 0; std::unique_ptr disas; +#endif fail::CommandLine::option_handle FROM, TO; diff --git a/tools/import-trace/RegisterImporter.cc b/tools/import-trace/RegisterImporter.cc index 2d3e14ad..ad240180 100644 --- a/tools/import-trace/RegisterImporter.cc +++ b/tools/import-trace/RegisterImporter.cc @@ -3,8 +3,11 @@ #include "RegisterImporter.hpp" #include "util/Logger.hpp" +#ifdef BUILD_LLVM_DISASSEMBLER using namespace llvm; using namespace llvm::object; +#endif + using namespace fail; @@ -29,7 +32,214 @@ bool RegisterImporter::cb_commandline_init() { return true; } +#if defined(BUILD_CAPSTONE_DISASSEMBLER) +bool RegisterImporter::addRegisterTrace(simtime_t curtime, instruction_count_t instr, + Trace_Event &ev, + const CapstoneToFailTranslator::reginfo_t &info, + char access_type) { + address_t from, to; + int chunk_width; + if (do_split_registers) { + /* If we want to split the registers into one byte chunks (to + enable proper pruning, we use a one byte window register, + to determine beginning and end address */ + CapstoneToFailTranslator::reginfo_t one_byte_window = info; + one_byte_window.width = 8; + from = one_byte_window.toDataAddress(); + to = one_byte_window.toDataAddress() + info.width / 8; + chunk_width = 1; // One byte chunks + } else { + /* We trace whole registers */ + from = info.toDataAddress(); + to = from + 1; /* exactly one trace event per register access*/ + chunk_width = (info.width / 8); + } + // 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(ev.ip())) { + 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 + + // pass through potentially available extended trace information + ev.set_width(chunk_width); + ev.set_memaddr(data_address); + ev.set_accesstype(access_type == 'R' ? ev.READ : ev.WRITE); + if (!add_trace_event(left_margin, right_margin, ev)) { + 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; +} + + +bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_count_t instr, + Trace_Event &ev) { + if (!isDisassembled) { + // 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; + } + do_gp = !cmd[NO_GP]; + do_flags = cmd[FLAGS]; + do_ip = cmd[IP]; + do_split_registers = !cmd[NO_SPLIT]; + + // retrieve register IDs for general-purpose and flags register(s) for + // the configured architecture + fail::Architecture arch; + m_ip_register_id = + (*arch.getRegisterSetOfType(RT_IP)->begin())->getId(); + fail::UniformRegisterSet *regset; + if (do_gp) { + regset = arch.getRegisterSetOfType(RT_GP); + for (fail::UniformRegisterSet::iterator it = regset->begin(); + it != regset->end(); ++it) { + m_register_ids.insert((*it)->getId()); + } + } + if (do_flags) { + regset = arch.getRegisterSetOfType(RT_ST); + for (fail::UniformRegisterSet::iterator it = regset->begin(); + it != regset->end(); ++it) { + m_register_ids.insert((*it)->getId()); + } + } + + + if (!m_elf) { + LOG << "Please give an ELF binary as parameter (-e/--elf)." << std::endl; + return false; + } + disas.reset(new CapstoneDisassembler(m_elf)); + LOG << "Start to dissamble" << std::endl; + disas->disassemble(); + LOG << "Get instr map" << std::endl; + CapstoneDisassembler::InstrMap &instr_map = disas->getInstrMap(); + LOG << "instructions disassembled: " << std::dec << instr_map.size() << std::endl; + m_ctof = disas->getTranslator(); + isDisassembled = true; + } + + // instruction pointer is read + written at each instruction + const CapstoneToFailTranslator::reginfo_t info_pc(m_ip_register_id); + if (do_ip && + (!addRegisterTrace(curtime, instr, ev, info_pc, 'R') || + !addRegisterTrace(curtime, instr, ev, info_pc, 'W'))) { + return false; + } + + const CapstoneDisassembler::InstrMap &instr_map = disas->getInstrMap(); + if (instr_map.find(ev.ip()) == instr_map.end()) { + LOG << "Could not find instruction for IP " << std::hex << ev.ip() + << ", skipping" << std::endl; + return true; + } + const CapstoneDisassembler::Instr &opcode = instr_map.at(ev.ip()); + //const MCRegisterInfo ®_info = disas->getRegisterInfo(); +// LOG << std::hex << "Address: " << opcode.address << " Opcode: " << opcode.opcode << std::endl; +// std::string log_regs = "Uses: "; + for (std::vector::const_iterator it = opcode.reg_uses.begin(); + it != opcode.reg_uses.end(); ++it) { +// log_regs += std::to_string(*it) + " "; + const CapstoneToFailTranslator::reginfo_t &info = m_ctof->getFailRegisterInfo(*it); + if (&info == &m_ctof->notfound) { + // record failed translation, report later + m_regnotfound[*it].count++; + m_regnotfound[*it].address.insert(ev.ip()); + continue; + } + + /* only proceed if we want to inject into this register */ + if (m_register_ids.find(info.id) == m_register_ids.end()) { +// log_regs += "n "; + continue; + } + + if (!addRegisterTrace(curtime, instr, ev, info, 'R')) { + return false; + } + } + +// log_regs += "Defs: "; + + for (std::vector::const_iterator it = opcode.reg_defs.begin(); + it != opcode.reg_defs.end(); ++it) { +// log_regs += std::to_string(*it) + " "; + const CapstoneToFailTranslator::reginfo_t &info = m_ctof->getFailRegisterInfo(*it); + if (&info == &m_ctof->notfound) { + // record failed translation, report later + m_regnotfound[*it].count++; + m_regnotfound[*it].address.insert(ev.ip()); + continue; + } + + /* only proceed if we want to inject into this register */ + if (m_register_ids.find(info.id) == m_register_ids.end()) { +// log_regs += "n "; + continue; + } + + if (!addRegisterTrace(curtime, instr, ev, info, 'W')) + return false; + } +// LOG << log_regs.c_str() << std::endl; + + return true; +} + +bool RegisterImporter::trace_end_reached() +{ + // report failed LLVM -> FAIL* register mappings, if any + if (m_regnotfound.empty()) { + return true; + } + + LOG << "WARNING: Some LLVM -> FAIL* register mappings failed during import, these will not be injected into:" << std::endl; + for (auto it = m_regnotfound.cbegin(); it != m_regnotfound.cend(); ++it) { + const CapstoneDisassembler::register_t id = it->first; + const RegNotFound& rnf = it->second; + LOG << "Capstone register " << std::dec << id + /* << " \"" << disas->getRegisterInfo().getName(id) << "\": " */ + << "seen " << rnf.count << " times in the trace" << std::endl; + std::ostream& o = LOG << " corresponding instruction addresses in ELF binary: " << std::hex; + for (auto addr_it = rnf.address.cbegin(); addr_it != rnf.address.cend(); ++addr_it) { + if (addr_it != rnf.address.cbegin()) { + o << ", "; + } + o << "0x" << *addr_it; + } + o << std::endl; + } + + return true; +} +#elif defined(BUILD_LLVM_DISASSEMBLER) bool RegisterImporter::addRegisterTrace(simtime_t curtime, instruction_count_t instr, Trace_Event &ev, const LLVMtoFailTranslator::reginfo_t &info, @@ -177,9 +387,12 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun } const LLVMDisassembler::Instr &opcode = instr_map.at(ev.ip()); //const MCRegisterInfo ®_info = disas->getRegisterInfo(); +// LOG << std::hex << "Address: " << opcode.address << " Opcode: " << opcode.opcode << std::endl; +// std::string log_regs = "Uses: "; for (std::vector::const_iterator it = opcode.reg_uses.begin(); it != opcode.reg_uses.end(); ++it) { +// log_regs += std::to_string(*it) + " "; const LLVMtoFailTranslator::reginfo_t &info = m_ltof->getFailRegisterInfo(*it); if (&info == &m_ltof->notfound) { // record failed translation, report later @@ -198,8 +411,10 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun } } +// log_regs += "Defs: "; for (std::vector::const_iterator it = opcode.reg_defs.begin(); it != opcode.reg_defs.end(); ++it) { +// log_regs += std::to_string(*it) + " "; const LLVMtoFailTranslator::reginfo_t &info = m_ltof->getFailRegisterInfo(*it); if (&info == &m_ltof->notfound) { // record failed translation, report later @@ -210,12 +425,14 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun /* only proceed if we want to inject into this register */ if (m_register_ids.find(info.id) == m_register_ids.end()) { +// log_regs += "n "; continue; } if (!addRegisterTrace(curtime, instr, ev, info, 'W')) return false; } +// LOG << log_regs.c_str() << std::endl; return true; } @@ -246,3 +463,4 @@ bool RegisterImporter::trace_end_reached() return true; } +#endif diff --git a/tools/import-trace/RegisterImporter.hpp b/tools/import-trace/RegisterImporter.hpp index 64218097..b0e927c3 100644 --- a/tools/import-trace/RegisterImporter.hpp +++ b/tools/import-trace/RegisterImporter.hpp @@ -5,10 +5,38 @@ #include "util/CommandLine.hpp" #include "Importer.hpp" +#if defined(BUILD_CAPSTONE_DISASSEMBLER) +#include "util/capstonedisassembler/CapstoneDisassembler.hpp" +#elif defined(BUILD_LLVM_DISASSEMBLER) #include "util/llvmdisassembler/LLVMDisassembler.hpp" - +#endif class RegisterImporter : public Importer { +#if defined(BUILD_CAPSTONE_DISASSEMBLER) + bool isDisassembled = false; + std::unique_ptr disas; + fail::CapstoneToFailTranslator *m_ctof = 0; + + bool addRegisterTrace(fail::simtime_t curtime, instruction_count_t instr, + Trace_Event &ev, + const fail::CapstoneToFailTranslator::reginfo_t &info, + char access_type); + + fail::CommandLine::option_handle NO_GP, FLAGS, IP, NO_SPLIT; + bool do_gp, do_flags, do_ip, do_split_registers; + + std::set m_register_ids; + unsigned m_ip_register_id; + + // Data structures for recording failed LLVM -> FAIL* register mappings, + // including occurrence counts in the trace (to give an estimate on the + // impact) and instruction addresses (for debugging purposes). + struct RegNotFound { + uint64_t count = 0; + std::set address; + }; + std::map m_regnotfound; +#elif defined(BUILD_LLVM_DISASSEMBLER) llvm::object::Binary *binary = 0; std::unique_ptr disas; fail::LLVMtoFailTranslator *m_ltof = 0; @@ -32,6 +60,8 @@ class RegisterImporter : public Importer { std::set address; }; std::map m_regnotfound; +#endif + public: RegisterImporter() : Importer(), do_gp(true), do_flags(false), do_ip(false), diff --git a/tools/import-trace/main.cc b/tools/import-trace/main.cc index c3be1237..064eb4ad 100644 --- a/tools/import-trace/main.cc +++ b/tools/import-trace/main.cc @@ -10,12 +10,14 @@ #include "FullTraceImporter.hpp" #include "util/AliasedRegistry.hpp" +#if defined(BUILD_LLVM_DISASSEMBLER) || defined(BUILD_CAPSTONE_DISASSEMBLER) #ifdef BUILD_LLVM_DISASSEMBLER #include "llvm/Support/ManagedStatic.h" -#include "InstructionImporter.hpp" -#include "RegisterImporter.hpp" +#endif #include "RandomJumpImporter.hpp" #include "AdvancedMemoryImporter.hpp" +#include "InstructionImporter.hpp" +#include "RegisterImporter.hpp" #include "ElfImporter.hpp" #endif @@ -67,18 +69,20 @@ int main(int argc, char *argv[]) { FullTraceImporter fti; registry.add(&fti); +#if defined(BUILD_LLVM_DISASSEMBLER) || defined(BUILD_CAPSTONE_DISASSEMBLER) #ifdef BUILD_LLVM_DISASSEMBLER llvm::llvm_shutdown_obj Y; - RegisterImporter reg; - registry.add(®); - RandomJumpImporter rjump; - registry.add(&rjump); +#endif AdvancedMemoryImporter adv; registry.add(&adv); - ElfImporter elf; - registry.add(&elf); + RandomJumpImporter rjump; + registry.add(&rjump); InstructionImporter instr; registry.add(&instr); + RegisterImporter reg; + registry.add(®); + ElfImporter elf; + registry.add(&elf); #endif std::string importers = registry.getPrimeAliasesCSV();