//
//===----------------------------------------------------------------------===//
+#include "llvm/Object/MachO.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/MachOFormat.h"
-#include "llvm/Object/MachOObject.h"
-#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/MachO.h"
-
#include <cctype>
#include <cstring>
#include <limits>
using namespace object;
namespace llvm {
+namespace object {
-typedef MachOObject::LoadCommandInfo LoadCommandInfo;
-
-class MachOObjectFile : public ObjectFile {
-public:
- MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec)
- : ObjectFile(Binary::isMachO, Object, ec),
- MachOObj(MOO),
- RegisteredStringTable(std::numeric_limits<uint32_t>::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 error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
- virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
- virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
- virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
- virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
- virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const;
-
- virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
- virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
- virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
- virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
- virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
- virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
- virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S,
- bool &Result) const;
-
-private:
- MachOObject *MachOObj;
- mutable uint32_t RegisteredStringTable;
-
- void moveToNextSection(DataRefImpl &DRI) const;
- void getSymbolTableEntry(DataRefImpl DRI,
- InMemoryStruct<macho::SymbolTableEntry> &Res) const;
- void getSymbol64TableEntry(DataRefImpl DRI,
- InMemoryStruct<macho::Symbol64TableEntry> &Res) const;
- void moveToNextSymbol(DataRefImpl &DRI) const;
- void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const;
- void getSection64(DataRefImpl DRI,
- InMemoryStruct<macho::Section64> &Res) const;
-};
+MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits,
+ error_code &ec)
+ : ObjectFile(getMachOType(true, Is64bits), Object) {
+}
+
+bool MachOObjectFileBase::is64Bit() const {
+ return isa<MachOObjectFile<true> >(this);
+}
+
+const MachOObjectFileBase::LoadCommand *
+MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const {
+ uint64_t Offset;
+ uint64_t NewOffset = getHeaderSize();
+ const LoadCommand *Load;
+ unsigned I = 0;
+ do {
+ Offset = NewOffset;
+ StringRef Data = getData(Offset, sizeof(LoadCommand));
+ Load = reinterpret_cast<const LoadCommand*>(Data.data());
+ NewOffset = Offset + Load->Size;
+ ++I;
+ } while (I != Index + 1);
+
+ return Load;
+}
+
+void MachOObjectFileBase::ReadULEB128s(uint64_t Index,
+ SmallVectorImpl<uint64_t> &Out) const {
+ DataExtractor extractor(ObjectFile::getData(), true, 0);
+
+ uint32_t offset = Index;
+ uint64_t data = 0;
+ while (uint64_t delta = extractor.getULEB128(&offset)) {
+ data += delta;
+ Out.push_back(data);
+ }
+}
+
+const MachOObjectFileBase::Header *MachOObjectFileBase::getHeader() const {
+ StringRef Data = getData(0, sizeof(Header));
+ return reinterpret_cast<const Header*>(Data.data());
+}
+
+unsigned MachOObjectFileBase::getHeaderSize() const {
+ return is64Bit() ? macho::Header64Size : macho::Header32Size;
+}
+
+StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const {
+ return ObjectFile::getData().substr(Offset, Size);
+}
ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
+ StringRef Magic = Buffer->getBuffer().slice(0, 4);
error_code ec;
- std::string Err;
- MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
- if (!MachOObj)
+ bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE";
+ ObjectFile *Ret;
+ if (Is64Bits)
+ Ret = new MachOObjectFile<true>(Buffer, ec);
+ else
+ Ret = new MachOObjectFile<false>(Buffer, ec);
+ if (ec)
return NULL;
- return new MachOObjectFile(Buffer, MachOObj, ec);
+ return Ret;
}
/*===-- Symbols -----------------------------------------------------------===*/
-void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
- uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
+void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const {
+ uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
while (DRI.d.a < LoadCommandCount) {
- LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
- if (LCI.Command.Type == macho::LCT_Symtab) {
- InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
- MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
+ const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
+ if (Command->Type == macho::LCT_Symtab) {
+ const SymtabLoadCommand *SymtabLoadCmd =
+ reinterpret_cast<const SymtabLoadCommand*>(Command);
if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
return;
}
}
}
-void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
- InMemoryStruct<macho::SymbolTableEntry> &Res) const {
- InMemoryStruct<macho::SymtabLoadCommand> 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);
+const MachOObjectFileBase::SymbolTableEntryBase *
+MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const {
+ const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
+ const SymtabLoadCommand *SymtabLoadCmd =
+ reinterpret_cast<const SymtabLoadCommand*>(Command);
+ return getSymbolTableEntryBase(DRI, SymtabLoadCmd);
}
-void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
- InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
- InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
- LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
- MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
+const MachOObjectFileBase::SymbolTableEntryBase *
+MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI,
+ const SymtabLoadCommand *SymtabLoadCmd) const {
+ uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
+ unsigned Index = DRI.d.b;
- if (RegisteredStringTable != DRI.d.a) {
- MachOObj->RegisterStringTable(*SymtabLoadCmd);
- RegisteredStringTable = DRI.d.a;
- }
+ unsigned SymbolTableEntrySize = is64Bit() ?
+ sizeof(MachOFormat::SymbolTableEntry<true>) :
+ sizeof(MachOFormat::SymbolTableEntry<false>);
- MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
- Res);
+ uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
+ StringRef Data = getData(Offset, SymbolTableEntrySize);
+ return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
}
-
-error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
- SymbolRef &Result) const {
+error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI,
+ SymbolRef &Result) const {
DRI.d.b++;
moveToNextSymbol(DRI);
Result = SymbolRef(DRI, this);
return object_error::success;
}
-error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
- StringRef &Result) const {
- if (MachOObj->is64Bit()) {
- InMemoryStruct<macho::Symbol64TableEntry> Entry;
- getSymbol64TableEntry(DRI, Entry);
- Result = MachOObj->getStringAtIndex(Entry->StringIndex);
- } else {
- InMemoryStruct<macho::SymbolTableEntry> Entry;
- getSymbolTableEntry(DRI, Entry);
- Result = MachOObj->getStringAtIndex(Entry->StringIndex);
- }
- return object_error::success;
-}
+error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI,
+ StringRef &Result) const {
+ const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
+ const SymtabLoadCommand *SymtabLoadCmd =
+ reinterpret_cast<const SymtabLoadCommand*>(Command);
-error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
- uint64_t &Result) const {
- if (MachOObj->is64Bit()) {
- InMemoryStruct<macho::Symbol64TableEntry> Entry;
- getSymbol64TableEntry(DRI, Entry);
- Result = Entry->Value;
- } else {
- InMemoryStruct<macho::SymbolTableEntry> Entry;
- getSymbolTableEntry(DRI, Entry);
- Result = Entry->Value;
- }
- return object_error::success;
-}
+ StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
+ SymtabLoadCmd->StringTableSize);
+
+ const SymbolTableEntryBase *Entry =
+ getSymbolTableEntryBase(DRI, SymtabLoadCmd);
+ uint32_t StringIndex = Entry->StringIndex;
+
+ const char *Start = &StringTable.data()[StringIndex];
+ Result = StringRef(Start);
-error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
- uint64_t &Result) const {
- Result = UnknownAddressOrSize;
return object_error::success;
}
-error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
- char &Result) const {
- uint8_t Type, Flags;
- if (MachOObj->is64Bit()) {
- InMemoryStruct<macho::Symbol64TableEntry> Entry;
- getSymbol64TableEntry(DRI, Entry);
- Type = Entry->Type;
- Flags = Entry->Flags;
- } else {
- InMemoryStruct<macho::SymbolTableEntry> Entry;
- getSymbolTableEntry(DRI, Entry);
- Type = Entry->Type;
- Flags = Entry->Flags;
- }
+error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI,
+ char &Result) const {
+ const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
+ uint8_t Type = Entry->Type;
+ uint16_t Flags = Entry->Flags;
char Char;
switch (Type & macho::STF_TypeMask) {
}
if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
- Char = toupper(Char);
+ Char = toupper(static_cast<unsigned char>(Char));
Result = Char;
return object_error::success;
}
-error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
- bool &Result) const {
- if (MachOObj->is64Bit()) {
- InMemoryStruct<macho::Symbol64TableEntry> Entry;
- getSymbol64TableEntry(DRI, Entry);
- Result = Entry->Flags & macho::STF_StabsEntryMask;
- } else {
- InMemoryStruct<macho::SymbolTableEntry> Entry;
- getSymbolTableEntry(DRI, Entry);
- Result = Entry->Flags & macho::STF_StabsEntryMask;
+error_code MachOObjectFileBase::getSymbolFlags(DataRefImpl DRI,
+ uint32_t &Result) const {
+ const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
+ uint8_t MachOType = Entry->Type;
+ uint16_t MachOFlags = Entry->Flags;
+
+ // TODO: Correctly set SF_ThreadLocal
+ Result = SymbolRef::SF_None;
+
+ if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
+ Result |= SymbolRef::SF_Undefined;
+
+ if (MachOFlags & macho::STF_StabsEntryMask)
+ Result |= SymbolRef::SF_FormatSpecific;
+
+ if (MachOType & MachO::NlistMaskExternal) {
+ Result |= SymbolRef::SF_Global;
+ if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
+ Result |= SymbolRef::SF_Common;
}
+
+ if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
+ Result |= SymbolRef::SF_Weak;
+
+ if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
+ Result |= SymbolRef::SF_Absolute;
+
return object_error::success;
}
-ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const {
+error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb,
+ section_iterator &Res) const {
+ const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
+ uint8_t index = Entry->SectionIndex;
+
+ if (index == 0)
+ Res = end_sections();
+ else
+ Res = section_iterator(SectionRef(Sections[index-1], this));
+
+ return object_error::success;
+}
+
+error_code MachOObjectFileBase::getSymbolType(DataRefImpl Symb,
+ SymbolRef::Type &Res) const {
+ const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
+ uint8_t n_type = Entry->Type;
+
+ Res = SymbolRef::ST_Other;
+
+ // If this is a STAB debugging symbol, we can do nothing more.
+ if (n_type & MachO::NlistMaskStab) {
+ Res = SymbolRef::ST_Debug;
+ return object_error::success;
+ }
+
+ switch (n_type & MachO::NlistMaskType) {
+ case MachO::NListTypeUndefined :
+ Res = SymbolRef::ST_Unknown;
+ break;
+ case MachO::NListTypeSection :
+ Res = SymbolRef::ST_Function;
+ break;
+ }
+ return object_error::success;
+}
+
+error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb,
+ uint64_t &Val) const {
+ report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase");
+}
+
+symbol_iterator MachOObjectFileBase::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 {
+symbol_iterator MachOObjectFileBase::end_symbols() const {
DataRefImpl DRI;
- DRI.d.a = MachOObj->getHeader().NumLoadCommands;
- DRI.d.b = 0;
+ DRI.d.a = getHeader()->NumLoadCommands;
return symbol_iterator(SymbolRef(DRI, this));
}
+symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const {
+ // TODO: implement
+ report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
+}
+
+symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const {
+ // TODO: implement
+ report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
+}
+
+library_iterator MachOObjectFileBase::begin_libraries_needed() const {
+ // TODO: implement
+ report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
+}
+
+library_iterator MachOObjectFileBase::end_libraries_needed() const {
+ // TODO: implement
+ report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
+}
+
+StringRef MachOObjectFileBase::getLoadName() const {
+ // TODO: Implement
+ report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase");
+}
/*===-- 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<macho::SegmentLoadCommand> SegmentLoadCmd;
- MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
- if (DRI.d.b < SegmentLoadCmd->NumSections)
- return;
- } else if (LCI.Command.Type == macho::LCT_Segment64) {
- InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
- MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
- if (DRI.d.b < Segment64LoadCmd->NumSections)
- return;
- }
+std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const {
+ SectionList::const_iterator loc =
+ std::find(Sections.begin(), Sections.end(), Sec);
+ assert(loc != Sections.end() && "Sec is not a valid section!");
+ return std::distance(Sections.begin(), loc);
+}
- DRI.d.a++;
- DRI.d.b = 0;
- }
+const MachOObjectFileBase::SectionBase*
+MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const {
+ const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
+ uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
+
+ bool Is64 = is64Bit();
+ unsigned SegmentLoadSize =
+ Is64 ? sizeof(MachOFormat::SegmentLoadCommand<true>) :
+ sizeof(MachOFormat::SegmentLoadCommand<false>);
+ unsigned SectionSize = Is64 ? sizeof(MachOFormat::Section<true>) :
+ sizeof(MachOFormat::Section<false>);
+
+ uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
+ return reinterpret_cast<const SectionBase*>(SectionAddr);
}
-error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
- SectionRef &Result) const {
- DRI.d.b++;
- moveToNextSection(DRI);
- Result = SectionRef(DRI, this);
- return object_error::success;
+static StringRef parseSegmentOrSectionName(const char *P) {
+ if (P[15] == 0)
+ // Null terminated.
+ return P;
+ // Not null terminated, so this is a 16 char string.
+ return StringRef(P, 16);
}
-void
-MachOObjectFile::getSection(DataRefImpl DRI,
- InMemoryStruct<macho::Section> &Res) const {
- InMemoryStruct<macho::SegmentLoadCommand> SLC;
- LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
- MachOObj->ReadSegmentLoadCommand(LCI, SLC);
- MachOObj->ReadSection(LCI, DRI.d.b, Res);
+ArrayRef<char> MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const {
+ const SectionBase *Base = getSectionBase(DRI);
+ return ArrayRef<char>(Base->Name);
}
-void
-MachOObjectFile::getSection64(DataRefImpl DRI,
- InMemoryStruct<macho::Section64> &Res) const {
- InMemoryStruct<macho::Segment64LoadCommand> SLC;
- LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
- MachOObj->ReadSegment64LoadCommand(LCI, SLC);
- MachOObj->ReadSection64(LCI, DRI.d.b, Res);
-}
-
-static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
- LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
- if (LCI.Command.Type == macho::LCT_Segment64)
- return true;
- assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
- return false;
-}
-
-error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
- StringRef &Result) const {
- // FIXME: thread safety.
- static char result[34];
- if (is64BitLoadCommand(MachOObj, DRI)) {
- InMemoryStruct<macho::Segment64LoadCommand> SLC;
- LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
- MachOObj->ReadSegment64LoadCommand(LCI, SLC);
- InMemoryStruct<macho::Section64> Sect;
- MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
-
- strcpy(result, Sect->SegmentName);
- strcat(result, ",");
- strcat(result, Sect->Name);
- } else {
- InMemoryStruct<macho::SegmentLoadCommand> SLC;
- LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
- MachOObj->ReadSegmentLoadCommand(LCI, SLC);
- InMemoryStruct<macho::Section> Sect;
- MachOObj->ReadSection(LCI, DRI.d.b, Sect);
-
- strcpy(result, Sect->SegmentName);
- strcat(result, ",");
- strcat(result, Sect->Name);
- }
- Result = StringRef(result);
+error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI,
+ StringRef &Result) const {
+ ArrayRef<char> Raw = getSectionRawName(DRI);
+ Result = parseSegmentOrSectionName(Raw.data());
return object_error::success;
}
-error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
- uint64_t &Result) const {
- if (is64BitLoadCommand(MachOObj, DRI)) {
- InMemoryStruct<macho::Section64> Sect;
- getSection64(DRI, Sect);
- Result = Sect->Address;
- } else {
- InMemoryStruct<macho::Section> Sect;
- getSection(DRI, Sect);
- Result = Sect->Address;
- }
+ArrayRef<char>
+MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
+ const SectionBase *Base = getSectionBase(Sec);
+ return ArrayRef<char>(Base->SegmentName);
+}
+
+StringRef
+MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const {
+ ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
+ return parseSegmentOrSectionName(Raw.data());
+}
+
+error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI,
+ bool &Result) const {
+ // FIXME: Unimplemented.
+ Result = false;
return object_error::success;
}
-error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
- uint64_t &Result) const {
- if (is64BitLoadCommand(MachOObj, DRI)) {
- InMemoryStruct<macho::Section64> Sect;
- getSection64(DRI, Sect);
- Result = Sect->Size;
- } else {
- InMemoryStruct<macho::Section> Sect;
- getSection(DRI, Sect);
- Result = Sect->Size;
- }
+error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI,
+ bool &Result) const {
+ // FIXME: Unimplemented.
+ Result = false;
return object_error::success;
}
-error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
- StringRef &Result) const {
- if (is64BitLoadCommand(MachOObj, DRI)) {
- InMemoryStruct<macho::Section64> Sect;
- getSection64(DRI, Sect);
- Result = MachOObj->getData(Sect->Offset, Sect->Size);
- } else {
- InMemoryStruct<macho::Section> Sect;
- getSection(DRI, Sect);
- Result = MachOObj->getData(Sect->Offset, Sect->Size);
- }
+error_code
+MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec,
+ bool &Result) const {
+ // FIXME: Unimplemented.
+ Result = true;
return object_error::success;
}
-error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
- bool &Result) const {
- if (is64BitLoadCommand(MachOObj, DRI)) {
- InMemoryStruct<macho::Section64> Sect;
- getSection64(DRI, Sect);
- Result = !strcmp(Sect->Name, "__text");
- } else {
- InMemoryStruct<macho::Section> Sect;
- getSection(DRI, Sect);
- Result = !strcmp(Sect->Name, "__text");
- }
+error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec,
+ bool &Result) const {
+ // FIXME: Unimplemented.
+ Result = false;
return object_error::success;
}
-error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
- DataRefImpl Symb,
- bool &Result) const {
- if (MachOObj->is64Bit()) {
- InMemoryStruct<macho::Symbol64TableEntry> Entry;
- getSymbol64TableEntry(Symb, Entry);
- Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b;
- } else {
- InMemoryStruct<macho::SymbolTableEntry> Entry;
- getSymbolTableEntry(Symb, Entry);
- Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b;
- }
+error_code MachOObjectFileBase::isSectionReadOnlyData(DataRefImpl Sec,
+ bool &Result) const {
+ // Consider using the code from isSectionText to look for __const sections.
+ // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
+ // to use section attributes to distinguish code from data.
+
+ // FIXME: Unimplemented.
+ Result = false;
return object_error::success;
}
-ObjectFile::section_iterator MachOObjectFile::begin_sections() const {
- DataRefImpl DRI;
- DRI.d.a = DRI.d.b = 0;
- moveToNextSection(DRI);
- return section_iterator(SectionRef(DRI, this));
+relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const {
+ DataRefImpl ret;
+ ret.d.b = getSectionIndex(Sec);
+ return relocation_iterator(RelocationRef(ret, this));
}
-ObjectFile::section_iterator MachOObjectFile::end_sections() const {
+section_iterator MachOObjectFileBase::end_sections() const {
DataRefImpl DRI;
- DRI.d.a = MachOObj->getHeader().NumLoadCommands;
- DRI.d.b = 0;
+ DRI.d.a = getHeader()->NumLoadCommands;
return section_iterator(SectionRef(DRI, this));
}
+/*===-- Relocations -------------------------------------------------------===*/
+
+error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel,
+ RelocationRef &Res) const {
+ ++Rel.d.a;
+ Res = RelocationRef(Rel, this);
+ return object_error::success;
+}
+
+// Helper to advance a section or symbol iterator multiple increments at a time.
+template<class T>
+error_code advance(T &it, size_t Val) {
+ error_code ec;
+ while (Val--) {
+ it.increment(ec);
+ }
+ return ec;
+}
+
+template<class T>
+void advanceTo(T &it, size_t Val) {
+ if (error_code ec = advance(it, Val))
+ report_fatal_error(ec.message());
+}
+
+void
+MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
+ raw_string_ostream &fmt) const {
+ unsigned Arch = getArch();
+ bool isScattered = (Arch != Triple::x86_64) &&
+ (RE->Word0 & macho::RF_Scattered);
+
+ // Target of a scattered relocation is an address. In the interest of
+ // generating pretty output, scan through the symbol table looking for a
+ // symbol that aligns with that address. If we find one, print it.
+ // Otherwise, we just print the hex address of the target.
+ if (isScattered) {
+ uint32_t Val = RE->Word1;
+
+ error_code ec;
+ for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
+ SI.increment(ec)) {
+ if (ec) report_fatal_error(ec.message());
+
+ uint64_t Addr;
+ StringRef Name;
+
+ if ((ec = SI->getAddress(Addr)))
+ report_fatal_error(ec.message());
+ if (Addr != Val) continue;
+ if ((ec = SI->getName(Name)))
+ report_fatal_error(ec.message());
+ fmt << Name;
+ return;
+ }
+
+ // If we couldn't find a symbol that this relocation refers to, try
+ // to find a section beginning instead.
+ for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
+ SI.increment(ec)) {
+ if (ec) report_fatal_error(ec.message());
+
+ uint64_t Addr;
+ StringRef Name;
+
+ if ((ec = SI->getAddress(Addr)))
+ report_fatal_error(ec.message());
+ if (Addr != Val) continue;
+ if ((ec = SI->getName(Name)))
+ report_fatal_error(ec.message());
+ fmt << Name;
+ return;
+ }
+
+ fmt << format("0x%x", Val);
+ return;
+ }
+
+ StringRef S;
+ bool isExtern = (RE->Word1 >> 27) & 1;
+ uint32_t Val = RE->Word1 & 0xFFFFFF;
+
+ if (isExtern) {
+ symbol_iterator SI = begin_symbols();
+ advanceTo(SI, Val);
+ SI->getName(S);
+ } else {
+ section_iterator SI = begin_sections();
+ advanceTo(SI, Val);
+ SI->getName(S);
+ }
+
+ fmt << S;
+}
+
+error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData,
+ LibraryRef &Res) const {
+ report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
+}
+
+error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData,
+ StringRef &Res) const {
+ report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
+}
+
+
/*===-- Miscellaneous -----------------------------------------------------===*/
-uint8_t MachOObjectFile::getBytesInAddress() const {
- return MachOObj->is64Bit() ? 8 : 4;
+uint8_t MachOObjectFileBase::getBytesInAddress() const {
+ return is64Bit() ? 8 : 4;
}
-StringRef MachOObjectFile::getFileFormatName() const {
- if (!MachOObj->is64Bit()) {
- switch (MachOObj->getHeader().CPUType) {
+StringRef MachOObjectFileBase::getFileFormatName() const {
+ if (!is64Bit()) {
+ switch (getHeader()->CPUType) {
case llvm::MachO::CPUTypeI386:
return "Mach-O 32-bit i386";
case llvm::MachO::CPUTypeARM:
case llvm::MachO::CPUTypePowerPC:
return "Mach-O 32-bit ppc";
default:
- assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
+ assert((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) {
+ // Make sure the cpu type has the correct mask.
+ assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
+ == llvm::MachO::CPUArchABI64 &&
+ "32-bit object file when we're 64-bit?");
+
+ switch (getHeader()->CPUType) {
case llvm::MachO::CPUTypeX86_64:
return "Mach-O 64-bit x86-64";
case llvm::MachO::CPUTypePowerPC64:
return "Mach-O 64-bit ppc64";
default:
- assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
- "32-bit object file when we're 64-bit?");
return "Mach-O 64-bit unknown";
}
}
-unsigned MachOObjectFile::getArch() const {
- switch (MachOObj->getHeader().CPUType) {
+unsigned MachOObjectFileBase::getArch() const {
+ switch (getHeader()->CPUType) {
case llvm::MachO::CPUTypeI386:
return Triple::x86;
case llvm::MachO::CPUTypeX86_64:
}
}
+} // end namespace object
} // end namespace llvm
-