]> git.siccegge.de Git - frida/frida.git/blobdiff - src/Binary.cxx
Update
[frida/frida.git] / src / Binary.cxx
index 696947d0262abd1d0ecc992ebc9918120d200283..d57db4e720f3bd6b4d5b5329341a2bdc091b66cc 100644 (file)
@@ -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=\"<a>";
+            // 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 << "<o>";
+
+                // 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;
+    }
+}