};
}
-template<typename T>
+template <typename T>
static T getStruct(const MachOObjectFile *O, const char *P) {
+ // Don't read before the beginning or past the end of the file
+ if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
+ report_fatal_error("Malformed MachO file.");
+
T Cmd;
memcpy(&Cmd, P, sizeof(T));
if (O->isLittleEndian() != sys::IsLittleEndianHost)
return Cmd;
}
+template <typename SegmentCmd>
+static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
+ uint32_t Cmdsize) {
+ const unsigned SectionSize = sizeof(SegmentCmd);
+ if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
+ S.nsects * SectionSize > Cmdsize - sizeof(S))
+ report_fatal_error(
+ "Number of sections too large for size of load command.");
+ return S.nsects;
+}
+
static uint32_t
getSegmentLoadCommandNumSections(const MachOObjectFile *O,
const MachOObjectFile::LoadCommandInfo &L) {
- if (O->is64Bit()) {
- MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
- return S.nsects;
- }
- MachO::segment_command S = O->getSegmentLoadCommand(L);
- return S.nsects;
+ if (O->is64Bit())
+ return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
+ L.C.cmdsize);
+
+ return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
+ L.C.cmdsize);
}
static bool isPageZeroSegment(const MachOObjectFile *O,
// to find a section beginning instead.
for (const SectionRef &Section : O->sections()) {
std::error_code ec;
- uint64_t Addr;
- StringRef Name;
- if ((ec = Section.getAddress(Addr)))
- report_fatal_error(ec.message());
+ StringRef Name;
+ uint64_t Addr = Section.getAddress();
if (Addr != Val)
continue;
if ((ec = Section.getName(Name)))
return RE.r_word1 & 0xf;
}
-static unsigned
-getScatteredRelocationType(const MachO::any_relocation_info &RE) {
- return (RE.r_word0 >> 24) & 0xf;
-}
-
static uint32_t getSectionFlags(const MachOObjectFile *O,
DataRefImpl Sec) {
if (O->is64Bit()) {
bool Is64bits, std::error_code &EC)
: ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
- DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
+ DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
+ DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
HasPageZeroSegment(false) {
uint32_t LoadCommandCount = this->getHeader().ncmds;
+ if (LoadCommandCount == 0)
+ return;
+
MachO::LoadCommandType SegmentLoadType = is64Bit() ?
MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
for (unsigned I = 0; ; ++I) {
if (Load.C.cmd == MachO::LC_SYMTAB) {
- assert(!SymtabLoadCmd && "Multiple symbol tables");
+ // Multiple symbol tables
+ if (SymtabLoadCmd) {
+ EC = object_error::parse_failed;
+ return;
+ }
SymtabLoadCmd = Load.Ptr;
} else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
- assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
+ // Multiple dynamic symbol tables
+ if (DysymtabLoadCmd) {
+ EC = object_error::parse_failed;
+ return;
+ }
DysymtabLoadCmd = Load.Ptr;
} else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
- assert(!DataInCodeLoadCmd && "Multiple data in code tables");
+ // Multiple data in code tables
+ if (DataInCodeLoadCmd) {
+ EC = object_error::parse_failed;
+ return;
+ }
DataInCodeLoadCmd = Load.Ptr;
+ } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
+ // Multiple linker optimization hint tables
+ if (LinkOptHintsLoadCmd) {
+ EC = object_error::parse_failed;
+ return;
+ }
+ LinkOptHintsLoadCmd = Load.Ptr;
} else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
- assert(!DyldInfoLoadCmd && "Multiple dyldinfo load commands");
+ // Multiple dyldinfo load commands
+ if (DyldInfoLoadCmd) {
+ EC = object_error::parse_failed;
+ return;
+ }
DyldInfoLoadCmd = Load.Ptr;
+ } else if (Load.C.cmd == MachO::LC_UUID) {
+ // Multiple UUID load commands
+ if (UuidLoadCmd) {
+ EC = object_error::parse_failed;
+ return;
+ }
+ UuidLoadCmd = Load.Ptr;
} else if (Load.C.cmd == SegmentLoadType) {
+ const unsigned SegmentLoadSize = this->is64Bit()
+ ? sizeof(MachO::segment_command_64)
+ : sizeof(MachO::segment_command);
+ if (Load.C.cmdsize < SegmentLoadSize)
+ report_fatal_error("Segment load command size is too small.");
+
uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
for (unsigned J = 0; J < NumSections; ++J) {
const char *Sec = getSectionPtr(this, Load, J);
StringRef StringTable = getStringTableData();
MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
const char *Start = &StringTable.data()[Entry.n_strx];
+ if (Start < getData().begin() || Start >= getData().end())
+ report_fatal_error(
+ "Symbol name entry points before beginning or past end of file.");
Res = StringRef(Start);
return object_error::success;
}
+unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
+ DataRefImpl DRI = Sec.getRawDataRefImpl();
+ uint32_t Flags = getSectionFlags(this, DRI);
+ return Flags & MachO::SECTION_TYPE;
+}
+
// 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,
EndOffset = Value;
}
if (!EndOffset) {
- uint64_t Size;
DataRefImpl Sec;
Sec.d.a = SectionIndex-1;
- getSectionSize(Sec, Size);
- getSectionAddress(Sec, EndOffset);
+ uint64_t Size = getSectionSize(Sec);
+ EndOffset = getSectionAddress(Sec);
EndOffset += Size;
}
Result = EndOffset - BeginOffset;
if (Value && Value != UnknownAddressOrSize)
Result |= SymbolRef::SF_Common;
}
+
+ if (!(MachOType & MachO::N_PEXT))
+ Result |= SymbolRef::SF_Exported;
}
if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
return object_error::success;
}
-std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
- uint64_t &Res) const {
- if (is64Bit()) {
- MachO::section_64 Sect = getSection64(Sec);
- Res = Sect.addr;
- } else {
- MachO::section Sect = getSection(Sec);
- Res = Sect.addr;
- }
- return object_error::success;
+uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
+ if (is64Bit())
+ return getSection64(Sec).addr;
+ return getSection(Sec).addr;
}
-std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
- uint64_t &Res) const {
- if (is64Bit()) {
- MachO::section_64 Sect = getSection64(Sec);
- Res = Sect.size;
- } else {
- MachO::section Sect = getSection(Sec);
- Res = Sect.size;
- }
-
- return object_error::success;
+uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
+ if (is64Bit())
+ return getSection64(Sec).size;
+ return getSection(Sec).size;
}
std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
return object_error::success;
}
-std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
- uint64_t &Res) const {
+uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
uint32_t Align;
if (is64Bit()) {
MachO::section_64 Sect = getSection64(Sec);
Align = Sect.align;
}
- Res = uint64_t(1) << Align;
- return object_error::success;
+ return uint64_t(1) << Align;
}
-std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
- bool &Res) const {
+bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
uint32_t Flags = getSectionFlags(this, Sec);
- Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
- return object_error::success;
+ return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
}
-std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
- bool &Result) const {
+bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
uint32_t Flags = getSectionFlags(this, Sec);
unsigned SectionType = Flags & MachO::SECTION_TYPE;
- Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
- !(SectionType == MachO::S_ZEROFILL ||
- SectionType == MachO::S_GB_ZEROFILL);
- return object_error::success;
-}
-
-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) &&
- (SectionType == MachO::S_ZEROFILL ||
- SectionType == MachO::S_GB_ZEROFILL);
- return object_error::success;
-}
-
-std::error_code
-MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
- bool &Result) const {
- // FIXME: Unimplemented.
- Result = true;
- return object_error::success;
+ return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
+ !(SectionType == MachO::S_ZEROFILL ||
+ SectionType == MachO::S_GB_ZEROFILL);
}
-std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
- bool &Result) const {
- // FIXME: Unimplemented.
- Result = false;
- return object_error::success;
-}
-
-std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
- bool &Res) const {
+bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
uint32_t Flags = getSectionFlags(this, Sec);
unsigned SectionType = Flags & MachO::SECTION_TYPE;
- Res = SectionType == MachO::S_ZEROFILL ||
- SectionType == MachO::S_GB_ZEROFILL;
- return object_error::success;
+ return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
+ (SectionType == MachO::S_ZEROFILL ||
+ SectionType == MachO::S_GB_ZEROFILL);
}
-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.
-
+bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
// FIXME: Unimplemented.
- Result = false;
- return object_error::success;
+ return false;
}
-std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
- DataRefImpl Symb,
- bool &Result) const {
+bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
+ DataRefImpl Symb) const {
SymbolRef::Type ST;
this->getSymbolType(Symb, ST);
- if (ST == SymbolRef::ST_Unknown) {
- Result = false;
- return object_error::success;
- }
+ if (ST == SymbolRef::ST_Unknown)
+ return false;
- uint64_t SectBegin, SectEnd;
- getSectionAddress(Sec, SectBegin);
- getSectionSize(Sec, SectEnd);
+ uint64_t SectBegin = getSectionAddress(Sec);
+ uint64_t SectEnd = getSectionSize(Sec);
SectEnd += SectBegin;
uint64_t SymAddr;
getSymbolAddress(Symb, SymAddr);
- Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
-
- return object_error::success;
+ return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
}
relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
DataRefImpl Sec;
Sec.d.a = Rel.d.a;
- uint64_t SecAddress;
- getSectionAddress(Sec, SecAddress);
+ uint64_t SecAddress = getSectionAddress(Sec);
Res = SecAddress + Offset;
return object_error::success;
}
return basic_symbol_iterator(SymbolRef(DRI, this));
MachO::symtab_command Symtab = getSymtabLoadCommand();
- assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
+ if (Index >= Symtab.nsyms)
+ report_fatal_error("Requested symbol index is out of range.");
unsigned SymbolTableEntrySize =
is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
case llvm::MachO::CPU_TYPE_POWERPC:
return "Mach-O 32-bit ppc";
default:
- assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
- "64-bit object file when we're not 64-bit?");
return "Mach-O 32-bit unknown";
}
}
- // Make sure the cpu type has the correct mask.
- assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
- == llvm::MachO::CPU_ARCH_ABI64 &&
- "32-bit object file when we're 64-bit?");
-
switch (CPUType) {
case llvm::MachO::CPU_TYPE_X86_64:
return "Mach-O 64-bit x86-64";
// string that is the accumulation of all edge strings along the parent chain
// to this point.
//
-// There is one “export” node for each exported symbol. But because some
+// There is one "export" node for each exported symbol. But because some
// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
// node may have child nodes too.
//
iterator_range<export_iterator>
MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
ExportEntry Start(Trie);
- Start.moveToFirst();
+ if (Trie.size() == 0)
+ Start.moveToEnd();
+ else
+ Start.moveToFirst();
ExportEntry Finish(Trie);
Finish.moveToEnd();
while (*Ptr) {
++Ptr;
}
- ++Ptr;
SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
Ptr-SymStart);
+ ++Ptr;
DEBUG_WITH_TYPE(
"mach-o-bind",
llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
SegmentOffset) << "\n");
return;
case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
- AdvanceAmount = readULEB128();
+ AdvanceAmount = readULEB128() + PointerSize;
RemainingLoopCount = 0;
if (TableKind == Kind::Lazy)
Malformed = true;
DEBUG_WITH_TYPE(
"mach-o-bind",
- llvm::dbgs() << "BIND_OPCODE_DO_BIND_IMM_TIMES: "
+ llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset)
<< ", AdvanceAmount=" << AdvanceAmount
<< ", RemainingLoopCount=" << RemainingLoopCount
<< "\n");
return;
case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
- AdvanceAmount = ImmValue * PointerSize;
+ AdvanceAmount = ImmValue * PointerSize + PointerSize;
RemainingLoopCount = 0;
if (TableKind == Kind::Lazy)
Malformed = true;
ArrayRef<char>
MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
+ if (Sec.d.a >= Sections.size())
+ report_fatal_error("getSectionRawName: Invalid section index");
const section_base *Base =
reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
return makeArrayRef(Base->sectname);
ArrayRef<char>
MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
+ if (Sec.d.a >= Sections.size())
+ report_fatal_error("getSectionRawFinalSegmentName: Invalid section index");
const section_base *Base =
reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
return makeArrayRef(Base->segname);
return RE.r_word1;
}
+uint32_t MachOObjectFile::getScatteredRelocationType(
+ const MachO::any_relocation_info &RE) const {
+ return (RE.r_word0 >> 24) & 0xf;
+}
+
unsigned MachOObjectFile::getAnyRelocationAddress(
const MachO::any_relocation_info &RE) const {
if (isRelocationScattered(RE))
sizeof(MachO::mach_header);
Load.Ptr = getPtr(this, HeaderSize);
Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
+ if (Load.C.cmdsize < 8)
+ report_fatal_error("Load command with size < 8 bytes.");
return Load;
}
MachOObjectFile::LoadCommandInfo Next;
Next.Ptr = L.Ptr + L.C.cmdsize;
Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
+ if (Next.C.cmdsize < 8)
+ report_fatal_error("Load command with size < 8 bytes.");
return Next;
}
MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
+ // TODO: What if Sections.size() == 0?
+ if (DRI.d.a >= Sections.size())
+ report_fatal_error("getSection: Invalid section index.");
return getStruct<MachO::section>(this, Sections[DRI.d.a]);
}
MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
+ // TODO: What if Sections.size() == 0?
+ if (DRI.d.a >= Sections.size())
+ report_fatal_error("getSection64: Invalid section index.");
return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
}
return getStruct<MachO::segment_command_64>(this, L.Ptr);
}
-MachO::linker_options_command
-MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
- return getStruct<MachO::linker_options_command>(this, L.Ptr);
+MachO::linker_option_command
+MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::linker_option_command>(this, L.Ptr);
}
MachO::version_min_command
return getStruct<MachO::uuid_command>(this, L.Ptr);
}
+MachO::rpath_command
+MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::rpath_command>(this, L.Ptr);
+}
+
MachO::source_version_command
MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
return getStruct<MachO::source_version_command>(this, L.Ptr);
return getStruct<MachO::entry_point_command>(this, L.Ptr);
}
+MachO::encryption_info_command
+MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::encryption_info_command>(this, L.Ptr);
+}
+
+MachO::encryption_info_command_64
+MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
+ return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
+}
+
+MachO::sub_framework_command
+MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::sub_framework_command>(this, L.Ptr);
+}
+
+MachO::sub_umbrella_command
+MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
+}
+
+MachO::sub_library_command
+MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::sub_library_command>(this, L.Ptr);
+}
+
+MachO::sub_client_command
+MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::sub_client_command>(this, L.Ptr);
+}
+
+MachO::routines_command
+MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::routines_command>(this, L.Ptr);
+}
+
+MachO::routines_command_64
+MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
+ return getStruct<MachO::routines_command_64>(this, L.Ptr);
+}
+
+MachO::thread_command
+MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::thread_command>(this, L.Ptr);
+}
MachO::any_relocation_info
MachOObjectFile::getRelocation(DataRefImpl Rel) const {
}
MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
- return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
+ if (SymtabLoadCmd)
+ return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
+
+ // If there is no SymtabLoadCmd return a load command with zero'ed fields.
+ MachO::symtab_command Cmd;
+ Cmd.cmd = MachO::LC_SYMTAB;
+ Cmd.cmdsize = sizeof(MachO::symtab_command);
+ Cmd.symoff = 0;
+ Cmd.nsyms = 0;
+ Cmd.stroff = 0;
+ Cmd.strsize = 0;
+ return Cmd;
}
MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
- return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
+ if (DysymtabLoadCmd)
+ return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
+
+ // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
+ MachO::dysymtab_command Cmd;
+ Cmd.cmd = MachO::LC_DYSYMTAB;
+ Cmd.cmdsize = sizeof(MachO::dysymtab_command);
+ Cmd.ilocalsym = 0;
+ Cmd.nlocalsym = 0;
+ Cmd.iextdefsym = 0;
+ Cmd.nextdefsym = 0;
+ Cmd.iundefsym = 0;
+ Cmd.nundefsym = 0;
+ Cmd.tocoff = 0;
+ Cmd.ntoc = 0;
+ Cmd.modtaboff = 0;
+ Cmd.nmodtab = 0;
+ Cmd.extrefsymoff = 0;
+ Cmd.nextrefsyms = 0;
+ Cmd.indirectsymoff = 0;
+ Cmd.nindirectsyms = 0;
+ Cmd.extreloff = 0;
+ Cmd.nextrel = 0;
+ Cmd.locreloff = 0;
+ Cmd.nlocrel = 0;
+ return Cmd;
}
MachO::linkedit_data_command
return Cmd;
}
+MachO::linkedit_data_command
+MachOObjectFile::getLinkOptHintsLoadCommand() const {
+ if (LinkOptHintsLoadCmd)
+ return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
+
+ // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
+ // fields.
+ MachO::linkedit_data_command Cmd;
+ Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
+ Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
+ Cmd.dataoff = 0;
+ Cmd.datasize = 0;
+ return Cmd;
+}
+
ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
if (!DyldInfoLoadCmd)
return ArrayRef<uint8_t>();
return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
}
+ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
+ if (!UuidLoadCmd)
+ return ArrayRef<uint8_t>();
+ // Returning a pointer is fine as uuid doesn't need endian swapping.
+ const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
+ return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
+}
StringRef MachOObjectFile::getStringTableData() const {
MachO::symtab_command S = getSymtabLoadCommand();