From 37e3e9570967efad39ba74213f51bd12aebe4c8c Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Thu, 14 Nov 2013 15:57:09 +0100 Subject: [PATCH] work --- Makefile | 6 +- src/Binary.cxx | 680 +++++++++++++++++++++++------------------ src/Binary.hxx | 74 +++-- src/gui/Mainwindow.cxx | 80 ++++- src/gui/Mainwindow.h++ | 21 +- 5 files changed, 524 insertions(+), 337 deletions(-) diff --git a/Makefile b/Makefile index 549ea3c..a32233b 100644 --- a/Makefile +++ b/Makefile @@ -3,9 +3,9 @@ CXX = clang++ LD = clang++ -CXXFLAGS += $(shell llvm-config-3.4 --cflags) $(shell pkg-config QtGui --cflags) -Isrc -LDFLAGS ?= $(shell llvm-config-3.4 --ldflags) -LIBS ?= $(shell llvm-config-3.4 --libs) $(shell pkg-config QtGui --libs) +CXXFLAGS += $(shell llvm-config-3.4 --cflags) $(shell pkg-config QtGui --cflags) -Isrc -std=c++0x +LDFLAGS += $(shell llvm-config-3.4 --ldflags) +LIBS += $(shell llvm-config-3.4 --libs) $(shell pkg-config QtGui --libs) objects = $(patsubst %.cxx,%.o,$(shell find src -name \*.cxx)) $(patsubst %.h++,%_moc.o,$(shell find src -name \*.h++)) diff --git a/src/Binary.cxx b/src/Binary.cxx index d57db4e..83909a0 100644 --- a/src/Binary.cxx +++ b/src/Binary.cxx @@ -4,351 +4,451 @@ #include #include +#include "llvm/Support/raw_ostream.h" + using namespace llvm; using namespace llvm::object; -static bool error(error_code ec) { - if (!ec) return false; +namespace { + bool error(error_code ec) { + if (!ec) return false; - outs() << "error reading file: " << ec.message() << ".\n"; - outs().flush(); - return true; -} + outs() << "error reading file: " << ec.message() << ".\n"; + outs().flush(); + return true; + } -static bool RelocAddressLess(RelocationRef a, RelocationRef b) { - uint64_t a_addr, b_addr; - if (error(a.getOffset(a_addr))) return false; - if (error(b.getOffset(b_addr))) return false; - return a_addr < b_addr; -} + bool RelocAddressLess(RelocationRef a, RelocationRef b) { + uint64_t a_addr, b_addr; + if (error(a.getOffset(a_addr))) return false; + if (error(b.getOffset(b_addr))) return false; + return a_addr < b_addr; + } -static void DumpBytes(StringRef bytes) { - static const char hex_rep[] = "0123456789abcdef"; - // FIXME: The real way to do this is to figure out the longest instruction - // and align to that size before printing. I'll fix this when I get - // around to outputting relocations. - // 15 is the longest x86 instruction - // 3 is for the hex rep of a byte + a space. - // 1 is for the null terminator. - enum { OutputSize = (15 * 3) + 1 }; - char output[OutputSize]; - - assert(bytes.size() <= 15 - && "DumpBytes only supports instructions of up to 15 bytes"); - memset(output, ' ', sizeof(output)); - unsigned index = 0; - for (StringRef::iterator i = bytes.begin(), - e = bytes.end(); i != e; ++i) { - output[index] = hex_rep[(*i & 0xF0) >> 4]; - output[index + 1] = hex_rep[*i & 0xF]; - index += 3; + void DumpBytes(StringRef bytes) { + static const char hex_rep[] = "0123456789abcdef"; + // FIXME: The real way to do this is to figure out the longest instruction + // and align to that size before printing. I'll fix this when I get + // around to outputting relocations. + // 15 is the longest x86 instruction + // 3 is for the hex rep of a byte + a space. + // 1 is for the null terminator. + enum { OutputSize = (15 * 3) + 1 }; + char output[OutputSize]; + + assert(bytes.size() <= 15 + && "DumpBytes only supports instructions of up to 15 bytes"); + memset(output, ' ', sizeof(output)); + unsigned index = 0; + for (StringRef::iterator i = bytes.begin(), + e = bytes.end(); i != e; ++i) { + output[index] = hex_rep[(*i & 0xF0) >> 4]; + output[index + 1] = hex_rep[*i & 0xF]; + index += 3; + } + + output[sizeof(output) - 1] = 0; + outs() << output; } - output[sizeof(output) - 1] = 0; - outs() << output; -} + std::map readSections(const ObjectFile& o) { + error_code ec; + std::map result; + section_iterator i(o.begin_sections()), e(o.end_sections()); + for (; i != e; i.increment(ec)) { + StringRef name; + if (error(i->getName(name))) break; -::Binary::Binary(const std::string& filename) - : triple("unkown-unknown-unknown") -{ - std::string error; + result.insert(make_pair(name.str(), *i)); + } + return result; + } - createBinary(filename, binary); - if (Archive *a = dyn_cast(binary.get())) { - std::cerr << "Got an archive!" << std::endl; - return; + std::map readSymbols(const ObjectFile& o) { + error_code ec; + std::map result; + symbol_iterator si(o.begin_symbols()), se(o.end_symbols()); + for (; si != se; si.increment(ec)) { + StringRef name; + if (error(si->getName(name))) break; + + result.insert(make_pair(name.str(), *si)); + } + return result; } +} - o = dyn_cast(binary.get()); +namespace qtlldb { - triple.setArch(Triple::ArchType(o->getArch())); - std::string tripleName(triple.getTriple()); + Binary::Binary(const std::string& filename) + : triple("unkown-unknown-unknown") + { + std::string error; - target = TargetRegistry::lookupTarget("", triple, error); - if (!target) { - std::cerr << error; - return; - } + createBinary(filename, binary); + if (Archive *a = dyn_cast(binary.get())) { + std::cerr << "Got an archive!" << std::endl; + return; + } - MRI.reset(target->createMCRegInfo(tripleName)); - if (!MRI) { - std::cerr << "error: no register info for target " << tripleName << "\n"; - return; - } + o = dyn_cast(binary.get()); - // Set up disassembler. - AsmInfo.reset(target->createMCAsmInfo(*MRI, tripleName)); - if (!AsmInfo) { - std::cerr << "error: no assembly info for target " << tripleName << "\n"; - return; - } + triple.setArch(Triple::ArchType(o->getArch())); + std::string tripleName(triple.getTriple()); - STI.reset(target->createMCSubtargetInfo(tripleName, "", "")); - if (!STI) { - errs() << "error: no subtarget info for target " << tripleName << "\n"; - return; - } + outs() << tripleName << "\n"; - MII.reset(target->createMCInstrInfo()); - if (!MII) { - std::cerr << "error: no instruction info for target " << tripleName << "\n"; - return; - } + target = TargetRegistry::lookupTarget("", triple, error); + if (!target) { + std::cerr << error; + return; + } - DisAsm.reset(target->createMCDisassembler(*STI)); - if (!DisAsm) { - std::cerr << "error: no disassembler for target " << tripleName << "\n"; - return; - } + outs() << target->getName() << "\n"; - MOFI.reset(new MCObjectFileInfo); - Ctx.reset(new MCContext(AsmInfo.get(), MRI.get(), MOFI.get())); - RelInfo.reset( - target->createMCRelocationInfo(tripleName, *Ctx.get())); - if (RelInfo) { - Symzer.reset( - MCObjectSymbolizer::createObjectSymbolizer(*Ctx.get(), RelInfo, o)); - if (Symzer) - DisAsm->setSymbolizer(Symzer); - } + MRI.reset(target->createMCRegInfo(tripleName)); + if (!MRI) { + std::cerr << "error: no register info for target " << tripleName << "\n"; + return; + } - MIA.reset(target->createMCInstrAnalysis(MII.get())); + // Set up disassembler. + AsmInfo.reset(target->createMCAsmInfo(*MRI, tripleName)); + if (!AsmInfo) { + std::cerr << "error: no assembly info for target " << tripleName << "\n"; + return; + } - int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); - IP.reset(target->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); - if (!IP) { - std::cerr << "error: no instruction printer for target " << tripleName - << '\n'; - return; - } + STI.reset(target->createMCSubtargetInfo(tripleName, "", "")); + if (!STI) { + errs() << "error: no subtarget info for target " << tripleName << "\n"; + return; + } - OwningPtr OD( - new MCObjectDisassembler(*o, *DisAsm, *MIA)); - Mod.reset(OD->buildModule(/* withCFG */ true)); -} + MII.reset(target->createMCInstrInfo()); + if (!MII) { + std::cerr << "error: no instruction info for target " << tripleName << "\n"; + return; + } -void ::Binary::disassemble() { - for (MCModule::const_atom_iterator AI = Mod->atom_begin(), - AE = Mod->atom_end(); - AI != AE; ++AI) { + DisAsm.reset(target->createMCDisassembler(*STI)); + if (!DisAsm) { + std::cerr << "error: no disassembler for target " << tripleName << "\n"; + return; + } - if ((*AI)->getKind() != llvm::MCAtom::TextAtom) - continue; + MOFI.reset(new MCObjectFileInfo); + Ctx.reset(new MCContext(AsmInfo.get(), MRI.get(), MOFI.get())); + RelInfo.reset( + target->createMCRelocationInfo(tripleName, *Ctx.get())); + if (RelInfo) { + Symzer.reset( + MCObjectSymbolizer::createObjectSymbolizer(*Ctx.get(), RelInfo, o)); + if (Symzer) + DisAsm->setSymbolizer(Symzer); + } - outs() << "\n\nAtom " << (*AI)->getName() << ": \n"; - if (const MCTextAtom *TA = dyn_cast(*AI)) { - for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end(); - II != IE; - ++II) { -// II->Inst.dump(); - IP->printInst(&II->Inst, outs(), ""); - outs() << "\n"; - } + MIA.reset(target->createMCInstrAnalysis(MII.get())); + + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); + IP.reset(target->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); + if (!IP) { + std::cerr << "error: no instruction printer for target " << tripleName + << '\n'; + return; } + + OwningPtr OD( + new MCObjectDisassembler(*o, *DisAsm, *MIA)); + Mod.reset(OD->buildModule(/* withCFG */ false)); + + symbols = readSymbols(*o); + sections = readSections(*o); + + // for_each(sections.begin(), sections.end(), [](const std::pair& i){ + // std::cout << "Section: " << i.first << std::endl; + // }); } - outs() << "binary " << triple.getArchName() << "\n"; -} -void ::Binary::disassemble_functions() { - error_code ec; - for (section_iterator i = o->begin_sections(), - e = o->end_sections(); - i != e; i.increment(ec)) { - if (error(ec)) break; - bool text; - if (error(i->isText(text))) break; - if (!text) continue; - - uint64_t SectionAddr; - if (error(i->getAddress(SectionAddr))) break; - - // Make a list of all the symbols in this section. - std::vector > Symbols; - for (symbol_iterator si = o->begin_symbols(), - se = o->end_symbols(); - si != se; si.increment(ec)) { - bool contains; - if (!error(i->containsSymbol(*si, contains)) && contains) { - uint64_t Address; - if (error(si->getAddress(Address))) break; - if (Address == UnknownAddressOrSize) continue; - Address -= SectionAddr; - - StringRef Name; - if (error(si->getName(Name))) break; - - outs() << "\nXXX " << Name << "\n"; - - Symbols.push_back(std::make_pair(Address, Name)); - } - } - // Sort the symbols by address, just in case they didn't come in that way. - array_pod_sort(Symbols.begin(), Symbols.end()); - - // Make a list of all the relocations for this section. - std::vector Rels; - // if (InlineRelocs) { - // for (relocation_iterator ri = i->begin_relocations(), - // re = i->end_relocations(); - // ri != re; ri.increment(ec)) { - // if (error(ec)) break; - // Rels.push_back(*ri); - // } - // } - - // Sort relocations by address. - std::sort(Rels.begin(), Rels.end(), RelocAddressLess); - - StringRef SegmentName = ""; - // if (const MachOObjectFile *MachO = - // dyn_cast(o)) { - // DataRefImpl DR = i->getRawDataRefImpl(); - // SegmentName = MachO->getSectionFinalSegmentName(DR); - // } - StringRef name; - if (error(i->getName(name))) break; - outs() << "Disassembly of section "; - if (!SegmentName.empty()) - outs() << SegmentName << ","; - outs() << name << ':'; - - // If the section has no symbols just insert a dummy one and disassemble - // the whole section. - if (Symbols.empty()) - Symbols.push_back(std::make_pair(0, name)); - - - StringRef Bytes; - if (error(i->getContents(Bytes))) break; - StringRefMemoryObject memoryObject(Bytes); - uint64_t Size; - uint64_t Index; - uint64_t SectSize; - if (error(i->getSize(SectSize))) break; - - std::vector::const_iterator rel_cur = Rels.begin(); - std::vector::const_iterator rel_end = Rels.end(); - // Disassemble symbol by symbol. - for (unsigned si = 0, se = Symbols.size(); si != se; ++si) { - uint64_t Start = Symbols[si].first; - uint64_t End; - // The end is either the size of the section or the beginning of the next - // symbol. - if (si == se - 1) - End = SectSize; - // Make sure this symbol takes up space. - else if (Symbols[si + 1].first != Start) - End = Symbols[si + 1].first - 1; - else - // This symbol has the same address as the next symbol. Skip it. - continue; + std::vector Binary::getSymbols() { + error_code ec; + SectionRef r = sections[".text"]; + std::vector result; + for_each(symbols.begin(), symbols.end(), [&](const std::pair& i) { + bool contains; + if (!error(r.containsSymbol(i.second, contains)) && contains) + result.push_back(i.first); + }); + return result; + } - outs() << '\n' << Symbols[si].second << ":\n"; + void Binary::for_each_instruction(const std::string& function, + std::function callback) { + StringRef bytes; + SymbolRef ref = symbols[function]; + section_iterator sec(o->begin_sections()); + uint64_t base_address, address, ssize, size(0), index, end; + + // outs() << "Start for_each_instruction " << function << "\n"; + + if (error(ref.getSection(sec))) return; + if (error(ref.getAddress(address))) return; + if (address == UnknownAddressOrSize) return; + if (error(ref.getSize(ssize))) return; + if (error(sec->getAddress(base_address))) return; + if (error(sec->getContents(bytes))) return; + + // outs() << "Middle for_each_instruction " << function << " Size: " << ssize << "\n"; + + StringRefMemoryObject memoryObject(bytes); + + for (end = address + ssize - base_address, index = address - base_address; index < end; index += size) { + MCInst Inst; + + if (DisAsm->getInstruction(Inst, size, memoryObject, index, + nulls(), nulls())) { + std::string buf; + llvm::raw_string_ostream s(buf); + IP->printInst(&Inst, s, ""); + + if (index + size < bytes.str().length()) + callback(base_address + index, bytes.str().substr(index, size), s.str()); + + } else { + errs() << "warning: invalid instruction encoding\n"; + if (size == 0) + size = 1; // skip illegible bytes + } + } + // outs() << "End for_each_instruction\n"; -#ifndef NDEBUG - raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); -#else - raw_ostream &DebugOut = nulls(); -#endif + } - for (Index = Start; Index < End; Index += Size) { - MCInst Inst; + void Binary::disassemble() { + for (MCModule::const_atom_iterator AI = Mod->atom_begin(), + AE = Mod->atom_end(); + AI != AE; ++AI) { - if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, - DebugOut, nulls())) { - outs() << format("%8" PRIx64 ":", SectionAddr + Index); - outs() << "\t"; - DumpBytes(StringRef(Bytes.data() + Index, Size)); + if ((*AI)->getKind() != llvm::MCAtom::TextAtom) + continue; - IP->printInst(&Inst, outs(), ""); + outs() << "\n\nAtom " << (*AI)->getName() << ": \n"; + if (const MCTextAtom *TA = dyn_cast(*AI)) { + for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end(); + II != IE; + ++II) { +// II->Inst.dump(); + IP->printInst(&II->Inst, outs(), ""); outs() << "\n"; - } else { - errs() << "warning: invalid instruction encoding\n"; - if (Size == 0) - Size = 1; // skip illegible bytes } + } + } - // Print relocation for instruction. - while (rel_cur != rel_end) { - bool hidden = false; - uint64_t addr; - SmallString<16> name; - SmallString<32> val; + outs() << "binary " << triple.getArchName() << "\n"; + } - // If this relocation is hidden, skip it. - if (error(rel_cur->getHidden(hidden))) goto skip_print_rel; - if (hidden) goto skip_print_rel; + void Binary::disassemble_functions() { + error_code ec; + for (section_iterator i = o->begin_sections(), + e = o->end_sections(); + i != e; i.increment(ec)) { + if (error(ec)) break; + bool text; + if (error(i->isText(text))) break; + if (!text) continue; + + uint64_t SectionAddr; + if (error(i->getAddress(SectionAddr))) break; + + // Make a list of all the symbols in this section. + std::vector > Symbols; + for (symbol_iterator si = o->begin_symbols(), + se = o->end_symbols(); + si != se; si.increment(ec)) { + bool contains; + if (!error(i->containsSymbol(*si, contains)) && contains) { + uint64_t Address; + if (error(si->getAddress(Address))) break; + if (Address == UnknownAddressOrSize) continue; + Address -= SectionAddr; + + StringRef Name; + if (error(si->getName(Name))) break; + + outs() << "\nXXX " << Name << "\n"; + + Symbols.push_back(std::make_pair(Address, Name)); + } + } - if (error(rel_cur->getOffset(addr))) goto skip_print_rel; - // Stop when rel_cur's address is past the current instruction. - if (addr >= Index + Size) break; - if (error(rel_cur->getTypeName(name))) goto skip_print_rel; - if (error(rel_cur->getValueString(val))) goto skip_print_rel; + // Sort the symbols by address, just in case they didn't come in that way. + array_pod_sort(Symbols.begin(), Symbols.end()); + + // Make a list of all the relocations for this section. + std::vector Rels; + // if (InlineRelocs) { + // for (relocation_iterator ri = i->begin_relocations(), + // re = i->end_relocations(); + // ri != re; ri.increment(ec)) { + // if (error(ec)) break; + // Rels.push_back(*ri); + // } + // } + + // Sort relocations by address. + std::sort(Rels.begin(), Rels.end(), RelocAddressLess); + + StringRef SegmentName = ""; + // if (const MachOObjectFile *MachO = + // dyn_cast(o)) { + // DataRefImpl DR = i->getRawDataRefImpl(); + // SegmentName = MachO->getSectionFinalSegmentName(DR); + // } + StringRef name; + if (error(i->getName(name))) break; + outs() << "Disassembly of section "; + if (!SegmentName.empty()) + outs() << SegmentName << ","; + outs() << name << ':'; + + // If the section has no symbols just insert a dummy one and disassemble + // the whole section. + if (Symbols.empty()) + Symbols.push_back(std::make_pair(0, name)); + + + StringRef Bytes; + if (error(i->getContents(Bytes))) break; + StringRefMemoryObject memoryObject(Bytes); + uint64_t Size; + uint64_t Index; + uint64_t SectSize; + if (error(i->getSize(SectSize))) break; + + std::vector::const_iterator rel_cur = Rels.begin(); + std::vector::const_iterator rel_end = Rels.end(); + // Disassemble symbol by symbol. + for (unsigned si = 0, se = Symbols.size(); si != se; ++si) { + uint64_t Start = Symbols[si].first; + uint64_t End; + // The end is either the size of the section or the beginning of the next + // symbol. + if (si == se - 1) + End = SectSize; + // Make sure this symbol takes up space. + else if (Symbols[si + 1].first != Start) + End = Symbols[si + 1].first - 1; + else + // This symbol has the same address as the next symbol. Skip it. + continue; + + outs() << '\n' << Symbols[si].second << ":\n"; - outs() << format("\t\t\t%8" PRIx64 ": ", SectionAddr + addr) << name - << "\t" << val << "\n"; +#ifndef NDEBUG + raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); +#else + raw_ostream &DebugOut = nulls(); +#endif - skip_print_rel: - ++rel_cur; + for (Index = Start; Index < End; Index += Size) { + MCInst Inst; + + if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, + DebugOut, nulls())) { + outs() << format("%8" PRIx64 ":", SectionAddr + Index); + outs() << "\t"; + DumpBytes(StringRef(Bytes.data() + Index, Size)); + + IP->printInst(&Inst, outs(), ""); + outs() << "\n"; + } else { + errs() << "warning: invalid instruction encoding\n"; + if (Size == 0) + Size = 1; // skip illegible bytes + } + + // Print relocation for instruction. + while (rel_cur != rel_end) { + bool hidden = false; + uint64_t addr; + SmallString<16> name; + SmallString<32> val; + + // If this relocation is hidden, skip it. + if (error(rel_cur->getHidden(hidden))) goto skip_print_rel; + if (hidden) goto skip_print_rel; + + if (error(rel_cur->getOffset(addr))) goto skip_print_rel; + // Stop when rel_cur's address is past the current instruction. + if (addr >= Index + Size) break; + if (error(rel_cur->getTypeName(name))) goto skip_print_rel; + if (error(rel_cur->getValueString(val))) goto skip_print_rel; + + outs() << format("\t\t\t%8" PRIx64 ": ", SectionAddr + addr) << name + << "\t" << val << "\n"; + + skip_print_rel: + ++rel_cur; + } } } } } -} -void ::Binary::disassemble_cfg() { - for (MCModule::const_func_iterator FI = Mod->func_begin(), - FE = Mod->func_end(); - FI != FE; ++FI) { - static int filenum = 0; - std::string FileName = std::string("dot/") + (Twine((*FI)->getName()) + "_" + utostr(filenum) + ".dot").str(); + void Binary::disassemble_cfg() { + for (MCModule::const_func_iterator FI = Mod->func_begin(), + FE = Mod->func_end(); + FI != FE; ++FI) { + static int filenum = 0; + std::string FileName = std::string("dot/") + (Twine((*FI)->getName()) + "_" + utostr(filenum) + ".dot").str(); - std::cerr << FileName << std::endl; + std::cerr << FileName << std::endl; // Start a new dot file. - std::string Error; - raw_fd_ostream Out(FileName.c_str(), Error); - if (!Error.empty()) { - errs() << "llvm-objdump: warning: " << Error << '\n'; - return; - } - - Out << "digraph \"" << (*FI)->getName() << "\" {\n"; - Out << "graph [ rankdir = \"LR\" ];\n"; - for (MCFunction::const_iterator i = (*FI)->begin(), e = (*FI)->end(); i != e; ++i) { - // Only print blocks that have predecessors. - bool hasPreds = (*i)->pred_begin() != (*i)->pred_end(); + std::string Error; + raw_fd_ostream Out(FileName.c_str(), Error); + if (!Error.empty()) { + errs() << "llvm-objdump: warning: " << Error << '\n'; + return; + } - if (!hasPreds && i != (*FI)->begin()) - continue; + Out << "digraph \"" << (*FI)->getName() << "\" {\n"; + Out << "graph [ rankdir = \"LR\" ];\n"; + for (MCFunction::const_iterator i = (*FI)->begin(), e = (*FI)->end(); i != e; ++i) { + // Only print blocks that have predecessors. + bool hasPreds = (*i)->pred_begin() != (*i)->pred_end(); + + if (!hasPreds && i != (*FI)->begin()) + continue; + + Out << '"' << (*i)->getInsts()->getBeginAddr() << "\" [ label=\""; + // Print instructions. + for (unsigned ii = 0, ie = (*i)->getInsts()->size(); ii != ie; + ++ii) { + if (ii != 0) // Not the first line, start a new row. + Out << '|'; + if (ii + 1 == ie) // Last line, add an end id. + Out << ""; + + // Escape special chars and print the instruction in mnemonic form. + std::string Str; + raw_string_ostream OS(Str); + IP->printInst(&(*i)->getInsts()->at(ii).Inst, OS, ""); + Out << DOT::EscapeString(OS.str()); + } + Out << "\" shape=\"record\" ];\n"; - Out << '"' << (*i)->getInsts()->getBeginAddr() << "\" [ label=\""; - // Print instructions. - for (unsigned ii = 0, ie = (*i)->getInsts()->size(); ii != ie; - ++ii) { - if (ii != 0) // Not the first line, start a new row. - Out << '|'; - if (ii + 1 == ie) // Last line, add an end id. - Out << ""; - - // Escape special chars and print the instruction in mnemonic form. - std::string Str; - raw_string_ostream OS(Str); - IP->printInst(&(*i)->getInsts()->at(ii).Inst, OS, ""); - Out << DOT::EscapeString(OS.str()); + // Add edges. + for (MCBasicBlock::succ_const_iterator si = (*i)->succ_begin(), + se = (*i)->succ_end(); si != se; ++si) + Out << (*i)->getInsts()->getBeginAddr() << ":o -> " + << (*si)->getInsts()->getBeginAddr() << ":a\n"; } - Out << "\" shape=\"record\" ];\n"; + Out << "}\n"; - // Add edges. - for (MCBasicBlock::succ_const_iterator si = (*i)->succ_begin(), - se = (*i)->succ_end(); si != se; ++si) - Out << (*i)->getInsts()->getBeginAddr() << ":o -> " - << (*si)->getInsts()->getBeginAddr() << ":a\n"; + ++filenum; } - Out << "}\n"; - - ++filenum; } } diff --git a/src/Binary.hxx b/src/Binary.hxx index 31d7485..180d8ee 100644 --- a/src/Binary.hxx +++ b/src/Binary.hxx @@ -1,34 +1,52 @@ +#ifndef INCLUDE__Binary_hxx +#define INCLUDE__Binary_hxx + #include "include.hxx" +#include "Section.hxx" #include +#include +#include using llvm::OwningPtr; -class Binary { -private: - llvm::Triple triple; - const llvm::Target * target; - llvm::object::ObjectFile * o; - - OwningPtr binary; - OwningPtr MRI; - OwningPtr AsmInfo; - OwningPtr Mod; - OwningPtr IP; - OwningPtr DisAsm; - OwningPtr MOFI; - OwningPtr Ctx; - OwningPtr MIA; - OwningPtr STI; - OwningPtr MII; - OwningPtr RelInfo; - OwningPtr Symzer; -public: - Binary(const std::string& filename); - - void disassemble(); - - void disassemble_functions(); - - void disassemble_cfg(); -}; +namespace qtlldb { + class Binary { + public: + Binary(const std::string& filename); + + void disassemble(); + + void disassemble_functions(); + + void disassemble_cfg(); + + std::vector getSymbols(); + + std::vector getFunctions(); + void for_each_instruction(const std::string& function, std::function callback); + + private: + llvm::Triple triple; + const llvm::Target * target; + llvm::object::ObjectFile * o; + + OwningPtr binary; + OwningPtr MRI; + OwningPtr AsmInfo; + OwningPtr Mod; + OwningPtr IP; + OwningPtr DisAsm; + OwningPtr MOFI; + OwningPtr Ctx; + OwningPtr MIA; + OwningPtr STI; + OwningPtr MII; + OwningPtr RelInfo; + OwningPtr Symzer; + + std::map sections; + std::map symbols; + }; +} +#endif diff --git a/src/gui/Mainwindow.cxx b/src/gui/Mainwindow.cxx index 3e26227..412c424 100644 --- a/src/gui/Mainwindow.cxx +++ b/src/gui/Mainwindow.cxx @@ -1,31 +1,41 @@ #include "Mainwindow.h++" +#include +#include + #include +namespace { + +} + Mainwindow::Mainwindow() { - // openAction = new QAction(tr("&Open"), this); + openAction = new QAction(tr("&Open"), this); // saveAction = new QAction(tr("&Save"), this); exitAction = new QAction(tr("E&xit"), this); - // connect(openAction, SIGNAL(triggered()), this, SLOT(open())); + connect(openAction, SIGNAL(triggered()), this, SLOT(open())); // connect(saveAction, SIGNAL(triggered()), this, SLOT(save())); connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit())); fileMenu = menuBar()->addMenu(tr("&File")); - // fileMenu->addAction(openAction); + fileMenu->addAction(openAction); // fileMenu->addAction(saveAction); - // fileMenu->addSeparator(); + fileMenu->addSeparator(); fileMenu->addAction(exitAction); - // - // setCentralWidget(textEdit); + listWidget = new QListWidget(); + stackedWidget = new QStackedWidget(); + dockWidget = new QDockWidget(tr("Functions"), this); + dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | + Qt::RightDockWidgetArea); + dockWidget->setWidget(listWidget); + addDockWidget(Qt::LeftDockWidgetArea, dockWidget); + setCentralWidget(stackedWidget); - tabwidget = new QTabWidget; - setCentralWidget(tabwidget); - - textEdit = new QTextEdit; - tabwidget->addTab(textEdit, "edit"); + connect(listWidget, SIGNAL(currentRowChanged(int)), + stackedWidget, SLOT(setCurrentIndex(int))); setWindowTitle(tr("Notepad")); } @@ -42,5 +52,53 @@ void Mainwindow::quit() } void Mainwindow::open() { + QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", + tr("Binaries (*)")); + + if (fileName != "") { + curBin = new qtlldb::Binary(fileName.toStdString()); + + std::vector symbols = curBin->getSymbols(); + if (0 == symbols.size()) + populateSymbolInformation(".text"); + for (std::vector::iterator it = symbols.begin(); + it != symbols.end(); + ++it) { + populateSymbolInformation(*it); + } + } +} + +void Mainwindow::populateSymbolInformation(const std::string& sym) { + QTabWidget * w = new QTabWidget(); + + // Listing + QTableWidget * t = new QTableWidget(); + t->setColumnCount(3); + t->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); + curBin->for_each_instruction(sym, [&t](long add, std::string bytes, std::string mnemonic) { + int row = t->rowCount(); + std::stringstream s; + t->setRowCount(t->rowCount() + 1); + s << std::hex << add; + t->setItem(row,0,new QTableWidgetItem(s.str().c_str())); + s.str(""); + s << std::hex; + for_each(bytes.begin(), bytes.end(), [&s](char c){s << (unsigned int)((unsigned char)c) << ' ';}); + t->setItem(row,1,new QTableWidgetItem(s.str().c_str())); + t->setItem(row,2,new QTableWidgetItem(mnemonic.c_str() + 1)); + }); + w->addTab(t, "Listing"); + + // CFG + QGraphicsScene * scene = new QGraphicsScene; + QGraphicsRectItem *rect = scene->addRect(QRectF(0, 0, 100, 100)); + rect->setFlag(QGraphicsItem::ItemIsMovable); + QGraphicsView * view = new QGraphicsView(scene); + w->addTab(view, "CFG"); + + + listWidget->addItem(sym.c_str()); + stackedWidget->addWidget(w); } diff --git a/src/gui/Mainwindow.h++ b/src/gui/Mainwindow.h++ index daf9d3d..46a6676 100644 --- a/src/gui/Mainwindow.h++ +++ b/src/gui/Mainwindow.h++ @@ -1,23 +1,34 @@ #include "include.hxx" - #include #include #include +#include +#include +#include "Binary.hxx" class Mainwindow : public QMainWindow { Q_OBJECT +public: + Mainwindow(); private: + void populateSymbolInformation(const std::string& sym); + QTextEdit *textEdit; QPushButton *quitButton; - QAction *exitAction; QMenu *fileMenu; + QTabWidget * tabwidget; + QListWidget * listWidget; + QStackedWidget * stackedWidget; + QDockWidget * dockWidget; + + QAction *exitAction; + QAction *openAction; + + qtlldb::Binary * curBin; private slots: void quit(); void open(); - -public: - Mainwindow(); }; -- 2.39.2