From 6256b03674f4d50d1c035aa3ecba45df1345ea79 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 22 Apr 2011 03:19:48 +0000 Subject: Add an ObjectFile implementation for mach-o. Patch by Patrick Walton! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129974 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 330 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 lib/Object/MachOObjectFile.cpp (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp new file mode 100644 index 0000000..4a00324 --- /dev/null +++ b/lib/Object/MachOObjectFile.cpp @@ -0,0 +1,330 @@ +//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MachOObjectFile class, which binds the MachOObject +// class to the generic ObjectFile wrapper. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Triple.h" +#include "llvm/Object/MachOFormat.h" +#include "llvm/Object/MachOObject.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/MemoryBuffer.h" + +#include +#include +#include + +using namespace llvm; +using namespace object; + +namespace llvm { + +typedef MachOObject::LoadCommandInfo LoadCommandInfo; + +class MachOObjectFile : public ObjectFile { +public: + MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO) + : ObjectFile(Object), + MachOObj(MOO), + RegisteredStringTable(std::numeric_limits::max()) {} + + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; + +protected: + virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; + virtual StringRef getSymbolName(DataRefImpl Symb) const; + virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; + virtual uint64_t getSymbolSize(DataRefImpl Symb) const; + virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; + virtual bool isSymbolInternal(DataRefImpl Symb) const; + + virtual SectionRef getSectionNext(DataRefImpl Sec) const; + virtual StringRef getSectionName(DataRefImpl Sec) const; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const; + virtual uint64_t getSectionSize(DataRefImpl Sec) const; + virtual StringRef getSectionContents(DataRefImpl Sec) const; + virtual bool isSectionText(DataRefImpl Sec) const; + +private: + MachOObject *MachOObj; + mutable uint32_t RegisteredStringTable; + + void moveToNextSection(DataRefImpl &DRI) const; + void getSymbolTableEntry(DataRefImpl DRI, + InMemoryStruct &Res) const; + void moveToNextSymbol(DataRefImpl &DRI) const; + void getSection(DataRefImpl DRI, InMemoryStruct &Res) const; +}; + +ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { + std::string Err; + MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); + if (!MachOObj) + return NULL; + return new MachOObjectFile(Buffer, MachOObj); +} + +/*===-- Symbols -----------------------------------------------------------===*/ + +void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { + uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + if (LCI.Command.Type == macho::LCT_Symtab) { + InMemoryStruct SymtabLoadCmd; + MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); + if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) + return; + } + + DRI.d.a++; + DRI.d.b = 0; + } +} + +void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, + InMemoryStruct &Res) const { + InMemoryStruct SymtabLoadCmd; + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); + + if (RegisteredStringTable != DRI.d.a) { + MachOObj->RegisterStringTable(*SymtabLoadCmd); + RegisteredStringTable = DRI.d.a; + } + + MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, + Res); +} + + +SymbolRef MachOObjectFile::getSymbolNext(DataRefImpl DRI) const { + DRI.d.b++; + moveToNextSymbol(DRI); + return SymbolRef(DRI, this); +} + +StringRef MachOObjectFile::getSymbolName(DataRefImpl DRI) const { + InMemoryStruct Entry; + getSymbolTableEntry(DRI, Entry); + return MachOObj->getStringAtIndex(Entry->StringIndex); +} + +uint64_t MachOObjectFile::getSymbolAddress(DataRefImpl DRI) const { + InMemoryStruct Entry; + getSymbolTableEntry(DRI, Entry); + return Entry->Value; +} + +uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const { + return UnknownAddressOrSize; +} + +char MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI) const { + InMemoryStruct Entry; + getSymbolTableEntry(DRI, Entry); + + char Char; + switch (Entry->Type & macho::STF_TypeMask) { + case macho::STT_Undefined: + Char = 'u'; + break; + case macho::STT_Absolute: + case macho::STT_Section: + Char = 's'; + break; + default: + Char = '?'; + break; + } + + if (Entry->Flags & (macho::STF_External | macho::STF_PrivateExtern)) + Char = toupper(Char); + return Char; +} + +bool MachOObjectFile::isSymbolInternal(DataRefImpl DRI) const { + InMemoryStruct Entry; + getSymbolTableEntry(DRI, Entry); + return Entry->Flags & macho::STF_StabsEntryMask; +} + +ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const { + // DRI.d.a = segment number; DRI.d.b = symbol index. + DataRefImpl DRI; + DRI.d.a = DRI.d.b = 0; + moveToNextSymbol(DRI); + return symbol_iterator(SymbolRef(DRI, this)); +} + +ObjectFile::symbol_iterator MachOObjectFile::end_symbols() const { + DataRefImpl DRI; + DRI.d.a = MachOObj->getHeader().NumLoadCommands; + DRI.d.b = 0; + return symbol_iterator(SymbolRef(DRI, this)); +} + + +/*===-- Sections ----------------------------------------------------------===*/ + +void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { + uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + if (LCI.Command.Type == macho::LCT_Segment) { + InMemoryStruct SegmentLoadCmd; + MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); + if (DRI.d.b < SegmentLoadCmd->NumSections) + return; + } else if (LCI.Command.Type == macho::LCT_Segment64) { + InMemoryStruct Segment64LoadCmd; + MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); + if (DRI.d.b < Segment64LoadCmd->NumSections) + return; + } + + DRI.d.a++; + DRI.d.b = 0; + } +} + +SectionRef MachOObjectFile::getSectionNext(DataRefImpl DRI) const { + DRI.d.b++; + moveToNextSection(DRI); + return SectionRef(DRI, this); +} + +void +MachOObjectFile::getSection(DataRefImpl DRI, + InMemoryStruct &Res) const { + InMemoryStruct SLC; + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + MachOObj->ReadSegmentLoadCommand(LCI, SLC); + MachOObj->ReadSection(LCI, DRI.d.b, Res); +} + +StringRef MachOObjectFile::getSectionName(DataRefImpl DRI) const { + InMemoryStruct SLC; + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + MachOObj->ReadSegmentLoadCommand(LCI, SLC); + InMemoryStruct Sect; + MachOObj->ReadSection(LCI, DRI.d.b, Sect); + + static char Result[34]; + strcpy(Result, SLC->Name); + strcat(Result, ","); + strcat(Result, Sect->Name); + return StringRef(Result); +} + +uint64_t MachOObjectFile::getSectionAddress(DataRefImpl DRI) const { + InMemoryStruct Sect; + getSection(DRI, Sect); + return Sect->Address; +} + +uint64_t MachOObjectFile::getSectionSize(DataRefImpl DRI) const { + InMemoryStruct Sect; + getSection(DRI, Sect); + return Sect->Size; +} + +StringRef MachOObjectFile::getSectionContents(DataRefImpl DRI) const { + InMemoryStruct Sect; + getSection(DRI, Sect); + return MachOObj->getData(Sect->Offset, Sect->Size); +} + +bool MachOObjectFile::isSectionText(DataRefImpl DRI) const { + InMemoryStruct SLC; + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + MachOObj->ReadSegmentLoadCommand(LCI, SLC); + return !strcmp(SLC->Name, "__TEXT"); +} + +ObjectFile::section_iterator MachOObjectFile::begin_sections() const { + DataRefImpl DRI; + DRI.d.a = DRI.d.b = 0; + moveToNextSection(DRI); + return section_iterator(SectionRef(DRI, this)); +} + +ObjectFile::section_iterator MachOObjectFile::end_sections() const { + DataRefImpl DRI; + DRI.d.a = MachOObj->getHeader().NumLoadCommands; + DRI.d.b = 0; + return section_iterator(SectionRef(DRI, this)); +} + +/*===-- Miscellaneous -----------------------------------------------------===*/ + +uint8_t MachOObjectFile::getBytesInAddress() const { + return MachOObj->is64Bit() ? 8 : 4; +} + +StringRef MachOObjectFile::getFileFormatName() const { + if (!MachOObj->is64Bit()) { + switch (MachOObj->getHeader().CPUType) { + case 0x00000007: + return "MACHO32-i386"; + case 0x01000007: + return "MACHO32-x86-64"; + case 0x0000000c: + return "MACHO32-arm"; + case 0x00000012: + return "MACHO32-ppc"; + case 0x01000012: + return "MACHO32-ppc64"; + } + } + + switch (MachOObj->getHeader().CPUType) { + case 0x00000007: + return "MACHO64-i386"; + case 0x01000007: + return "MACHO64-x86-64"; + case 0x0000000c: + return "MACHO64-arm"; + case 0x00000012: + return "MACHO64-ppc"; + case 0x01000012: + return "MACHO64-ppc64"; + default: + return "MACHO64-unknown"; + } +} + +unsigned MachOObjectFile::getArch() const { + switch (MachOObj->getHeader().CPUType) { + case 0x00000007: + return Triple::x86; + case 0x01000007: + return Triple::x86_64; + case 0x0000000c: + return Triple::arm; + case 0x00000012: + return Triple::ppc; + case 0x01000012: + return Triple::ppc64; + default: + return Triple::UnknownArch; + } +} + +} // end namespace llvm + -- cgit v1.1 From 9ab1d7f9b2d4caf1b8a5af91b74a7b13f1ac8986 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 22 Apr 2011 04:08:58 +0000 Subject: Make the file format strings a little prettier for mach-o. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129980 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 4a00324..21ac694 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -281,31 +281,27 @@ StringRef MachOObjectFile::getFileFormatName() const { if (!MachOObj->is64Bit()) { switch (MachOObj->getHeader().CPUType) { case 0x00000007: - return "MACHO32-i386"; - case 0x01000007: - return "MACHO32-x86-64"; + return "Mach-O 32-bit i386"; case 0x0000000c: - return "MACHO32-arm"; + return "Mach-O arm"; case 0x00000012: - return "MACHO32-ppc"; - case 0x01000012: - return "MACHO32-ppc64"; + return "Mach-O 32-bit ppc"; + default: + assert((MachOObj->getHeader().CPUType & 0x01000000) == 0 && + "64-bit object file when we're not 64-bit?"); + return "Mach-O 32-bit unknown"; } } switch (MachOObj->getHeader().CPUType) { - case 0x00000007: - return "MACHO64-i386"; case 0x01000007: - return "MACHO64-x86-64"; - case 0x0000000c: - return "MACHO64-arm"; - case 0x00000012: - return "MACHO64-ppc"; + return "Mach-O 64-bit x86-64"; case 0x01000012: - return "MACHO64-ppc64"; + return "Mach-O 64-bit ppc64"; default: - return "MACHO64-unknown"; + assert((MachOObj->getHeader().CPUType & 0x01000000) == 1 && + "32-bit object file when we're 64-bit?"); + return "Mach-O 64-bit unknown"; } } -- cgit v1.1 From f4b2f933a98e402083134f710a5d247c42e39ed5 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 22 Apr 2011 06:34:01 +0000 Subject: Use enums for constant values. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129984 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 21ac694..877cbfb 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -17,6 +17,7 @@ #include "llvm/Object/MachOObject.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/MachO.h" #include #include @@ -280,26 +281,26 @@ uint8_t MachOObjectFile::getBytesInAddress() const { StringRef MachOObjectFile::getFileFormatName() const { if (!MachOObj->is64Bit()) { switch (MachOObj->getHeader().CPUType) { - case 0x00000007: + case llvm::MachO::CPUTypeI386: return "Mach-O 32-bit i386"; - case 0x0000000c: + case llvm::MachO::CPUTypeARM: return "Mach-O arm"; - case 0x00000012: + case llvm::MachO::CPUTypePowerPC: return "Mach-O 32-bit ppc"; default: - assert((MachOObj->getHeader().CPUType & 0x01000000) == 0 && + assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && "64-bit object file when we're not 64-bit?"); return "Mach-O 32-bit unknown"; } } switch (MachOObj->getHeader().CPUType) { - case 0x01000007: + case llvm::MachO::CPUTypeX86_64: return "Mach-O 64-bit x86-64"; - case 0x01000012: + case llvm::MachO::CPUTypePowerPC64: return "Mach-O 64-bit ppc64"; default: - assert((MachOObj->getHeader().CPUType & 0x01000000) == 1 && + assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 && "32-bit object file when we're 64-bit?"); return "Mach-O 64-bit unknown"; } @@ -307,15 +308,15 @@ StringRef MachOObjectFile::getFileFormatName() const { unsigned MachOObjectFile::getArch() const { switch (MachOObj->getHeader().CPUType) { - case 0x00000007: + case llvm::MachO::CPUTypeI386: return Triple::x86; - case 0x01000007: + case llvm::MachO::CPUTypeX86_64: return Triple::x86_64; - case 0x0000000c: + case llvm::MachO::CPUTypeARM: return Triple::arm; - case 0x00000012: + case llvm::MachO::CPUTypePowerPC: return Triple::ppc; - case 0x01000012: + case llvm::MachO::CPUTypePowerPC64: return Triple::ppc64; default: return Triple::UnknownArch; -- cgit v1.1 From 69aec36f9b3129ba6eb83d64cde31c3d86d6d39a Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Mon, 13 Jun 2011 11:12:33 +0000 Subject: Make Binary the parent of ObjectFile and update children to new interface. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132911 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 877cbfb..3b76c6f 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -32,8 +32,8 @@ typedef MachOObject::LoadCommandInfo LoadCommandInfo; class MachOObjectFile : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO) - : ObjectFile(Object), + MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec) + : ObjectFile(Binary::isMachO, Object, ec), MachOObj(MOO), RegisteredStringTable(std::numeric_limits::max()) {} @@ -73,11 +73,12 @@ private: }; ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { + error_code ec; std::string Err; MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); if (!MachOObj) return NULL; - return new MachOObjectFile(Buffer, MachOObj); + return new MachOObjectFile(Buffer, MachOObj, ec); } /*===-- Symbols -----------------------------------------------------------===*/ -- cgit v1.1 From 5e45dc40d329829ad23bf444f32dca221215e239 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Mon, 13 Jun 2011 11:53:31 +0000 Subject: Revert the last two commits in the series. r132911, r132912. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132913 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 3b76c6f..877cbfb 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -32,8 +32,8 @@ typedef MachOObject::LoadCommandInfo LoadCommandInfo; class MachOObjectFile : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec) - : ObjectFile(Binary::isMachO, Object, ec), + MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO) + : ObjectFile(Object), MachOObj(MOO), RegisteredStringTable(std::numeric_limits::max()) {} @@ -73,12 +73,11 @@ private: }; ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { - error_code ec; std::string Err; MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); if (!MachOObj) return NULL; - return new MachOObjectFile(Buffer, MachOObj, ec); + return new MachOObjectFile(Buffer, MachOObj); } /*===-- Symbols -----------------------------------------------------------===*/ -- cgit v1.1