(capstone) feat: add capstone disassembler to tools/import-trace/
This commit is contained in:
committed by
Robin Thunig
parent
d04afaac54
commit
f7f982fec5
@ -2,8 +2,10 @@
|
||||
#include <sstream>
|
||||
#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);
|
||||
|
||||
|
||||
@ -5,7 +5,11 @@
|
||||
#include <deque>
|
||||
#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<fail::CapstoneDisassembler> disas;
|
||||
#elif defined(BUILD_LLVM_DISASSEMBLER)
|
||||
llvm::object::Binary *binary = 0;
|
||||
std::unique_ptr<fail::LLVMDisassembler> disas;
|
||||
#endif
|
||||
bool m_last_was_conditional_branch;
|
||||
fail::guest_address_t m_ip_jump_not_taken;
|
||||
std::vector<bool> branches_taken;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -9,9 +9,10 @@
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BUILD_LLVM_DISASSEMBLER
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
#endif
|
||||
using namespace fail;
|
||||
using namespace std;
|
||||
|
||||
|
||||
@ -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<llvm::object::Binary> binary;
|
||||
#if defined(BUILD_CAPSTONE_DISASSEMBLER)
|
||||
std::unique_ptr<fail::CapstoneDisassembler> disas;
|
||||
#elif defined(BUILD_LLVM_DISASSEMBLER)
|
||||
std::unique_ptr<fail::LLVMDisassembler> disas;
|
||||
#endif
|
||||
|
||||
fail::CommandLine::option_handle OBJDUMP;
|
||||
fail::CommandLine::option_handle SOURCECODE;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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<fail::CapstoneDisassembler> disas;
|
||||
#elif defined(BUILD_LLVM_DISASSEMBLER)
|
||||
llvm::object::Binary *binary = 0;
|
||||
std::unique_ptr<fail::LLVMDisassembler> disas;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<fail::CapstoneDisassembler> disas;
|
||||
#elif defined(BUILD_LLVM_DISASSEMBLER)
|
||||
llvm::object::Binary *binary = 0;
|
||||
std::unique_ptr<fail::LLVMDisassembler> disas;
|
||||
#endif
|
||||
|
||||
fail::CommandLine::option_handle FROM, TO;
|
||||
|
||||
|
||||
@ -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<CapstoneDisassembler::register_t>::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<CapstoneDisassembler::register_t>::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<LLVMDisassembler::register_t>::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<LLVMDisassembler::register_t>::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
|
||||
|
||||
@ -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<fail::CapstoneDisassembler> 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<unsigned> 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<fail::guest_address_t> address;
|
||||
};
|
||||
std::map<fail::CapstoneDisassembler::register_t, RegNotFound> m_regnotfound;
|
||||
#elif defined(BUILD_LLVM_DISASSEMBLER)
|
||||
llvm::object::Binary *binary = 0;
|
||||
std::unique_ptr<fail::LLVMDisassembler> disas;
|
||||
fail::LLVMtoFailTranslator *m_ltof = 0;
|
||||
@ -32,6 +60,8 @@ class RegisterImporter : public Importer {
|
||||
std::set<fail::guest_address_t> address;
|
||||
};
|
||||
std::map<fail::LLVMDisassembler::register_t, RegNotFound> m_regnotfound;
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
RegisterImporter() : Importer(), do_gp(true), do_flags(false), do_ip(false),
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user