aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Object/MachOObjectFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Object/MachOObjectFile.cpp')
-rw-r--r--lib/Object/MachOObjectFile.cpp696
1 files changed, 516 insertions, 180 deletions
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index c6bab03..4919114 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -28,6 +28,7 @@ using namespace llvm;
using namespace object;
namespace llvm {
+
namespace object {
struct nlist_base {
@@ -43,190 +44,195 @@ struct section_base {
};
template<typename T>
-static void SwapValue(T &Value) {
- Value = sys::SwapByteOrder(Value);
-}
-
-template<typename T>
static void SwapStruct(T &Value);
template<>
void SwapStruct(MachO::any_relocation_info &H) {
- SwapValue(H.r_word0);
- SwapValue(H.r_word1);
+ sys::swapByteOrder(H.r_word0);
+ sys::swapByteOrder(H.r_word1);
}
template<>
void SwapStruct(MachO::load_command &L) {
- SwapValue(L.cmd);
- SwapValue(L.cmdsize);
+ sys::swapByteOrder(L.cmd);
+ sys::swapByteOrder(L.cmdsize);
}
template<>
void SwapStruct(nlist_base &S) {
- SwapValue(S.n_strx);
- SwapValue(S.n_desc);
+ sys::swapByteOrder(S.n_strx);
+ sys::swapByteOrder(S.n_desc);
}
template<>
void SwapStruct(MachO::section &S) {
- SwapValue(S.addr);
- SwapValue(S.size);
- SwapValue(S.offset);
- SwapValue(S.align);
- SwapValue(S.reloff);
- SwapValue(S.nreloc);
- SwapValue(S.flags);
- SwapValue(S.reserved1);
- SwapValue(S.reserved2);
+ sys::swapByteOrder(S.addr);
+ sys::swapByteOrder(S.size);
+ sys::swapByteOrder(S.offset);
+ sys::swapByteOrder(S.align);
+ sys::swapByteOrder(S.reloff);
+ sys::swapByteOrder(S.nreloc);
+ sys::swapByteOrder(S.flags);
+ sys::swapByteOrder(S.reserved1);
+ sys::swapByteOrder(S.reserved2);
}
template<>
void SwapStruct(MachO::section_64 &S) {
- SwapValue(S.addr);
- SwapValue(S.size);
- SwapValue(S.offset);
- SwapValue(S.align);
- SwapValue(S.reloff);
- SwapValue(S.nreloc);
- SwapValue(S.flags);
- SwapValue(S.reserved1);
- SwapValue(S.reserved2);
- SwapValue(S.reserved3);
+ sys::swapByteOrder(S.addr);
+ sys::swapByteOrder(S.size);
+ sys::swapByteOrder(S.offset);
+ sys::swapByteOrder(S.align);
+ sys::swapByteOrder(S.reloff);
+ sys::swapByteOrder(S.nreloc);
+ sys::swapByteOrder(S.flags);
+ sys::swapByteOrder(S.reserved1);
+ sys::swapByteOrder(S.reserved2);
+ sys::swapByteOrder(S.reserved3);
}
template<>
void SwapStruct(MachO::nlist &S) {
- SwapValue(S.n_strx);
- SwapValue(S.n_desc);
- SwapValue(S.n_value);
+ sys::swapByteOrder(S.n_strx);
+ sys::swapByteOrder(S.n_desc);
+ sys::swapByteOrder(S.n_value);
}
template<>
void SwapStruct(MachO::nlist_64 &S) {
- SwapValue(S.n_strx);
- SwapValue(S.n_desc);
- SwapValue(S.n_value);
+ sys::swapByteOrder(S.n_strx);
+ sys::swapByteOrder(S.n_desc);
+ sys::swapByteOrder(S.n_value);
}
template<>
void SwapStruct(MachO::mach_header &H) {
- SwapValue(H.magic);
- SwapValue(H.cputype);
- SwapValue(H.cpusubtype);
- SwapValue(H.filetype);
- SwapValue(H.ncmds);
- SwapValue(H.sizeofcmds);
- SwapValue(H.flags);
+ sys::swapByteOrder(H.magic);
+ sys::swapByteOrder(H.cputype);
+ sys::swapByteOrder(H.cpusubtype);
+ sys::swapByteOrder(H.filetype);
+ sys::swapByteOrder(H.ncmds);
+ sys::swapByteOrder(H.sizeofcmds);
+ sys::swapByteOrder(H.flags);
}
template<>
void SwapStruct(MachO::mach_header_64 &H) {
- SwapValue(H.magic);
- SwapValue(H.cputype);
- SwapValue(H.cpusubtype);
- SwapValue(H.filetype);
- SwapValue(H.ncmds);
- SwapValue(H.sizeofcmds);
- SwapValue(H.flags);
- SwapValue(H.reserved);
+ sys::swapByteOrder(H.magic);
+ sys::swapByteOrder(H.cputype);
+ sys::swapByteOrder(H.cpusubtype);
+ sys::swapByteOrder(H.filetype);
+ sys::swapByteOrder(H.ncmds);
+ sys::swapByteOrder(H.sizeofcmds);
+ sys::swapByteOrder(H.flags);
+ sys::swapByteOrder(H.reserved);
}
template<>
void SwapStruct(MachO::symtab_command &C) {
- SwapValue(C.cmd);
- SwapValue(C.cmdsize);
- SwapValue(C.symoff);
- SwapValue(C.nsyms);
- SwapValue(C.stroff);
- SwapValue(C.strsize);
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.symoff);
+ sys::swapByteOrder(C.nsyms);
+ sys::swapByteOrder(C.stroff);
+ sys::swapByteOrder(C.strsize);
}
template<>
void SwapStruct(MachO::dysymtab_command &C) {
- SwapValue(C.cmd);
- SwapValue(C.cmdsize);
- SwapValue(C.ilocalsym);
- SwapValue(C.nlocalsym);
- SwapValue(C.iextdefsym);
- SwapValue(C.nextdefsym);
- SwapValue(C.iundefsym);
- SwapValue(C.nundefsym);
- SwapValue(C.tocoff);
- SwapValue(C.ntoc);
- SwapValue(C.modtaboff);
- SwapValue(C.nmodtab);
- SwapValue(C.extrefsymoff);
- SwapValue(C.nextrefsyms);
- SwapValue(C.indirectsymoff);
- SwapValue(C.nindirectsyms);
- SwapValue(C.extreloff);
- SwapValue(C.nextrel);
- SwapValue(C.locreloff);
- SwapValue(C.nlocrel);
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.ilocalsym);
+ sys::swapByteOrder(C.nlocalsym);
+ sys::swapByteOrder(C.iextdefsym);
+ sys::swapByteOrder(C.nextdefsym);
+ sys::swapByteOrder(C.iundefsym);
+ sys::swapByteOrder(C.nundefsym);
+ sys::swapByteOrder(C.tocoff);
+ sys::swapByteOrder(C.ntoc);
+ sys::swapByteOrder(C.modtaboff);
+ sys::swapByteOrder(C.nmodtab);
+ sys::swapByteOrder(C.extrefsymoff);
+ sys::swapByteOrder(C.nextrefsyms);
+ sys::swapByteOrder(C.indirectsymoff);
+ sys::swapByteOrder(C.nindirectsyms);
+ sys::swapByteOrder(C.extreloff);
+ sys::swapByteOrder(C.nextrel);
+ sys::swapByteOrder(C.locreloff);
+ sys::swapByteOrder(C.nlocrel);
}
template<>
void SwapStruct(MachO::linkedit_data_command &C) {
- SwapValue(C.cmd);
- SwapValue(C.cmdsize);
- SwapValue(C.dataoff);
- SwapValue(C.datasize);
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.dataoff);
+ sys::swapByteOrder(C.datasize);
}
template<>
void SwapStruct(MachO::segment_command &C) {
- SwapValue(C.cmd);
- SwapValue(C.cmdsize);
- SwapValue(C.vmaddr);
- SwapValue(C.vmsize);
- SwapValue(C.fileoff);
- SwapValue(C.filesize);
- SwapValue(C.maxprot);
- SwapValue(C.initprot);
- SwapValue(C.nsects);
- SwapValue(C.flags);
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.vmaddr);
+ sys::swapByteOrder(C.vmsize);
+ sys::swapByteOrder(C.fileoff);
+ sys::swapByteOrder(C.filesize);
+ sys::swapByteOrder(C.maxprot);
+ sys::swapByteOrder(C.initprot);
+ sys::swapByteOrder(C.nsects);
+ sys::swapByteOrder(C.flags);
}
template<>
void SwapStruct(MachO::segment_command_64 &C) {
- SwapValue(C.cmd);
- SwapValue(C.cmdsize);
- SwapValue(C.vmaddr);
- SwapValue(C.vmsize);
- SwapValue(C.fileoff);
- SwapValue(C.filesize);
- SwapValue(C.maxprot);
- SwapValue(C.initprot);
- SwapValue(C.nsects);
- SwapValue(C.flags);
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.vmaddr);
+ sys::swapByteOrder(C.vmsize);
+ sys::swapByteOrder(C.fileoff);
+ sys::swapByteOrder(C.filesize);
+ sys::swapByteOrder(C.maxprot);
+ sys::swapByteOrder(C.initprot);
+ sys::swapByteOrder(C.nsects);
+ sys::swapByteOrder(C.flags);
}
template<>
void SwapStruct(uint32_t &C) {
- SwapValue(C);
+ sys::swapByteOrder(C);
}
template<>
void SwapStruct(MachO::linker_options_command &C) {
- SwapValue(C.cmd);
- SwapValue(C.cmdsize);
- SwapValue(C.count);
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.count);
}
template<>
void SwapStruct(MachO::version_min_command&C) {
- SwapValue(C.cmd);
- SwapValue(C.cmdsize);
- SwapValue(C.version);
- SwapValue(C.reserved);
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.version);
+ sys::swapByteOrder(C.reserved);
+}
+
+template<>
+void SwapStruct(MachO::dylib_command&C) {
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.dylib.name);
+ sys::swapByteOrder(C.dylib.timestamp);
+ sys::swapByteOrder(C.dylib.current_version);
+ sys::swapByteOrder(C.dylib.compatibility_version);
}
template<>
void SwapStruct(MachO::data_in_code_entry &C) {
- SwapValue(C.offset);
- SwapValue(C.length);
- SwapValue(C.kind);
+ sys::swapByteOrder(C.offset);
+ sys::swapByteOrder(C.length);
+ sys::swapByteOrder(C.kind);
}
template<typename T>
@@ -306,7 +312,7 @@ static void printRelocationTargetName(const MachOObjectFile *O,
uint32_t Val = O->getPlainRelocationSymbolNum(RE);
for (const SymbolRef &Symbol : O->symbols()) {
- error_code ec;
+ std::error_code ec;
uint64_t Addr;
StringRef Name;
@@ -323,7 +329,7 @@ static void printRelocationTargetName(const MachOObjectFile *O,
// If we couldn't find a symbol that this relocation refers to, try
// to find a section beginning instead.
for (const SectionRef &Section : O->sections()) {
- error_code ec;
+ std::error_code ec;
uint64_t Addr;
StringRef Name;
@@ -416,10 +422,10 @@ static uint32_t getSectionFlags(const MachOObjectFile *O,
return Sect.flags;
}
-MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian,
- bool Is64bits, error_code &EC,
- bool BufferOwned)
- : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object, BufferOwned),
+MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object,
+ bool IsLittleEndian, bool Is64bits,
+ std::error_code &EC)
+ : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)),
SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
DataInCodeLoadCmd(nullptr) {
uint32_t LoadCommandCount = this->getHeader().ncmds;
@@ -443,6 +449,12 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian,
const char *Sec = getSectionPtr(this, Load, J);
Sections.push_back(Sec);
}
+ } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
+ Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
+ Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
+ Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
+ Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
+ Libraries.push_back(Load.Ptr);
}
if (I == LoadCommandCount - 1)
@@ -459,8 +471,8 @@ void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Symb.p += SymbolTableEntrySize;
}
-error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
- StringRef &Res) const {
+std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
+ StringRef &Res) const {
StringRef StringTable = getStringTableData();
nlist_base Entry = getSymbolTableEntryBase(this, Symb);
const char *Start = &StringTable.data()[Entry.n_strx];
@@ -468,8 +480,32 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
return object_error::success;
}
-error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
- uint64_t &Res) const {
+// getIndirectName() returns the name of the alias'ed symbol who's string table
+// index is in the n_value field.
+std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
+ StringRef &Res) const {
+ StringRef StringTable = getStringTableData();
+ uint64_t NValue;
+ if (is64Bit()) {
+ MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
+ NValue = Entry.n_value;
+ if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
+ return object_error::parse_failed;
+ } else {
+ MachO::nlist Entry = getSymbolTableEntry(Symb);
+ NValue = Entry.n_value;
+ if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
+ return object_error::parse_failed;
+ }
+ if (NValue >= StringTable.size())
+ return object_error::parse_failed;
+ const char *Start = &StringTable.data()[NValue];
+ Res = StringRef(Start);
+ return object_error::success;
+}
+
+std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
+ uint64_t &Res) const {
if (is64Bit()) {
MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
@@ -488,8 +524,8 @@ error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
return object_error::success;
}
-error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
- uint32_t &Result) const {
+std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
+ uint32_t &Result) const {
uint32_t flags = getSymbolFlags(DRI);
if (flags & SymbolRef::SF_Common) {
nlist_base Entry = getSymbolTableEntryBase(this, DRI);
@@ -500,8 +536,8 @@ error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
return object_error::success;
}
-error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
- uint64_t &Result) const {
+std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
+ uint64_t &Result) const {
uint64_t BeginOffset;
uint64_t EndOffset = 0;
uint8_t SectionIndex;
@@ -549,8 +585,8 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
return object_error::success;
}
-error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
- SymbolRef::Type &Res) const {
+std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
+ SymbolRef::Type &Res) const {
nlist_base Entry = getSymbolTableEntryBase(this, Symb);
uint8_t n_type = Entry.n_type;
@@ -584,6 +620,9 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Result |= SymbolRef::SF_Undefined;
+ if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
+ Result |= SymbolRef::SF_Indirect;
+
if (MachOType & MachO::N_STAB)
Result |= SymbolRef::SF_FormatSpecific;
@@ -606,9 +645,8 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
return Result;
}
-error_code
-MachOObjectFile::getSymbolSection(DataRefImpl Symb,
- section_iterator &Res) const {
+std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
+ section_iterator &Res) const {
nlist_base Entry = getSymbolTableEntryBase(this, Symb);
uint8_t index = Entry.n_sect;
@@ -627,15 +665,15 @@ void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Sec.d.a++;
}
-error_code
-MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const {
+std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
+ StringRef &Result) const {
ArrayRef<char> Raw = getSectionRawName(Sec);
Result = parseSegmentOrSectionName(Raw.data());
return object_error::success;
}
-error_code
-MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const {
+std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
+ uint64_t &Res) const {
if (is64Bit()) {
MachO::section_64 Sect = getSection64(Sec);
Res = Sect.addr;
@@ -646,8 +684,8 @@ MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const {
return object_error::success;
}
-error_code
-MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const {
+std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
+ uint64_t &Res) const {
if (is64Bit()) {
MachO::section_64 Sect = getSection64(Sec);
Res = Sect.size;
@@ -659,8 +697,8 @@ MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const {
return object_error::success;
}
-error_code
-MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const {
+std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
+ StringRef &Res) const {
uint32_t Offset;
uint64_t Size;
@@ -678,8 +716,8 @@ MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const {
return object_error::success;
}
-error_code
-MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const {
+std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
+ uint64_t &Res) const {
uint32_t Align;
if (is64Bit()) {
MachO::section_64 Sect = getSection64(Sec);
@@ -693,14 +731,15 @@ MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const {
return object_error::success;
}
-error_code
-MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
+std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
+ bool &Res) const {
uint32_t Flags = getSectionFlags(this, Sec);
Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
return object_error::success;
}
-error_code MachOObjectFile::isSectionData(DataRefImpl Sec, bool &Result) const {
+std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
+ bool &Result) const {
uint32_t Flags = getSectionFlags(this, Sec);
unsigned SectionType = Flags & MachO::SECTION_TYPE;
Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
@@ -709,7 +748,8 @@ error_code MachOObjectFile::isSectionData(DataRefImpl Sec, bool &Result) const {
return object_error::success;
}
-error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, bool &Result) const {
+std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
+ bool &Result) const {
uint32_t Flags = getSectionFlags(this, Sec);
unsigned SectionType = Flags & MachO::SECTION_TYPE;
Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
@@ -718,7 +758,7 @@ error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, bool &Result) const {
return object_error::success;
}
-error_code
+std::error_code
MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
bool &Result) const {
// FIXME: Unimplemented.
@@ -726,15 +766,15 @@ MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
return object_error::success;
}
-error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
- bool &Result) const {
+std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
+ bool &Result) const {
// FIXME: Unimplemented.
Result = false;
return object_error::success;
}
-error_code
-MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
+std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
+ bool &Res) const {
uint32_t Flags = getSectionFlags(this, Sec);
unsigned SectionType = Flags & MachO::SECTION_TYPE;
Res = SectionType == MachO::S_ZEROFILL ||
@@ -742,8 +782,8 @@ MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
return object_error::success;
}
-error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
- bool &Result) const {
+std::error_code MachOObjectFile::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.
@@ -753,9 +793,9 @@ error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
return object_error::success;
}
-error_code
-MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
- bool &Result) const {
+std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
+ DataRefImpl Symb,
+ bool &Result) const {
SymbolRef::Type ST;
this->getSymbolType(Symb, ST);
if (ST == SymbolRef::ST_Unknown) {
@@ -803,8 +843,8 @@ void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
++Rel.d.b;
}
-error_code
-MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const {
+std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
+ uint64_t &Res) const {
uint64_t Offset;
getRelocationOffset(Rel, Offset);
@@ -816,8 +856,8 @@ MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const {
return object_error::success;
}
-error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
- uint64_t &Res) const {
+std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
+ uint64_t &Res) const {
assert(getHeader().filetype == MachO::MH_OBJECT &&
"Only implemented for MH_OBJECT");
MachO::any_relocation_info RE = getRelocation(Rel);
@@ -828,6 +868,9 @@ error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
symbol_iterator
MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
MachO::any_relocation_info RE = getRelocation(Rel);
+ if (isRelocationScattered(RE))
+ return symbol_end();
+
uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
bool isExtern = getPlainRelocationExternal(RE);
if (!isExtern)
@@ -843,14 +886,14 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
return symbol_iterator(SymbolRef(Sym, this));
}
-error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
- uint64_t &Res) const {
+std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
+ uint64_t &Res) const {
MachO::any_relocation_info RE = getRelocation(Rel);
Res = getAnyRelocationType(RE);
return object_error::success;
}
-error_code
+std::error_code
MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const {
StringRef res;
@@ -963,7 +1006,7 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
return object_error::success;
}
-error_code
+std::error_code
MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const {
MachO::any_relocation_info RE = getRelocation(Rel);
@@ -1139,8 +1182,8 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
return object_error::success;
}
-error_code
-MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const {
+std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
+ bool &Result) const {
unsigned Arch = getArch();
uint64_t Type;
getRelocationType(Rel, Type);
@@ -1167,16 +1210,199 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const {
return object_error::success;
}
-error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
- LibraryRef &Res) const {
+std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
+ LibraryRef &Res) const {
report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}
-error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
- StringRef &Res) const {
+std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
+ StringRef &Res) const {
report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}
+//
+// guessLibraryShortName() is passed a name of a dynamic library and returns a
+// guess on what the short name is. Then name is returned as a substring of the
+// StringRef Name passed in. The name of the dynamic library is recognized as
+// a framework if it has one of the two following forms:
+// Foo.framework/Versions/A/Foo
+// Foo.framework/Foo
+// Where A and Foo can be any string. And may contain a trailing suffix
+// starting with an underbar. If the Name is recognized as a framework then
+// isFramework is set to true else it is set to false. If the Name has a
+// suffix then Suffix is set to the substring in Name that contains the suffix
+// else it is set to a NULL StringRef.
+//
+// The Name of the dynamic library is recognized as a library name if it has
+// one of the two following forms:
+// libFoo.A.dylib
+// libFoo.dylib
+// The library may have a suffix trailing the name Foo of the form:
+// libFoo_profile.A.dylib
+// libFoo_profile.dylib
+//
+// The Name of the dynamic library is also recognized as a library name if it
+// has the following form:
+// Foo.qtx
+//
+// If the Name of the dynamic library is none of the forms above then a NULL
+// StringRef is returned.
+//
+StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
+ bool &isFramework,
+ StringRef &Suffix) {
+ StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
+ size_t a, b, c, d, Idx;
+
+ isFramework = false;
+ Suffix = StringRef();
+
+ // Pull off the last component and make Foo point to it
+ a = Name.rfind('/');
+ if (a == Name.npos || a == 0)
+ goto guess_library;
+ Foo = Name.slice(a+1, Name.npos);
+
+ // Look for a suffix starting with a '_'
+ Idx = Foo.rfind('_');
+ if (Idx != Foo.npos && Foo.size() >= 2) {
+ Suffix = Foo.slice(Idx, Foo.npos);
+ Foo = Foo.slice(0, Idx);
+ }
+
+ // First look for the form Foo.framework/Foo
+ b = Name.rfind('/', a);
+ if (b == Name.npos)
+ Idx = 0;
+ else
+ Idx = b+1;
+ F = Name.slice(Idx, Idx + Foo.size());
+ DotFramework = Name.slice(Idx + Foo.size(),
+ Idx + Foo.size() + sizeof(".framework/")-1);
+ if (F == Foo && DotFramework == ".framework/") {
+ isFramework = true;
+ return Foo;
+ }
+
+ // Next look for the form Foo.framework/Versions/A/Foo
+ if (b == Name.npos)
+ goto guess_library;
+ c = Name.rfind('/', b);
+ if (c == Name.npos || c == 0)
+ goto guess_library;
+ V = Name.slice(c+1, Name.npos);
+ if (!V.startswith("Versions/"))
+ goto guess_library;
+ d = Name.rfind('/', c);
+ if (d == Name.npos)
+ Idx = 0;
+ else
+ Idx = d+1;
+ F = Name.slice(Idx, Idx + Foo.size());
+ DotFramework = Name.slice(Idx + Foo.size(),
+ Idx + Foo.size() + sizeof(".framework/")-1);
+ if (F == Foo && DotFramework == ".framework/") {
+ isFramework = true;
+ return Foo;
+ }
+
+guess_library:
+ // pull off the suffix after the "." and make a point to it
+ a = Name.rfind('.');
+ if (a == Name.npos || a == 0)
+ return StringRef();
+ Dylib = Name.slice(a, Name.npos);
+ if (Dylib != ".dylib")
+ goto guess_qtx;
+
+ // First pull off the version letter for the form Foo.A.dylib if any.
+ if (a >= 3) {
+ Dot = Name.slice(a-2, a-1);
+ if (Dot == ".")
+ a = a - 2;
+ }
+
+ b = Name.rfind('/', a);
+ if (b == Name.npos)
+ b = 0;
+ else
+ b = b+1;
+ // ignore any suffix after an underbar like Foo_profile.A.dylib
+ Idx = Name.find('_', b);
+ if (Idx != Name.npos && Idx != b) {
+ Lib = Name.slice(b, Idx);
+ Suffix = Name.slice(Idx, a);
+ }
+ else
+ Lib = Name.slice(b, a);
+ // There are incorrect library names of the form:
+ // libATS.A_profile.dylib so check for these.
+ if (Lib.size() >= 3) {
+ Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
+ if (Dot == ".")
+ Lib = Lib.slice(0, Lib.size()-2);
+ }
+ return Lib;
+
+guess_qtx:
+ Qtx = Name.slice(a, Name.npos);
+ if (Qtx != ".qtx")
+ return StringRef();
+ b = Name.rfind('/', a);
+ if (b == Name.npos)
+ Lib = Name.slice(0, a);
+ else
+ Lib = Name.slice(b+1, a);
+ // There are library names of the form: QT.A.qtx so check for these.
+ if (Lib.size() >= 3) {
+ Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
+ if (Dot == ".")
+ Lib = Lib.slice(0, Lib.size()-2);
+ }
+ return Lib;
+}
+
+// getLibraryShortNameByIndex() is used to get the short name of the library
+// for an undefined symbol in a linked Mach-O binary that was linked with the
+// normal two-level namespace default (that is MH_TWOLEVEL in the header).
+// It is passed the index (0 - based) of the library as translated from
+// GET_LIBRARY_ORDINAL (1 - based).
+std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
+ StringRef &Res) {
+ if (Index >= Libraries.size())
+ return object_error::parse_failed;
+
+ MachO::dylib_command D =
+ getStruct<MachO::dylib_command>(this, Libraries[Index]);
+ if (D.dylib.name >= D.cmdsize)
+ return object_error::parse_failed;
+
+ // If the cache of LibrariesShortNames is not built up do that first for
+ // all the Libraries.
+ if (LibrariesShortNames.size() == 0) {
+ for (unsigned i = 0; i < Libraries.size(); i++) {
+ MachO::dylib_command D =
+ getStruct<MachO::dylib_command>(this, Libraries[i]);
+ if (D.dylib.name >= D.cmdsize) {
+ LibrariesShortNames.push_back(StringRef());
+ continue;
+ }
+ const char *P = (const char *)(Libraries[i]) + D.dylib.name;
+ StringRef Name = StringRef(P);
+ StringRef Suffix;
+ bool isFramework;
+ StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
+ if (shortName == StringRef())
+ LibrariesShortNames.push_back(Name);
+ else
+ LibrariesShortNames.push_back(shortName);
+ }
+ }
+
+ Res = LibrariesShortNames[Index];
+ return object_error::success;
+}
+
basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
return getSymbolByIndex(0);
}
@@ -1288,6 +1514,108 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
}
}
+Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
+ switch (CPUType) {
+ case MachO::CPU_TYPE_I386:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_I386_ALL:
+ return Triple("i386-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_X86_64:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_X86_64_ALL:
+ return Triple("x86_64-apple-darwin");
+ case MachO::CPU_SUBTYPE_X86_64_H:
+ return Triple("x86_64h-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_ARM:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_ARM_V4T:
+ return Triple("armv4t-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V5TEJ:
+ return Triple("armv5e-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V6:
+ return Triple("armv6-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V6M:
+ return Triple("armv6m-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7EM:
+ return Triple("armv7em-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7K:
+ return Triple("armv7k-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7M:
+ return Triple("armv7m-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7S:
+ return Triple("armv7s-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_ARM64:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_ARM64_ALL:
+ return Triple("arm64-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_POWERPC:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_POWERPC_ALL:
+ return Triple("ppc-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_POWERPC64:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_POWERPC_ALL:
+ return Triple("ppc64-apple-darwin");
+ default:
+ return Triple();
+ }
+ default:
+ return Triple();
+ }
+}
+
+Triple MachOObjectFile::getHostArch() {
+ return Triple(sys::getDefaultTargetTriple());
+}
+
+Triple MachOObjectFile::getArch(StringRef ArchFlag) {
+ if (ArchFlag == "i386")
+ return Triple("i386-apple-darwin");
+ else if (ArchFlag == "x86_64")
+ return Triple("x86_64-apple-darwin");
+ else if (ArchFlag == "x86_64h")
+ return Triple("x86_64h-apple-darwin");
+ else if (ArchFlag == "armv4t" || ArchFlag == "arm")
+ return Triple("armv4t-apple-darwin");
+ else if (ArchFlag == "armv5e")
+ return Triple("armv5e-apple-darwin");
+ else if (ArchFlag == "armv6")
+ return Triple("armv6-apple-darwin");
+ else if (ArchFlag == "armv6m")
+ return Triple("armv6m-apple-darwin");
+ else if (ArchFlag == "armv7em")
+ return Triple("armv7em-apple-darwin");
+ else if (ArchFlag == "armv7k")
+ return Triple("armv7k-apple-darwin");
+ else if (ArchFlag == "armv7k")
+ return Triple("armv7m-apple-darwin");
+ else if (ArchFlag == "armv7s")
+ return Triple("armv7s-apple-darwin");
+ else if (ArchFlag == "arm64")
+ return Triple("arm64-apple-darwin");
+ else if (ArchFlag == "ppc")
+ return Triple("ppc-apple-darwin");
+ else if (ArchFlag == "ppc64")
+ return Triple("ppc64-apple-darwin");
+ else
+ return Triple();
+}
+
unsigned MachOObjectFile::getArch() const {
return getArch(getCPUType(this));
}
@@ -1498,6 +1826,12 @@ MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
return getStruct<MachO::version_min_command>(this, L.Ptr);
}
+MachO::dylib_command
+MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::dylib_command>(this, L.Ptr);
+}
+
+
MachO::any_relocation_info
MachOObjectFile::getRelocation(DataRefImpl Rel) const {
DataRefImpl Sec;
@@ -1574,7 +1908,7 @@ StringRef MachOObjectFile::getStringTableData() const {
bool MachOObjectFile::is64Bit() const {
return getType() == getMachOType(false, true) ||
- getType() == getMachOType(true, true);
+ getType() == getMachOType(true, true);
}
void MachOObjectFile::ReadULEB128s(uint64_t Index,
@@ -1589,23 +1923,25 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index,
}
}
-ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer,
- bool BufferOwned) {
+const char *MachOObjectFile::getSectionPointer(DataRefImpl Rel) const {
+ return Sections[Rel.d.a];
+}
+
+ErrorOr<ObjectFile *>
+ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {
StringRef Magic = Buffer->getBuffer().slice(0, 4);
- error_code EC;
+ std::error_code EC;
std::unique_ptr<MachOObjectFile> Ret;
if (Magic == "\xFE\xED\xFA\xCE")
- Ret.reset(new MachOObjectFile(Buffer, false, false, EC, BufferOwned));
+ Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC));
else if (Magic == "\xCE\xFA\xED\xFE")
- Ret.reset(new MachOObjectFile(Buffer, true, false, EC, BufferOwned));
+ Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC));
else if (Magic == "\xFE\xED\xFA\xCF")
- Ret.reset(new MachOObjectFile(Buffer, false, true, EC, BufferOwned));
+ Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC));
else if (Magic == "\xCF\xFA\xED\xFE")
- Ret.reset(new MachOObjectFile(Buffer, true, true, EC, BufferOwned));
- else {
- delete Buffer;
+ Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC));
+ else
return object_error::parse_failed;
- }
if (EC)
return EC;