X-Git-Url: https://git.siccegge.de//index.cgi?p=frida%2Ffrida.git;a=blobdiff_plain;f=src%2FBinary.cxx;h=d57db4e720f3bd6b4d5b5329341a2bdc091b66cc;hp=696947d0262abd1d0ecc992ebc9918120d200283;hb=9023eb3885faa52eb9729b61b401e5b131199c0d;hpb=988726af7276c31122cd2e27adae87aa8b4049ad diff --git a/src/Binary.cxx b/src/Binary.cxx index 696947d..d57db4e 100644 --- a/src/Binary.cxx +++ b/src/Binary.cxx @@ -8,44 +8,44 @@ using namespace llvm; using namespace llvm::object; static bool error(error_code ec) { - if (!ec) return false; + 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; + 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; - } - - output[sizeof(output) - 1] = 0; - outs() << output; + 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; } ::Binary::Binary(const std::string& filename) @@ -177,6 +177,9 @@ void ::Binary::disassemble_functions() { StringRef Name; if (error(si->getName(Name))) break; + + outs() << "\nXXX " << Name << "\n"; + Symbols.push_back(std::make_pair(Address, Name)); } } @@ -294,3 +297,58 @@ void ::Binary::disassemble_functions() { } } } + +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; + + // 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(); + + 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"; + + // 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 << "}\n"; + + ++filenum; + } +}