Index: include/llvm/Object/MachO.h =================================================================== --- include/llvm/Object/MachO.h +++ include/llvm/Object/MachO.h @@ -228,10 +228,12 @@ return v->isMachO(); } + const char *getSectionPointer(DataRefImpl Rel) const; + private: - typedef SmallVector SectionList; + typedef SmallVector SectionList; SectionList Sections; - typedef SmallVector LibraryList; + typedef SmallVector LibraryList; LibraryList Libraries; typedef SmallVector LibraryShortName; LibraryShortName LibrariesShortNames; Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -105,14 +105,9 @@ void finalizeLoad(ObjectImage &ObjImg, ObjSectionToIDMap &SectionMap) override; - static ObjectImage *createObjectImage(ObjectBuffer *InputBuffer) { - return new ObjectImageCommon(InputBuffer); - } - + static ObjectImage *createObjectImage(ObjectBuffer *Buffer); static ObjectImage * - createObjectImageFromFile(std::unique_ptr InputObject) { - return new ObjectImageCommon(std::move(InputObject)); - } + createObjectImageFromFile(std::unique_ptr InputObject); }; } // end namespace llvm Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -14,6 +14,8 @@ #include "RuntimeDyldMachO.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "ObjectImageCommon.h" +#include "JITRegistrar.h" using namespace llvm; using namespace llvm::object; @@ -21,6 +23,123 @@ namespace llvm { +class MachOObjectImage : public ObjectImageCommon { +private: + typedef SmallVector SectionAddrList; + SectionAddrList OldSectionAddrList; + +protected: + bool is64; + bool Registered; + +private: + void initOldAddress() { + MachOObjectFile *objf = static_cast(ObjFile.get()); + // Unfortunately we need to do this, since there's information encoded + // in the original addr of the section that we could not otherwise + // recover. The reason for this is that symbols do not actually store + // their file offset, but only their vmaddr. This means that in order + // to locate the symbol correctly in the object file, we need to know + // where the original start of the section was (including any padding, + // etc). + for (section_iterator i = objf->section_begin(), e = objf->section_end(); + i != e; ++i) { + uint64_t Addr; + i->getAddress(Addr); + OldSectionAddrList[i->getRawDataRefImpl().d.a] = Addr; + } + } + +public: + MachOObjectImage(ObjectBuffer *Input, bool is64) + : ObjectImageCommon(Input), + OldSectionAddrList(ObjFile->section_end()->getRawDataRefImpl().d.a, 0), + is64(is64), Registered(false) { + initOldAddress(); + } + + MachOObjectImage(std::unique_ptr Input, bool is64) + : ObjectImageCommon(std::move(Input)), + OldSectionAddrList(ObjFile->section_end()->getRawDataRefImpl().d.a, 0), + is64(is64), Registered(false) { + initOldAddress(); + } + + virtual ~MachOObjectImage() {} + + // Subclasses can override these methods to update the image with loaded + // addresses for sections and common symbols + virtual void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) { + MachOObjectFile *objf = static_cast(ObjFile.get()); + char *data = + const_cast(objf->getSectionPointer(Sec.getRawDataRefImpl())); + + uint64_t oldAddr = OldSectionAddrList[Sec.getRawDataRefImpl().d.a]; + + if (is64) { + ((MachO::section_64 *)data)->addr = Addr; + } else { + ((MachO::section *)data)->addr = Addr; + } + + for (symbol_iterator i = objf->symbol_begin(), e = objf->symbol_end(); + i != e; ++i) { + section_iterator symSec(objf->section_end()); + (*i).getSection(symSec); + if (*symSec == Sec) { + uint64_t symAddr; + (*i).getAddress(symAddr); + updateSymbolAddress(*i, symAddr + Addr - oldAddr); + } + } + } + + uint64_t getOldSectionAddr(const SectionRef &Sec) const { + return OldSectionAddrList[Sec.getRawDataRefImpl().d.a]; + } + + virtual void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) { + char *data = const_cast( + reinterpret_cast(Sym.getRawDataRefImpl().p)); + if (is64) + ((MachO::nlist_64 *)data)->n_value = Addr; + else + ((MachO::nlist *)data)->n_value = Addr; + } + + virtual void registerWithDebugger() { + JITRegistrar::getGDBRegistrar().registerObject(*Buffer); + Registered = true; + } + + virtual void deregisterWithDebugger() { + JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer); + } +}; + +ObjectImage *RuntimeDyldMachO::createObjectImage(ObjectBuffer *Buffer) { + uint32_t magic = *((uint32_t *)Buffer->getBufferStart()); + bool is64 = (magic == MachO::MH_MAGIC_64); + assert((magic == MachO::MH_MAGIC_64 || magic == MachO::MH_MAGIC) && + "Unrecognized Macho Magic"); + return new MachOObjectImage(Buffer, is64); +} + +ObjectImage *RuntimeDyldMachO::createObjectImageFromFile( + std::unique_ptr ObjFile) { + if (!ObjFile) + return nullptr; + + MemoryBuffer *Buffer = + MemoryBuffer::getMemBuffer(ObjFile->getData(), "", false); + + uint32_t magic = *((uint32_t *)Buffer->getBufferStart()); + bool is64 = (magic == MachO::MH_MAGIC_64); + assert((magic == MachO::MH_MAGIC_64 || magic == MachO::MH_MAGIC) && + "Unrecognized Macho Magic"); + return new MachOObjectImage(std::move(ObjFile), is64); +} + static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, intptr_t DeltaForEH) { DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText @@ -533,6 +652,7 @@ ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs) { const ObjectFile *OF = Obj.getObjectFile(); + const MachOObjectImage &MachOObj = *static_cast(&Obj); const MachOObjectFile *MachO = static_cast(OF); MachO::any_relocation_info RE = MachO->getRelocation(RelI->getRawDataRefImpl()); @@ -609,8 +729,8 @@ bool IsCode = false; Sec.isText(IsCode); Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); - uint64_t Addr; - Sec.getAddress(Addr); + uint64_t Addr = MachOObj.getOldSectionAddr(Sec); + DEBUG(dbgs() << "\nAddr: " << Addr << "\nAddend: " << Addend); Value.Addend = Addend - Addr; if (IsPCRel) Value.Addend += Offset + NumBytes; Index: lib/Object/MachOObjectFile.cpp =================================================================== --- lib/Object/MachOObjectFile.cpp +++ lib/Object/MachOObjectFile.cpp @@ -1797,7 +1797,7 @@ bool MachOObjectFile::is64Bit() const { return getType() == getMachOType(false, true) || - getType() == getMachOType(true, true); + getType() == getMachOType(true, true); } void MachOObjectFile::ReadULEB128s(uint64_t Index, @@ -1812,6 +1812,10 @@ } } +const char *MachOObjectFile::getSectionPointer(DataRefImpl Rel) const { + return Sections[Rel.d.a]; +} + ErrorOr ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer, bool BufferOwned) { StringRef Magic = Buffer->getBuffer().slice(0, 4);