using namespace llvm::object;
using std::error_code;
+/*
+ *
+ */
+Disassembler * createLLVMDisassembler(const std::string& filename, InformationManager* manager) {
+ std::unique_ptr<Binary> o;
+ o.reset(createBinary(filename).get());
+ const Binary * op = o.get();
+
+ // ELFType<endian, maxalign, 64bit>
+ if (const ELF32LEObjectFile * _ = dyn_cast<ELF32LEObjectFile>(op)) {
+#pragma unused(_)
+ return new LLVMDisassembler<ELFType<support::little, 2, false>>(filename, manager);
+ }
+ if (const ELF64LEObjectFile * _ = dyn_cast<ELF64LEObjectFile>(op)) {
+#pragma unused(_)
+ return new LLVMDisassembler<ELFType<support::little, 2, true>>(filename, manager);
+ }
+ if (const ELF32BEObjectFile * _ = dyn_cast<ELF32BEObjectFile>(op)) {
+#pragma unused(_)
+ return new LLVMDisassembler<ELFType<support::big, 2, false>>(filename, manager);
+ }
+ if (const ELF64BEObjectFile * _ = dyn_cast<ELF64BEObjectFile>(op)) {
+#pragma unused(_)
+ return new LLVMDisassembler<ELFType<support::big, 2, true>>(filename, manager);
+ }
+
+ return NULL;
+}
+
/*
* TODO: fallback code falls die Datei kein ELF/PE/COFF/MacO/.. binary
* ist sondern z.B. einfach nur Instruktionen oder ein Bootsektor oder
* foo
*/
-LLVMDisassembler::LLVMDisassembler(const std::string& filename,
+template <typename ELFT>
+LLVMDisassembler<ELFT>::LLVMDisassembler(const std::string& filename,
InformationManager* manager)
: Disassembler(filename, manager)
, logger(log4cxx::Logger::getLogger("LLVMDisassembler"))
Mod.reset(OD->buildModule(false));
}
-void LLVMDisassembler::start() {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::start() {
readSymbols();
readSections();
disassemble();
}
-LLVMDisassembler::~LLVMDisassembler() {
+template <typename ELFT>
+LLVMDisassembler<ELFT>::~LLVMDisassembler() {
std::for_each(functions.begin(), functions.end(),
[](std::pair<uint64_t,LLVMFunction*> it) {
delete it.second;
});
}
-Function* LLVMDisassembler::disassembleFunctionAt(uint64_t address, const std::string& name) {
+template <typename ELFT>
+Function* LLVMDisassembler<ELFT>::disassembleFunctionAt(uint64_t address, const std::string& name) {
SectionRef text_section = sections[".text"];
uint64_t base_address, size;
text_section.getAddress(base_address);
return function;
}
-void LLVMDisassembler::disassembleFunction(LLVMFunction* function) {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::disassembleFunction(LLVMFunction* function) {
std::stack<LLVMBasicBlock*> remaining_blocks;
SectionRef text_section = sections[".text"];
StringRef bytes;
blocks.insert(std::make_pair(block->getStartAddress(), block));
function->addBasicBlock(block);
remaining_blocks.push(block);
+ } else {
+ LOG4CXX_DEBUG(logger, "Reusing Block starting at " << std::hex << current_block->getStartAddress());
+ function->addBasicBlock(blocks.find(jmptarget)->second);
}
if (MIA->isConditionalBranch(inst)) {
jmptarget = base_address + current_address + inst_size;
blocks.insert(std::make_pair(block->getStartAddress(), block));
function->addBasicBlock(block);
remaining_blocks.push(block);
+ } else {
+ LOG4CXX_DEBUG(logger, "Reusing Block starting at " << std::hex << current_block->getStartAddress());
+ function->addBasicBlock(blocks.find(jmptarget)->second);
}
}
}
manager->signal_new_function(function);
}
-void LLVMDisassembler::disassemble() {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::disassemble() {
SectionRef text_section = sections[".text"];
std::vector<LLVMFunction*> remaining_functions;
if (binary->isELF()) {
bool is64bit = (binary->getData()[4] == 0x02);
- uint64_t entry(0);
for (int i(0); i < (is64bit? 8 : 4); ++i) {
if (binary->isLittleEndian()) {
- entry |= (unsigned int)((unsigned char)binary->getData()[0x18 + i]) << 8*i;
+ _entryAddress |= (unsigned int)((unsigned char)binary->getData()[0x18 + i]) << 8*i;
} else {
- entry = entry << 8;
- entry |= (unsigned char)binary->getData()[0x18 + i];
+ _entryAddress = _entryAddress << 8;
+ _entryAddress |= (unsigned char)binary->getData()[0x18 + i];
}
}
- LOG4CXX_DEBUG(logger, "Adding entry at: " << std::hex << entry);
+ LOG4CXX_DEBUG(logger, "Adding entryAddress at: " << std::hex << _entryAddress);
std::stringstream s;
- s << "<_start 0x" << std::hex << entry << ">";
+ s << "<_start 0x" << std::hex << _entryAddress << ">";
- disassembleFunctionAt(entry, s.str());
+ disassembleFunctionAt(_entryAddress, s.str());
}
if (functions.empty()) {
}
}
-void LLVMDisassembler::splitBlocks(LLVMFunction* function) {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::splitBlocks(LLVMFunction* function) {
SectionRef text_section = sections[".text"];
StringRef bytes;
text_section.getContents(bytes);
<< current_block->getStartAddress()
<< " now ending at "
<< other->first);
+ function->addBasicBlock(other->second);
current_block->setEndAddress(endaddress);
current_block->setNextBlock(0, other->first);
current_block->setNextBlock(1, 0);
}
}
-void LLVMDisassembler::readSymbols() {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::readSymbols() {
error_code ec;
symbol_iterator si(o->symbol_begin()), se(o->symbol_end());
for (; si != se; ++si) {
}
}
-void LLVMDisassembler::readSections() {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::readSections() {
error_code ec;
section_iterator i(o->section_begin()), e(o->section_end());
for (; i != e; ++i) {
}
-void LLVMDisassembler::forEachFunction(std::function<void (uint64_t, Function*)> callback) {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::forEachFunction(std::function<void (uint64_t, Function*)> callback) {
std::for_each(functions.begin(), functions.end(),
[&](std::pair<uint64_t, LLVMFunction*> x) {
callback(x.first, x.second);
});
}
-void LLVMDisassembler::printEachInstruction(uint64_t start, uint64_t end,
- std::function<void (uint8_t*, size_t,
- const std::string&)> fun) {
+template <typename ELFT>
+void LLVMDisassembler<ELFT>::printEachInstruction(uint64_t start, uint64_t end,
+ std::function<void (uint8_t*, size_t,
+ const std::string&,
+ const std::string&)> fun) {
SectionRef text_section = sections[".text"];
uint64_t base_address;
text_section.getAddress(base_address);
ref.readBytes(current_address, inst_size, bytes);
uint64_t jmptarget;
+ std::string ref("");
+ IP->printInst(&inst, s, "");
if (MIA->evaluateBranch(inst, current_address, inst_size, jmptarget)) {
std::stringstream stream;
+ if (MIA->isCall(inst))
+ stream << "function:";
+ else
+ stream << "block:";
+
stream << std::hex << (base_address + jmptarget);
- IP->printInst(&inst, s, stream.str());
- } else
- IP->printInst(&inst, s, "");
+ ref = stream.str();
+ }
+
- fun(bytes, inst_size, s.str());
+ fun(bytes, inst_size, s.str(), ref);
} else {
LOG4CXX_WARN(logger, "Invalid byte at" << std::hex << current_address + base_address);
- fun(NULL, 0, "Invalid Byte");
+ fun(NULL, 0, "Invalid Byte", "");
inst_size = 1;
}