[llvm] r188886 - MC CFG: Add MCObjectDisassembler Mach-O implementation.

Ahmed Bougacha ahmed.bougacha at gmail.com
Wed Aug 21 00:28:44 PDT 2013


Author: ab
Date: Wed Aug 21 02:28:44 2013
New Revision: 188886

URL: http://llvm.org/viewvc/llvm-project?rev=188886&view=rev
Log:
MC CFG: Add MCObjectDisassembler Mach-O implementation.

Supports:
- entrypoint, using LC_MAIN.
- static ctors/dtors, using __mod_{init,exit}_func
- translation between effective and object load address, using
  dyld's VM address slide.

Modified:
    llvm/trunk/include/llvm/MC/MCObjectDisassembler.h
    llvm/trunk/lib/MC/MCObjectDisassembler.cpp

Modified: llvm/trunk/include/llvm/MC/MCObjectDisassembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectDisassembler.h?rev=188886&r1=188885&r2=188886&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCObjectDisassembler.h (original)
+++ llvm/trunk/include/llvm/MC/MCObjectDisassembler.h Wed Aug 21 02:28:44 2013
@@ -23,6 +23,7 @@ namespace llvm {
 
 namespace object {
   class ObjectFile;
+  class MachOObjectFile;
 }
 
 class MCBasicBlock;
@@ -100,6 +101,36 @@ private:
   void buildCFG(MCModule *Module);
 };
 
+class MCMachOObjectDisassembler : public MCObjectDisassembler {
+  const object::MachOObjectFile &MOOF;
+
+  uint64_t VMAddrSlide;
+  uint64_t HeaderLoadAddress;
+
+  // __DATA;__mod_init_func support.
+  llvm::StringRef ModInitContents;
+  // __DATA;__mod_exit_func support.
+  llvm::StringRef ModExitContents;
+
+public:
+  /// \brief Construct a Mach-O specific object disassembler.
+  /// \param VMAddrSlide The virtual address slide applied by dyld.
+  /// \param HeaderLoadAddress The load address of the mach_header for this
+  /// object.
+  MCMachOObjectDisassembler(const object::MachOObjectFile &MOOF,
+                            const MCDisassembler &Dis,
+                            const MCInstrAnalysis &MIA, uint64_t VMAddrSlide,
+                            uint64_t HeaderLoadAddress);
+
+protected:
+  uint64_t getEffectiveLoadAddr(uint64_t Addr) LLVM_OVERRIDE;
+  uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr) LLVM_OVERRIDE;
+  uint64_t getEntrypoint() LLVM_OVERRIDE;
+
+  ArrayRef<uint64_t> getStaticInitFunctions() LLVM_OVERRIDE;
+  ArrayRef<uint64_t> getStaticExitFunctions() LLVM_OVERRIDE;
+};
+
 }
 
 #endif

Modified: llvm/trunk/lib/MC/MCObjectDisassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectDisassembler.cpp?rev=188886&r1=188885&r2=188886&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectDisassembler.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectDisassembler.cpp Wed Aug 21 02:28:44 2013
@@ -18,7 +18,10 @@
 #include "llvm/MC/MCFunction.h"
 #include "llvm/MC/MCInstrAnalysis.h"
 #include "llvm/MC/MCModule.h"
+#include "llvm/Object/MachO.h"
 #include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/MachO.h"
 #include "llvm/Support/MemoryObject.h"
 #include "llvm/Support/StringRefMemoryObject.h"
 #include "llvm/Support/raw_ostream.h"
@@ -285,3 +288,89 @@ void MCObjectDisassembler::buildCFG(MCMo
     }
   }
 }
+
+// MachO MCObjectDisassembler implementation.
+
+MCMachOObjectDisassembler::MCMachOObjectDisassembler(
+    const MachOObjectFile &MOOF, const MCDisassembler &Dis,
+    const MCInstrAnalysis &MIA, uint64_t VMAddrSlide,
+    uint64_t HeaderLoadAddress)
+    : MCObjectDisassembler(MOOF, Dis, MIA), MOOF(MOOF),
+      VMAddrSlide(VMAddrSlide), HeaderLoadAddress(HeaderLoadAddress) {
+
+  error_code ec;
+  for (section_iterator SI = MOOF.begin_sections(), SE = MOOF.end_sections();
+       SI != SE; SI.increment(ec)) {
+    if (ec)
+      break;
+    StringRef Name;
+    SI->getName(Name);
+    // FIXME: We should use the S_ section type instead of the name.
+    if (Name == "__mod_init_func") {
+      DEBUG(dbgs() << "Found __mod_init_func section!\n");
+      SI->getContents(ModInitContents);
+    } else if (Name == "__mod_exit_func") {
+      DEBUG(dbgs() << "Found __mod_exit_func section!\n");
+      SI->getContents(ModExitContents);
+    }
+  }
+}
+
+// FIXME: Only do the translations for addresses actually inside the object.
+uint64_t MCMachOObjectDisassembler::getEffectiveLoadAddr(uint64_t Addr) {
+  return Addr + VMAddrSlide;
+}
+
+uint64_t
+MCMachOObjectDisassembler::getOriginalLoadAddr(uint64_t EffectiveAddr) {
+  return EffectiveAddr - VMAddrSlide;
+}
+
+uint64_t MCMachOObjectDisassembler::getEntrypoint() {
+  uint64_t EntryFileOffset = 0;
+
+  // Look for LC_MAIN.
+  {
+    uint32_t LoadCommandCount = MOOF.getHeader().NumLoadCommands;
+    MachOObjectFile::LoadCommandInfo Load = MOOF.getFirstLoadCommandInfo();
+    for (unsigned I = 0;; ++I) {
+      if (Load.C.Type == MachO::LoadCommandMain) {
+        EntryFileOffset =
+            ((const MachO::entry_point_command *)Load.Ptr)->entryoff;
+        break;
+      }
+
+      if (I == LoadCommandCount - 1)
+        break;
+      else
+        Load = MOOF.getNextLoadCommandInfo(Load);
+    }
+  }
+
+  // If we didn't find anything, default to the common implementation.
+  // FIXME: Maybe we could also look at LC_UNIXTHREAD and friends?
+  if (EntryFileOffset)
+    return MCObjectDisassembler::getEntrypoint();
+
+  return EntryFileOffset + HeaderLoadAddress;
+}
+
+ArrayRef<uint64_t> MCMachOObjectDisassembler::getStaticInitFunctions() {
+  // FIXME: We only handle 64bit mach-o
+  assert(MOOF.is64Bit());
+
+  size_t EntrySize = 8;
+  size_t EntryCount = ModInitContents.size() / EntrySize;
+  return ArrayRef<uint64_t>(
+      reinterpret_cast<const uint64_t *>(ModInitContents.data()), EntryCount);
+}
+
+ArrayRef<uint64_t> MCMachOObjectDisassembler::getStaticExitFunctions() {
+  // FIXME: We only handle 64bit mach-o
+  assert(MOOF.is64Bit());
+
+  size_t EntrySize = 8;
+  size_t EntryCount = ModExitContents.size() / EntrySize;
+  return ArrayRef<uint64_t>(
+      reinterpret_cast<const uint64_t *>(ModExitContents.data()), EntryCount);
+}





More information about the llvm-commits mailing list