diff options
author | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2013-08-21 07:28:44 +0000 |
---|---|---|
committer | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2013-08-21 07:28:44 +0000 |
commit | 0e83b902834530da4670ad8416cf44afba9b4111 (patch) | |
tree | 62dd59d82ab30e22bd7ce7dd769c42b05768d8a4 | |
parent | fe018c414542141010ef0706820ebfde0a4b3e41 (diff) | |
download | external_llvm-0e83b902834530da4670ad8416cf44afba9b4111.zip external_llvm-0e83b902834530da4670ad8416cf44afba9b4111.tar.gz external_llvm-0e83b902834530da4670ad8416cf44afba9b4111.tar.bz2 |
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188886 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/MC/MCObjectDisassembler.h | 31 | ||||
-rw-r--r-- | lib/MC/MCObjectDisassembler.cpp | 89 |
2 files changed, 120 insertions, 0 deletions
diff --git a/include/llvm/MC/MCObjectDisassembler.h b/include/llvm/MC/MCObjectDisassembler.h index edaf7dc..4ac3456 100644 --- a/include/llvm/MC/MCObjectDisassembler.h +++ b/include/llvm/MC/MCObjectDisassembler.h @@ -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 diff --git a/lib/MC/MCObjectDisassembler.cpp b/lib/MC/MCObjectDisassembler.cpp index 4ce8e92..1969bcb 100644 --- a/lib/MC/MCObjectDisassembler.cpp +++ b/lib/MC/MCObjectDisassembler.cpp @@ -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(MCModule *Module) { } } } + +// 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); +} |