blob: 579faf607c0b348f1a4582b02775cbd8c29779dd [file] [log] [blame]
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00001//===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
Eric Christopher7b015c72011-04-22 03:19:48 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000015#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/None.h"
Tim Northover00ed9962014-03-29 10:18:08 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000019#include "llvm/ADT/StringExtras.h"
20#include "llvm/ADT/StringRef.h"
Rafael Espindola72318b42014-08-08 16:30:17 +000021#include "llvm/ADT/StringSwitch.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/ADT/Triple.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000023#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000024#include "llvm/BinaryFormat/MachO.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000025#include "llvm/Object/Error.h"
26#include "llvm/Object/MachO.h"
27#include "llvm/Object/ObjectFile.h"
28#include "llvm/Object/SymbolicFile.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000029#include "llvm/Support/DataExtractor.h"
Nick Kledzikac431442014-09-12 21:34:15 +000030#include "llvm/Support/Debug.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000031#include "llvm/Support/Error.h"
32#include "llvm/Support/ErrorHandling.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000033#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000034#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000035#include "llvm/Support/LEB128.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000036#include "llvm/Support/MemoryBuffer.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000037#include "llvm/Support/SwapByteOrder.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000038#include "llvm/Support/raw_ostream.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000039#include <algorithm>
40#include <cassert>
41#include <cstddef>
42#include <cstdint>
Eric Christopher7b015c72011-04-22 03:19:48 +000043#include <cstring>
44#include <limits>
Kevin Enderbyd5039402016-10-31 20:29:48 +000045#include <list>
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000046#include <memory>
47#include <string>
48#include <system_error>
Eric Christopher7b015c72011-04-22 03:19:48 +000049
50using namespace llvm;
51using namespace object;
52
Artyom Skrobov7d602f72014-07-20 12:08:28 +000053namespace {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000054
Artyom Skrobov7d602f72014-07-20 12:08:28 +000055 struct section_base {
56 char sectname[16];
57 char segname[16];
58 };
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000059
60} // end anonymous namespace
Rafael Espindola56f976f2013-04-18 18:08:55 +000061
Lang Hames9e964f32016-03-25 17:25:34 +000062static Error
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000063malformedError(Twine Msg) {
Kevin Enderby89134962016-05-05 23:41:05 +000064 std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")";
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000065 return make_error<GenericBinaryError>(std::move(StringMsg),
Kevin Enderby89134962016-05-05 23:41:05 +000066 object_error::parse_failed);
Lang Hames9e964f32016-03-25 17:25:34 +000067}
68
Alexey Samsonov9f336632015-06-04 19:45:22 +000069// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000070template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000071static T getStruct(const MachOObjectFile &O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000072 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000073 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Filipe Cabecinhas40139502015-01-15 22:52:38 +000074 report_fatal_error("Malformed MachO file.");
75
Rafael Espindola3cdeb172013-04-19 13:45:05 +000076 T Cmd;
77 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000078 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000079 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000080 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000081}
82
Alexey Samsonov9f336632015-06-04 19:45:22 +000083template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000084static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000085 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000086 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000087 return malformedError("Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000088
89 T Cmd;
90 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000091 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Alexey Samsonov9f336632015-06-04 19:45:22 +000092 MachO::swapStruct(Cmd);
93 return Cmd;
94}
95
Rafael Espindola6e040c02013-04-26 20:07:33 +000096static const char *
Lang Hames697e7cd2016-12-04 01:56:10 +000097getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
Rafael Espindola6e040c02013-04-26 20:07:33 +000098 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000099 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
100
Lang Hames697e7cd2016-12-04 01:56:10 +0000101 bool Is64 = O.is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +0000102 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
103 sizeof(MachO::segment_command);
104 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
105 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000106
107 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +0000108 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +0000109}
110
Lang Hames697e7cd2016-12-04 01:56:10 +0000111static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
112 return O.getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +0000113}
114
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000115static MachO::nlist_base
Lang Hames697e7cd2016-12-04 01:56:10 +0000116getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +0000117 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000118 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +0000119}
120
Rafael Espindola56f976f2013-04-18 18:08:55 +0000121static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000122 if (P[15] == 0)
123 // Null terminated.
124 return P;
125 // Not null terminated, so this is a 16 char string.
126 return StringRef(P, 16);
127}
128
Lang Hames697e7cd2016-12-04 01:56:10 +0000129static unsigned getCPUType(const MachOObjectFile &O) {
130 return O.getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000131}
132
Charles Davis8bdfafd2013-09-01 04:28:48 +0000133static uint32_t
134getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
135 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000136}
137
138static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000139getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
140 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000141}
142
Lang Hames697e7cd2016-12-04 01:56:10 +0000143static bool getPlainRelocationPCRel(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000144 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000145 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000146 return (RE.r_word1 >> 24) & 1;
147 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000148}
149
150static bool
Lang Hames697e7cd2016-12-04 01:56:10 +0000151getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000152 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000153}
154
Lang Hames697e7cd2016-12-04 01:56:10 +0000155static unsigned getPlainRelocationLength(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000156 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000157 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000158 return (RE.r_word1 >> 25) & 3;
159 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000160}
161
162static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000163getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
164 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000165}
166
Lang Hames697e7cd2016-12-04 01:56:10 +0000167static unsigned getPlainRelocationType(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000168 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000169 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000170 return RE.r_word1 >> 28;
171 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000172}
173
Lang Hames697e7cd2016-12-04 01:56:10 +0000174static uint32_t getSectionFlags(const MachOObjectFile &O,
Rafael Espindola56f976f2013-04-18 18:08:55 +0000175 DataRefImpl Sec) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000176 if (O.is64Bit()) {
177 MachO::section_64 Sect = O.getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000178 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000179 }
Lang Hames697e7cd2016-12-04 01:56:10 +0000180 MachO::section Sect = O.getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000181 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000182}
183
Lang Hames9e964f32016-03-25 17:25:34 +0000184static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000185getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000186 uint32_t LoadCommandIndex) {
Lang Hames9e964f32016-03-25 17:25:34 +0000187 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
188 if (CmdOrErr->cmdsize < 8)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000189 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000190 " with size less than 8 bytes");
Lang Hames9e964f32016-03-25 17:25:34 +0000191 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
192 } else
193 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000194}
195
Lang Hames9e964f32016-03-25 17:25:34 +0000196static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000197getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
198 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
199 : sizeof(MachO::mach_header);
200 if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000201 return malformedError("load command 0 extends past the end all load "
Kevin Enderby89134962016-05-05 23:41:05 +0000202 "commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000203 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000204}
205
Lang Hames9e964f32016-03-25 17:25:34 +0000206static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000207getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000208 const MachOObjectFile::LoadCommandInfo &L) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000209 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
210 : sizeof(MachO::mach_header);
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000211 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
Lang Hames697e7cd2016-12-04 01:56:10 +0000212 Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000213 return malformedError("load command " + Twine(LoadCommandIndex + 1) +
Kevin Enderby89134962016-05-05 23:41:05 +0000214 " extends past the end all load commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000215 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000216}
217
Alexey Samsonov9f336632015-06-04 19:45:22 +0000218template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +0000219static void parseHeader(const MachOObjectFile &Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000220 Error &Err) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000221 if (sizeof(T) > Obj.getData().size()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000222 Err = malformedError("the mach header extends past the end of the "
Kevin Enderby89134962016-05-05 23:41:05 +0000223 "file");
Kevin Enderby87025742016-04-13 21:17:58 +0000224 return;
225 }
Lang Hames9e964f32016-03-25 17:25:34 +0000226 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
227 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000228 else
Lang Hames9e964f32016-03-25 17:25:34 +0000229 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000230}
231
Kevin Enderbyd5039402016-10-31 20:29:48 +0000232// This is used to check for overlapping of Mach-O elements.
233struct MachOElement {
234 uint64_t Offset;
235 uint64_t Size;
236 const char *Name;
237};
238
239static Error checkOverlappingElement(std::list<MachOElement> &Elements,
240 uint64_t Offset, uint64_t Size,
241 const char *Name) {
242 if (Size == 0)
243 return Error::success();
244
245 for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
246 auto E = *it;
247 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
248 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
249 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
250 return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
251 " with a size of " + Twine(Size) + ", overlaps " +
252 E.Name + " at offset " + Twine(E.Offset) + " with "
253 "a size of " + Twine(E.Size));
254 auto nt = it;
255 nt++;
256 if (nt != Elements.end()) {
257 auto N = *nt;
258 if (Offset + Size <= N.Offset) {
259 Elements.insert(nt, {Offset, Size, Name});
260 return Error::success();
261 }
262 }
263 }
264 Elements.push_back({Offset, Size, Name});
265 return Error::success();
266}
267
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000268// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
269// sections to \param Sections, and optionally sets
270// \param IsPageZeroSegment to true.
Kevin Enderbyc614d282016-08-12 20:10:25 +0000271template <typename Segment, typename Section>
Lang Hames9e964f32016-03-25 17:25:34 +0000272static Error parseSegmentLoadCommand(
Lang Hames697e7cd2016-12-04 01:56:10 +0000273 const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000274 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000275 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
276 std::list<MachOElement> &Elements) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000277 const unsigned SegmentLoadSize = sizeof(Segment);
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000278 if (Load.C.cmdsize < SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000279 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000280 " " + CmdName + " cmdsize too small");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000281 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
282 Segment S = SegOrErr.get();
283 const unsigned SectionSize = sizeof(Section);
Lang Hames697e7cd2016-12-04 01:56:10 +0000284 uint64_t FileSize = Obj.getData().size();
Lang Hames9e964f32016-03-25 17:25:34 +0000285 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
286 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000287 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000288 " inconsistent cmdsize in " + CmdName +
Kevin Enderby89134962016-05-05 23:41:05 +0000289 " for the number of sections");
Lang Hames9e964f32016-03-25 17:25:34 +0000290 for (unsigned J = 0; J < S.nsects; ++J) {
291 const char *Sec = getSectionPtr(Obj, Load, J);
292 Sections.push_back(Sec);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000293 Section s = getStruct<Section>(Obj, Sec);
Lang Hames697e7cd2016-12-04 01:56:10 +0000294 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
295 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000296 s.flags != MachO::S_ZEROFILL &&
297 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
298 s.offset > FileSize)
299 return malformedError("offset field of section " + Twine(J) + " in " +
300 CmdName + " command " + Twine(LoadCommandIndex) +
301 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000302 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
303 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000304 s.flags != MachO::S_ZEROFILL &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000305 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
306 s.offset < SizeOfHeaders && s.size != 0)
Kevin Enderbyc614d282016-08-12 20:10:25 +0000307 return malformedError("offset field of section " + Twine(J) + " in " +
308 CmdName + " command " + Twine(LoadCommandIndex) +
309 " not past the headers of the file");
310 uint64_t BigSize = s.offset;
311 BigSize += s.size;
Lang Hames697e7cd2016-12-04 01:56:10 +0000312 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
313 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000314 s.flags != MachO::S_ZEROFILL &&
315 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
316 BigSize > FileSize)
317 return malformedError("offset field plus size field of section " +
318 Twine(J) + " in " + CmdName + " command " +
319 Twine(LoadCommandIndex) +
320 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000321 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
322 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000323 s.flags != MachO::S_ZEROFILL &&
324 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
325 s.size > S.filesize)
326 return malformedError("size field of section " +
327 Twine(J) + " in " + CmdName + " command " +
328 Twine(LoadCommandIndex) +
329 " greater than the segment");
Lang Hames697e7cd2016-12-04 01:56:10 +0000330 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
331 Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000332 s.addr < S.vmaddr)
333 return malformedError("addr field of section " + Twine(J) + " in " +
334 CmdName + " command " + Twine(LoadCommandIndex) +
335 " less than the segment's vmaddr");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000336 BigSize = s.addr;
337 BigSize += s.size;
338 uint64_t BigEnd = S.vmaddr;
339 BigEnd += S.vmsize;
340 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000341 return malformedError("addr field plus size of section " + Twine(J) +
342 " in " + CmdName + " command " +
343 Twine(LoadCommandIndex) +
344 " greater than than "
Kevin Enderbyc614d282016-08-12 20:10:25 +0000345 "the segment's vmaddr plus vmsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000346 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
347 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000348 s.flags != MachO::S_ZEROFILL &&
349 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
350 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
351 "section contents"))
352 return Err;
Kevin Enderbyc614d282016-08-12 20:10:25 +0000353 if (s.reloff > FileSize)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000354 return malformedError("reloff field of section " + Twine(J) + " in " +
355 CmdName + " command " + Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000356 " extends past the end of the file");
357 BigSize = s.nreloc;
358 BigSize *= sizeof(struct MachO::relocation_info);
359 BigSize += s.reloff;
360 if (BigSize > FileSize)
361 return malformedError("reloff field plus nreloc field times sizeof("
362 "struct relocation_info) of section " +
363 Twine(J) + " in " + CmdName + " command " +
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000364 Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000365 " extends past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000366 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
367 sizeof(struct
368 MachO::relocation_info),
369 "section relocation entries"))
370 return Err;
Lang Hames9e964f32016-03-25 17:25:34 +0000371 }
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000372 if (S.fileoff > FileSize)
373 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000374 " fileoff field in " + CmdName +
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000375 " extends past the end of the file");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000376 uint64_t BigSize = S.fileoff;
377 BigSize += S.filesize;
378 if (BigSize > FileSize)
379 return malformedError("load command " + Twine(LoadCommandIndex) +
380 " fileoff field plus filesize field in " +
381 CmdName + " extends past the end of the file");
382 if (S.vmsize != 0 && S.filesize > S.vmsize)
383 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby86d8bd12017-02-07 21:20:44 +0000384 " filesize field in " + CmdName +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000385 " greater than vmsize field");
Lang Hames9e964f32016-03-25 17:25:34 +0000386 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
387 } else
388 return SegOrErr.takeError();
389
390 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000391}
392
Lang Hames697e7cd2016-12-04 01:56:10 +0000393static Error checkSymtabCommand(const MachOObjectFile &Obj,
Kevin Enderby0e52c922016-08-26 19:34:07 +0000394 const MachOObjectFile::LoadCommandInfo &Load,
395 uint32_t LoadCommandIndex,
Kevin Enderbyd5039402016-10-31 20:29:48 +0000396 const char **SymtabLoadCmd,
397 std::list<MachOElement> &Elements) {
Kevin Enderby0e52c922016-08-26 19:34:07 +0000398 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
399 return malformedError("load command " + Twine(LoadCommandIndex) +
400 " LC_SYMTAB cmdsize too small");
401 if (*SymtabLoadCmd != nullptr)
402 return malformedError("more than one LC_SYMTAB command");
403 MachO::symtab_command Symtab =
404 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
405 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
406 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
407 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000408 uint64_t FileSize = Obj.getData().size();
Kevin Enderby0e52c922016-08-26 19:34:07 +0000409 if (Symtab.symoff > FileSize)
410 return malformedError("symoff field of LC_SYMTAB command " +
411 Twine(LoadCommandIndex) + " extends past the end "
412 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000413 uint64_t SymtabSize = Symtab.nsyms;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000414 const char *struct_nlist_name;
Lang Hames697e7cd2016-12-04 01:56:10 +0000415 if (Obj.is64Bit()) {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000416 SymtabSize *= sizeof(MachO::nlist_64);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000417 struct_nlist_name = "struct nlist_64";
418 } else {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000419 SymtabSize *= sizeof(MachO::nlist);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000420 struct_nlist_name = "struct nlist";
421 }
Kevin Enderbyd5039402016-10-31 20:29:48 +0000422 uint64_t BigSize = SymtabSize;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000423 BigSize += Symtab.symoff;
424 if (BigSize > FileSize)
425 return malformedError("symoff field plus nsyms field times sizeof(" +
426 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
427 Twine(LoadCommandIndex) + " extends past the end "
428 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000429 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
430 "symbol table"))
431 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000432 if (Symtab.stroff > FileSize)
433 return malformedError("stroff field of LC_SYMTAB command " +
434 Twine(LoadCommandIndex) + " extends past the end "
435 "of the file");
436 BigSize = Symtab.stroff;
437 BigSize += Symtab.strsize;
438 if (BigSize > FileSize)
439 return malformedError("stroff field plus strsize field of LC_SYMTAB "
440 "command " + Twine(LoadCommandIndex) + " extends "
441 "past the end of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000442 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
443 Symtab.strsize, "string table"))
444 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000445 *SymtabLoadCmd = Load.Ptr;
446 return Error::success();
447}
448
Lang Hames697e7cd2016-12-04 01:56:10 +0000449static Error checkDysymtabCommand(const MachOObjectFile &Obj,
450 const MachOObjectFile::LoadCommandInfo &Load,
451 uint32_t LoadCommandIndex,
452 const char **DysymtabLoadCmd,
453 std::list<MachOElement> &Elements) {
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000454 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
455 return malformedError("load command " + Twine(LoadCommandIndex) +
456 " LC_DYSYMTAB cmdsize too small");
457 if (*DysymtabLoadCmd != nullptr)
458 return malformedError("more than one LC_DYSYMTAB command");
459 MachO::dysymtab_command Dysymtab =
460 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
461 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
462 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
463 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000464 uint64_t FileSize = Obj.getData().size();
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000465 if (Dysymtab.tocoff > FileSize)
466 return malformedError("tocoff field of LC_DYSYMTAB command " +
467 Twine(LoadCommandIndex) + " extends past the end of "
468 "the file");
469 uint64_t BigSize = Dysymtab.ntoc;
470 BigSize *= sizeof(MachO::dylib_table_of_contents);
471 BigSize += Dysymtab.tocoff;
472 if (BigSize > FileSize)
473 return malformedError("tocoff field plus ntoc field times sizeof(struct "
474 "dylib_table_of_contents) of LC_DYSYMTAB command " +
475 Twine(LoadCommandIndex) + " extends past the end of "
476 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000477 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
478 Dysymtab.ntoc * sizeof(struct
479 MachO::dylib_table_of_contents),
480 "table of contents"))
481 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000482 if (Dysymtab.modtaboff > FileSize)
483 return malformedError("modtaboff field of LC_DYSYMTAB command " +
484 Twine(LoadCommandIndex) + " extends past the end of "
485 "the file");
486 BigSize = Dysymtab.nmodtab;
487 const char *struct_dylib_module_name;
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000488 uint64_t sizeof_modtab;
Lang Hames697e7cd2016-12-04 01:56:10 +0000489 if (Obj.is64Bit()) {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000490 sizeof_modtab = sizeof(MachO::dylib_module_64);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000491 struct_dylib_module_name = "struct dylib_module_64";
492 } else {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000493 sizeof_modtab = sizeof(MachO::dylib_module);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000494 struct_dylib_module_name = "struct dylib_module";
495 }
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000496 BigSize *= sizeof_modtab;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000497 BigSize += Dysymtab.modtaboff;
498 if (BigSize > FileSize)
499 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
500 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
501 "command " + Twine(LoadCommandIndex) + " extends "
502 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000503 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
504 Dysymtab.nmodtab * sizeof_modtab,
505 "module table"))
506 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000507 if (Dysymtab.extrefsymoff > FileSize)
508 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
509 Twine(LoadCommandIndex) + " extends past the end of "
510 "the file");
511 BigSize = Dysymtab.nextrefsyms;
512 BigSize *= sizeof(MachO::dylib_reference);
513 BigSize += Dysymtab.extrefsymoff;
514 if (BigSize > FileSize)
515 return malformedError("extrefsymoff field plus nextrefsyms field times "
516 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
517 "command " + Twine(LoadCommandIndex) + " extends "
518 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000519 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
520 Dysymtab.nextrefsyms *
521 sizeof(MachO::dylib_reference),
522 "reference table"))
523 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000524 if (Dysymtab.indirectsymoff > FileSize)
525 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
526 Twine(LoadCommandIndex) + " extends past the end of "
527 "the file");
528 BigSize = Dysymtab.nindirectsyms;
529 BigSize *= sizeof(uint32_t);
530 BigSize += Dysymtab.indirectsymoff;
531 if (BigSize > FileSize)
532 return malformedError("indirectsymoff field plus nindirectsyms field times "
533 "sizeof(uint32_t) of LC_DYSYMTAB command " +
534 Twine(LoadCommandIndex) + " extends past the end of "
535 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000536 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
537 Dysymtab.nindirectsyms *
538 sizeof(uint32_t),
539 "indirect table"))
540 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000541 if (Dysymtab.extreloff > FileSize)
542 return malformedError("extreloff field of LC_DYSYMTAB command " +
543 Twine(LoadCommandIndex) + " extends past the end of "
544 "the file");
545 BigSize = Dysymtab.nextrel;
546 BigSize *= sizeof(MachO::relocation_info);
547 BigSize += Dysymtab.extreloff;
548 if (BigSize > FileSize)
549 return malformedError("extreloff field plus nextrel field times sizeof"
550 "(struct relocation_info) of LC_DYSYMTAB command " +
551 Twine(LoadCommandIndex) + " extends past the end of "
552 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000553 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
554 Dysymtab.nextrel *
555 sizeof(MachO::relocation_info),
556 "external relocation table"))
557 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000558 if (Dysymtab.locreloff > FileSize)
559 return malformedError("locreloff field of LC_DYSYMTAB command " +
560 Twine(LoadCommandIndex) + " extends past the end of "
561 "the file");
562 BigSize = Dysymtab.nlocrel;
563 BigSize *= sizeof(MachO::relocation_info);
564 BigSize += Dysymtab.locreloff;
565 if (BigSize > FileSize)
566 return malformedError("locreloff field plus nlocrel field times sizeof"
567 "(struct relocation_info) of LC_DYSYMTAB command " +
568 Twine(LoadCommandIndex) + " extends past the end of "
569 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000570 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
571 Dysymtab.nlocrel *
572 sizeof(MachO::relocation_info),
573 "local relocation table"))
574 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000575 *DysymtabLoadCmd = Load.Ptr;
576 return Error::success();
577}
578
Lang Hames697e7cd2016-12-04 01:56:10 +0000579static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000580 const MachOObjectFile::LoadCommandInfo &Load,
581 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000582 const char **LoadCmd, const char *CmdName,
583 std::list<MachOElement> &Elements,
584 const char *ElementName) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000585 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
586 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
587 CmdName + " cmdsize too small");
588 if (*LoadCmd != nullptr)
589 return malformedError("more than one " + Twine(CmdName) + " command");
590 MachO::linkedit_data_command LinkData =
591 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
592 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
593 return malformedError(Twine(CmdName) + " command " +
594 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000595 uint64_t FileSize = Obj.getData().size();
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000596 if (LinkData.dataoff > FileSize)
597 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
598 Twine(LoadCommandIndex) + " extends past the end of "
599 "the file");
600 uint64_t BigSize = LinkData.dataoff;
601 BigSize += LinkData.datasize;
602 if (BigSize > FileSize)
603 return malformedError("dataoff field plus datasize field of " +
604 Twine(CmdName) + " command " +
605 Twine(LoadCommandIndex) + " extends past the end of "
606 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000607 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
608 LinkData.datasize, ElementName))
609 return Err;
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000610 *LoadCmd = Load.Ptr;
611 return Error::success();
612}
613
Lang Hames697e7cd2016-12-04 01:56:10 +0000614static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000615 const MachOObjectFile::LoadCommandInfo &Load,
616 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000617 const char **LoadCmd, const char *CmdName,
618 std::list<MachOElement> &Elements) {
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000619 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
620 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
621 CmdName + " cmdsize too small");
622 if (*LoadCmd != nullptr)
623 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
624 "command");
625 MachO::dyld_info_command DyldInfo =
626 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
627 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
628 return malformedError(Twine(CmdName) + " command " +
629 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000630 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000631 if (DyldInfo.rebase_off > FileSize)
632 return malformedError("rebase_off field of " + Twine(CmdName) +
633 " command " + Twine(LoadCommandIndex) + " extends "
634 "past the end of the file");
635 uint64_t BigSize = DyldInfo.rebase_off;
636 BigSize += DyldInfo.rebase_size;
637 if (BigSize > FileSize)
638 return malformedError("rebase_off field plus rebase_size field of " +
639 Twine(CmdName) + " command " +
640 Twine(LoadCommandIndex) + " extends past the end of "
641 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000642 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
643 DyldInfo.rebase_size,
644 "dyld rebase info"))
645 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000646 if (DyldInfo.bind_off > FileSize)
647 return malformedError("bind_off field of " + Twine(CmdName) +
648 " command " + Twine(LoadCommandIndex) + " extends "
649 "past the end of the file");
650 BigSize = DyldInfo.bind_off;
651 BigSize += DyldInfo.bind_size;
652 if (BigSize > FileSize)
653 return malformedError("bind_off field plus bind_size field of " +
654 Twine(CmdName) + " command " +
655 Twine(LoadCommandIndex) + " extends past the end of "
656 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000657 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
658 DyldInfo.bind_size,
659 "dyld bind info"))
660 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000661 if (DyldInfo.weak_bind_off > FileSize)
662 return malformedError("weak_bind_off field of " + Twine(CmdName) +
663 " command " + Twine(LoadCommandIndex) + " extends "
664 "past the end of the file");
665 BigSize = DyldInfo.weak_bind_off;
666 BigSize += DyldInfo.weak_bind_size;
667 if (BigSize > FileSize)
668 return malformedError("weak_bind_off field plus weak_bind_size field of " +
669 Twine(CmdName) + " command " +
670 Twine(LoadCommandIndex) + " extends past the end of "
671 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000672 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
673 DyldInfo.weak_bind_size,
674 "dyld weak bind info"))
675 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000676 if (DyldInfo.lazy_bind_off > FileSize)
677 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
678 " command " + Twine(LoadCommandIndex) + " extends "
679 "past the end of the file");
680 BigSize = DyldInfo.lazy_bind_off;
681 BigSize += DyldInfo.lazy_bind_size;
682 if (BigSize > FileSize)
683 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
684 Twine(CmdName) + " command " +
685 Twine(LoadCommandIndex) + " extends past the end of "
686 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000687 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
688 DyldInfo.lazy_bind_size,
689 "dyld lazy bind info"))
690 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000691 if (DyldInfo.export_off > FileSize)
692 return malformedError("export_off field of " + Twine(CmdName) +
693 " command " + Twine(LoadCommandIndex) + " extends "
694 "past the end of the file");
695 BigSize = DyldInfo.export_off;
696 BigSize += DyldInfo.export_size;
697 if (BigSize > FileSize)
698 return malformedError("export_off field plus export_size field of " +
699 Twine(CmdName) + " command " +
700 Twine(LoadCommandIndex) + " extends past the end of "
701 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000702 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
703 DyldInfo.export_size,
704 "dyld export info"))
705 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000706 *LoadCmd = Load.Ptr;
707 return Error::success();
708}
709
Lang Hames697e7cd2016-12-04 01:56:10 +0000710static Error checkDylibCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000711 const MachOObjectFile::LoadCommandInfo &Load,
712 uint32_t LoadCommandIndex, const char *CmdName) {
713 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
714 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
715 CmdName + " cmdsize too small");
716 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
717 if (D.dylib.name < sizeof(MachO::dylib_command))
718 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
719 CmdName + " name.offset field too small, not past "
720 "the end of the dylib_command struct");
721 if (D.dylib.name >= D.cmdsize)
722 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
723 CmdName + " name.offset field extends past the end "
724 "of the load command");
725 // Make sure there is a null between the starting offset of the name and
726 // the end of the load command.
727 uint32_t i;
728 const char *P = (const char *)Load.Ptr;
729 for (i = D.dylib.name; i < D.cmdsize; i++)
730 if (P[i] == '\0')
731 break;
732 if (i >= D.cmdsize)
733 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
734 CmdName + " library name extends past the end of the "
735 "load command");
736 return Error::success();
737}
738
Lang Hames697e7cd2016-12-04 01:56:10 +0000739static Error checkDylibIdCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000740 const MachOObjectFile::LoadCommandInfo &Load,
741 uint32_t LoadCommandIndex,
742 const char **LoadCmd) {
743 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
744 "LC_ID_DYLIB"))
745 return Err;
746 if (*LoadCmd != nullptr)
747 return malformedError("more than one LC_ID_DYLIB command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000748 if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
749 Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000750 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
751 "file type");
752 *LoadCmd = Load.Ptr;
753 return Error::success();
754}
755
Lang Hames697e7cd2016-12-04 01:56:10 +0000756static Error checkDyldCommand(const MachOObjectFile &Obj,
Kevin Enderby3e490ef2016-09-27 23:24:13 +0000757 const MachOObjectFile::LoadCommandInfo &Load,
758 uint32_t LoadCommandIndex, const char *CmdName) {
759 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
760 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
761 CmdName + " cmdsize too small");
762 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
763 if (D.name < sizeof(MachO::dylinker_command))
764 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
765 CmdName + " name.offset field too small, not past "
766 "the end of the dylinker_command struct");
767 if (D.name >= D.cmdsize)
768 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
769 CmdName + " name.offset field extends past the end "
770 "of the load command");
771 // Make sure there is a null between the starting offset of the name and
772 // the end of the load command.
773 uint32_t i;
774 const char *P = (const char *)Load.Ptr;
775 for (i = D.name; i < D.cmdsize; i++)
776 if (P[i] == '\0')
777 break;
778 if (i >= D.cmdsize)
779 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
780 CmdName + " dyld name extends past the end of the "
781 "load command");
782 return Error::success();
783}
784
Lang Hames697e7cd2016-12-04 01:56:10 +0000785static Error checkVersCommand(const MachOObjectFile &Obj,
Kevin Enderby32359db2016-09-28 21:20:45 +0000786 const MachOObjectFile::LoadCommandInfo &Load,
787 uint32_t LoadCommandIndex,
788 const char **LoadCmd, const char *CmdName) {
789 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
790 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
791 CmdName + " has incorrect cmdsize");
792 if (*LoadCmd != nullptr)
793 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
794 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
795 "LC_VERSION_MIN_WATCHOS command");
796 *LoadCmd = Load.Ptr;
797 return Error::success();
798}
799
Kevin Enderbya4579c42017-01-19 17:36:31 +0000800static Error checkNoteCommand(const MachOObjectFile &Obj,
801 const MachOObjectFile::LoadCommandInfo &Load,
802 uint32_t LoadCommandIndex,
803 std::list<MachOElement> &Elements) {
804 if (Load.C.cmdsize != sizeof(MachO::note_command))
805 return malformedError("load command " + Twine(LoadCommandIndex) +
806 " LC_NOTE has incorrect cmdsize");
807 MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
808 uint64_t FileSize = Obj.getData().size();
809 if (Nt.offset > FileSize)
810 return malformedError("offset field of LC_NOTE command " +
811 Twine(LoadCommandIndex) + " extends "
812 "past the end of the file");
813 uint64_t BigSize = Nt.offset;
814 BigSize += Nt.size;
815 if (BigSize > FileSize)
816 return malformedError("size field plus offset field of LC_NOTE command " +
817 Twine(LoadCommandIndex) + " extends past the end of "
818 "the file");
819 if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
820 "LC_NOTE data"))
821 return Err;
822 return Error::success();
823}
824
Steven Wu5b54a422017-01-23 20:07:55 +0000825static Error
826parseBuildVersionCommand(const MachOObjectFile &Obj,
827 const MachOObjectFile::LoadCommandInfo &Load,
828 SmallVectorImpl<const char*> &BuildTools,
829 uint32_t LoadCommandIndex) {
830 MachO::build_version_command BVC =
831 getStruct<MachO::build_version_command>(Obj, Load.Ptr);
832 if (Load.C.cmdsize !=
833 sizeof(MachO::build_version_command) +
834 BVC.ntools * sizeof(MachO::build_tool_version))
835 return malformedError("load command " + Twine(LoadCommandIndex) +
836 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
837
838 auto Start = Load.Ptr + sizeof(MachO::build_version_command);
839 BuildTools.resize(BVC.ntools);
840 for (unsigned i = 0; i < BVC.ntools; ++i)
841 BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
842
843 return Error::success();
844}
845
Lang Hames697e7cd2016-12-04 01:56:10 +0000846static Error checkRpathCommand(const MachOObjectFile &Obj,
Kevin Enderby76966bf2016-09-28 23:16:01 +0000847 const MachOObjectFile::LoadCommandInfo &Load,
848 uint32_t LoadCommandIndex) {
849 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
850 return malformedError("load command " + Twine(LoadCommandIndex) +
851 " LC_RPATH cmdsize too small");
852 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
853 if (R.path < sizeof(MachO::rpath_command))
854 return malformedError("load command " + Twine(LoadCommandIndex) +
855 " LC_RPATH path.offset field too small, not past "
856 "the end of the rpath_command struct");
857 if (R.path >= R.cmdsize)
858 return malformedError("load command " + Twine(LoadCommandIndex) +
859 " LC_RPATH path.offset field extends past the end "
860 "of the load command");
861 // Make sure there is a null between the starting offset of the path and
862 // the end of the load command.
863 uint32_t i;
864 const char *P = (const char *)Load.Ptr;
865 for (i = R.path; i < R.cmdsize; i++)
866 if (P[i] == '\0')
867 break;
868 if (i >= R.cmdsize)
869 return malformedError("load command " + Twine(LoadCommandIndex) +
870 " LC_RPATH library name extends past the end of the "
871 "load command");
872 return Error::success();
873}
874
Lang Hames697e7cd2016-12-04 01:56:10 +0000875static Error checkEncryptCommand(const MachOObjectFile &Obj,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000876 const MachOObjectFile::LoadCommandInfo &Load,
877 uint32_t LoadCommandIndex,
878 uint64_t cryptoff, uint64_t cryptsize,
879 const char **LoadCmd, const char *CmdName) {
880 if (*LoadCmd != nullptr)
881 return malformedError("more than one LC_ENCRYPTION_INFO and or "
882 "LC_ENCRYPTION_INFO_64 command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000883 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000884 if (cryptoff > FileSize)
885 return malformedError("cryptoff field of " + Twine(CmdName) +
886 " command " + Twine(LoadCommandIndex) + " extends "
887 "past the end of the file");
888 uint64_t BigSize = cryptoff;
889 BigSize += cryptsize;
890 if (BigSize > FileSize)
891 return malformedError("cryptoff field plus cryptsize field of " +
892 Twine(CmdName) + " command " +
893 Twine(LoadCommandIndex) + " extends past the end of "
894 "the file");
895 *LoadCmd = Load.Ptr;
896 return Error::success();
897}
898
Lang Hames697e7cd2016-12-04 01:56:10 +0000899static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
Kevin Enderby68fffa82016-10-11 21:04:39 +0000900 const MachOObjectFile::LoadCommandInfo &Load,
901 uint32_t LoadCommandIndex) {
902 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
903 return malformedError("load command " + Twine(LoadCommandIndex) +
904 " LC_LINKER_OPTION cmdsize too small");
905 MachO::linker_option_command L =
906 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
907 // Make sure the count of strings is correct.
908 const char *string = (const char *)Load.Ptr +
909 sizeof(struct MachO::linker_option_command);
910 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
911 uint32_t i = 0;
912 while (left > 0) {
913 while (*string == '\0' && left > 0) {
914 string++;
915 left--;
916 }
917 if (left > 0) {
918 i++;
919 uint32_t NullPos = StringRef(string, left).find('\0');
920 uint32_t len = std::min(NullPos, left) + 1;
921 string += len;
922 left -= len;
923 }
924 }
925 if (L.count != i)
926 return malformedError("load command " + Twine(LoadCommandIndex) +
927 " LC_LINKER_OPTION string count " + Twine(L.count) +
928 " does not match number of strings");
929 return Error::success();
930}
931
Lang Hames697e7cd2016-12-04 01:56:10 +0000932static Error checkSubCommand(const MachOObjectFile &Obj,
Kevin Enderby2490de02016-10-17 22:09:25 +0000933 const MachOObjectFile::LoadCommandInfo &Load,
934 uint32_t LoadCommandIndex, const char *CmdName,
935 size_t SizeOfCmd, const char *CmdStructName,
936 uint32_t PathOffset, const char *PathFieldName) {
937 if (PathOffset < SizeOfCmd)
938 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
939 CmdName + " " + PathFieldName + ".offset field too "
940 "small, not past the end of the " + CmdStructName);
941 if (PathOffset >= Load.C.cmdsize)
942 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
943 CmdName + " " + PathFieldName + ".offset field "
944 "extends past the end of the load command");
945 // Make sure there is a null between the starting offset of the path and
946 // the end of the load command.
947 uint32_t i;
948 const char *P = (const char *)Load.Ptr;
949 for (i = PathOffset; i < Load.C.cmdsize; i++)
950 if (P[i] == '\0')
951 break;
952 if (i >= Load.C.cmdsize)
953 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
954 CmdName + " " + PathFieldName + " name extends past "
955 "the end of the load command");
956 return Error::success();
957}
958
Lang Hames697e7cd2016-12-04 01:56:10 +0000959static Error checkThreadCommand(const MachOObjectFile &Obj,
Kevin Enderby210030b2016-10-19 23:44:34 +0000960 const MachOObjectFile::LoadCommandInfo &Load,
961 uint32_t LoadCommandIndex,
962 const char *CmdName) {
963 if (Load.C.cmdsize < sizeof(MachO::thread_command))
964 return malformedError("load command " + Twine(LoadCommandIndex) +
965 CmdName + " cmdsize too small");
966 MachO::thread_command T =
967 getStruct<MachO::thread_command>(Obj, Load.Ptr);
968 const char *state = Load.Ptr + sizeof(MachO::thread_command);
969 const char *end = Load.Ptr + T.cmdsize;
970 uint32_t nflavor = 0;
971 uint32_t cputype = getCPUType(Obj);
972 while (state < end) {
973 if(state + sizeof(uint32_t) > end)
974 return malformedError("load command " + Twine(LoadCommandIndex) +
975 "flavor in " + CmdName + " extends past end of "
976 "command");
977 uint32_t flavor;
978 memcpy(&flavor, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000979 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000980 sys::swapByteOrder(flavor);
981 state += sizeof(uint32_t);
982
983 if(state + sizeof(uint32_t) > end)
984 return malformedError("load command " + Twine(LoadCommandIndex) +
985 " count in " + CmdName + " extends past end of "
986 "command");
987 uint32_t count;
988 memcpy(&count, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000989 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000990 sys::swapByteOrder(count);
991 state += sizeof(uint32_t);
992
Kevin Enderbyc3a035d2017-01-23 21:13:29 +0000993 if (cputype == MachO::CPU_TYPE_I386) {
994 if (flavor == MachO::x86_THREAD_STATE32) {
995 if (count != MachO::x86_THREAD_STATE32_COUNT)
996 return malformedError("load command " + Twine(LoadCommandIndex) +
997 " count not x86_THREAD_STATE32_COUNT for "
998 "flavor number " + Twine(nflavor) + " which is "
999 "a x86_THREAD_STATE32 flavor in " + CmdName +
1000 " command");
1001 if (state + sizeof(MachO::x86_thread_state32_t) > end)
1002 return malformedError("load command " + Twine(LoadCommandIndex) +
1003 " x86_THREAD_STATE32 extends past end of "
1004 "command in " + CmdName + " command");
1005 state += sizeof(MachO::x86_thread_state32_t);
1006 } else {
1007 return malformedError("load command " + Twine(LoadCommandIndex) +
1008 " unknown flavor (" + Twine(flavor) + ") for "
1009 "flavor number " + Twine(nflavor) + " in " +
1010 CmdName + " command");
1011 }
1012 } else if (cputype == MachO::CPU_TYPE_X86_64) {
Kevin Enderby210030b2016-10-19 23:44:34 +00001013 if (flavor == MachO::x86_THREAD_STATE64) {
1014 if (count != MachO::x86_THREAD_STATE64_COUNT)
1015 return malformedError("load command " + Twine(LoadCommandIndex) +
1016 " count not x86_THREAD_STATE64_COUNT for "
1017 "flavor number " + Twine(nflavor) + " which is "
1018 "a x86_THREAD_STATE64 flavor in " + CmdName +
1019 " command");
1020 if (state + sizeof(MachO::x86_thread_state64_t) > end)
1021 return malformedError("load command " + Twine(LoadCommandIndex) +
1022 " x86_THREAD_STATE64 extends past end of "
1023 "command in " + CmdName + " command");
1024 state += sizeof(MachO::x86_thread_state64_t);
1025 } else {
1026 return malformedError("load command " + Twine(LoadCommandIndex) +
1027 " unknown flavor (" + Twine(flavor) + ") for "
1028 "flavor number " + Twine(nflavor) + " in " +
1029 CmdName + " command");
1030 }
1031 } else if (cputype == MachO::CPU_TYPE_ARM) {
1032 if (flavor == MachO::ARM_THREAD_STATE) {
1033 if (count != MachO::ARM_THREAD_STATE_COUNT)
1034 return malformedError("load command " + Twine(LoadCommandIndex) +
1035 " count not ARM_THREAD_STATE_COUNT for "
1036 "flavor number " + Twine(nflavor) + " which is "
1037 "a ARM_THREAD_STATE flavor in " + CmdName +
1038 " command");
1039 if (state + sizeof(MachO::arm_thread_state32_t) > end)
1040 return malformedError("load command " + Twine(LoadCommandIndex) +
1041 " ARM_THREAD_STATE extends past end of "
1042 "command in " + CmdName + " command");
1043 state += sizeof(MachO::arm_thread_state32_t);
1044 } else {
1045 return malformedError("load command " + Twine(LoadCommandIndex) +
1046 " unknown flavor (" + Twine(flavor) + ") for "
1047 "flavor number " + Twine(nflavor) + " in " +
1048 CmdName + " command");
1049 }
Kevin Enderby7747cb52016-11-03 20:51:28 +00001050 } else if (cputype == MachO::CPU_TYPE_ARM64) {
1051 if (flavor == MachO::ARM_THREAD_STATE64) {
1052 if (count != MachO::ARM_THREAD_STATE64_COUNT)
1053 return malformedError("load command " + Twine(LoadCommandIndex) +
1054 " count not ARM_THREAD_STATE64_COUNT for "
1055 "flavor number " + Twine(nflavor) + " which is "
1056 "a ARM_THREAD_STATE64 flavor in " + CmdName +
1057 " command");
1058 if (state + sizeof(MachO::arm_thread_state64_t) > end)
1059 return malformedError("load command " + Twine(LoadCommandIndex) +
1060 " ARM_THREAD_STATE64 extends past end of "
1061 "command in " + CmdName + " command");
1062 state += sizeof(MachO::arm_thread_state64_t);
1063 } else {
1064 return malformedError("load command " + Twine(LoadCommandIndex) +
1065 " unknown flavor (" + Twine(flavor) + ") for "
1066 "flavor number " + Twine(nflavor) + " in " +
1067 CmdName + " command");
1068 }
Kevin Enderby210030b2016-10-19 23:44:34 +00001069 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1070 if (flavor == MachO::PPC_THREAD_STATE) {
1071 if (count != MachO::PPC_THREAD_STATE_COUNT)
1072 return malformedError("load command " + Twine(LoadCommandIndex) +
1073 " count not PPC_THREAD_STATE_COUNT for "
1074 "flavor number " + Twine(nflavor) + " which is "
1075 "a PPC_THREAD_STATE flavor in " + CmdName +
1076 " command");
1077 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1078 return malformedError("load command " + Twine(LoadCommandIndex) +
1079 " PPC_THREAD_STATE extends past end of "
1080 "command in " + CmdName + " command");
1081 state += sizeof(MachO::ppc_thread_state32_t);
1082 } else {
1083 return malformedError("load command " + Twine(LoadCommandIndex) +
1084 " unknown flavor (" + Twine(flavor) + ") for "
1085 "flavor number " + Twine(nflavor) + " in " +
1086 CmdName + " command");
1087 }
1088 } else {
1089 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1090 "command " + Twine(LoadCommandIndex) + " for " +
1091 CmdName + " command can't be checked");
1092 }
1093 nflavor++;
1094 }
1095 return Error::success();
1096}
1097
Lang Hames697e7cd2016-12-04 01:56:10 +00001098static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001099 const MachOObjectFile::LoadCommandInfo
1100 &Load,
1101 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001102 const char **LoadCmd,
1103 std::list<MachOElement> &Elements) {
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001104 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1105 return malformedError("load command " + Twine(LoadCommandIndex) +
1106 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1107 if (*LoadCmd != nullptr)
1108 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1109 MachO::twolevel_hints_command Hints =
1110 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
Lang Hames697e7cd2016-12-04 01:56:10 +00001111 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001112 if (Hints.offset > FileSize)
1113 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1114 Twine(LoadCommandIndex) + " extends past the end of "
1115 "the file");
1116 uint64_t BigSize = Hints.nhints;
1117 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint);
1118 BigSize += Hints.offset;
1119 if (BigSize > FileSize)
1120 return malformedError("offset field plus nhints times sizeof(struct "
1121 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1122 Twine(LoadCommandIndex) + " extends past the end of "
1123 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001124 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1125 sizeof(MachO::twolevel_hint),
1126 "two level hints"))
1127 return Err;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001128 *LoadCmd = Load.Ptr;
1129 return Error::success();
1130}
1131
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001132// Returns true if the libObject code does not support the load command and its
1133// contents. The cmd value it is treated as an unknown load command but with
1134// an error message that says the cmd value is obsolete.
1135static bool isLoadCommandObsolete(uint32_t cmd) {
1136 if (cmd == MachO::LC_SYMSEG ||
1137 cmd == MachO::LC_LOADFVMLIB ||
1138 cmd == MachO::LC_IDFVMLIB ||
1139 cmd == MachO::LC_IDENT ||
1140 cmd == MachO::LC_FVMFILE ||
1141 cmd == MachO::LC_PREPAGE ||
1142 cmd == MachO::LC_PREBOUND_DYLIB ||
1143 cmd == MachO::LC_TWOLEVEL_HINTS ||
1144 cmd == MachO::LC_PREBIND_CKSUM)
1145 return true;
1146 return false;
1147}
1148
Lang Hames82627642016-03-25 21:59:14 +00001149Expected<std::unique_ptr<MachOObjectFile>>
1150MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001151 bool Is64Bits, uint32_t UniversalCputype,
1152 uint32_t UniversalIndex) {
Mehdi Amini41af4302016-11-11 04:28:40 +00001153 Error Err = Error::success();
Lang Hames82627642016-03-25 21:59:14 +00001154 std::unique_ptr<MachOObjectFile> Obj(
1155 new MachOObjectFile(std::move(Object), IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001156 Is64Bits, Err, UniversalCputype,
1157 UniversalIndex));
Lang Hames82627642016-03-25 21:59:14 +00001158 if (Err)
1159 return std::move(Err);
1160 return std::move(Obj);
1161}
1162
Rafael Espindola48af1c22014-08-19 18:44:46 +00001163MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001164 bool Is64bits, Error &Err,
1165 uint32_t UniversalCputype,
1166 uint32_t UniversalIndex)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00001167 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
Lang Hames5e51a2e2016-07-22 16:11:25 +00001168 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001169 uint64_t SizeOfHeaders;
Kevin Enderby79d6c632016-10-24 21:15:11 +00001170 uint32_t cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001171 if (is64Bit()) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001172 parseHeader(*this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001173 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001174 cputype = Header64.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001175 } else {
Lang Hames697e7cd2016-12-04 01:56:10 +00001176 parseHeader(*this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001177 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001178 cputype = Header.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001179 }
Lang Hames9e964f32016-03-25 17:25:34 +00001180 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +00001181 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +00001182 SizeOfHeaders += getHeader().sizeofcmds;
1183 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001184 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +00001185 return;
1186 }
Kevin Enderby79d6c632016-10-24 21:15:11 +00001187 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1188 Err = malformedError("universal header architecture: " +
1189 Twine(UniversalIndex) + "'s cputype does not match "
1190 "object file's mach header");
1191 return;
1192 }
Kevin Enderbyd5039402016-10-31 20:29:48 +00001193 std::list<MachOElement> Elements;
1194 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001195
1196 uint32_t LoadCommandCount = getHeader().ncmds;
Lang Hames9e964f32016-03-25 17:25:34 +00001197 LoadCommandInfo Load;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001198 if (LoadCommandCount != 0) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001199 if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001200 Load = *LoadOrErr;
1201 else {
1202 Err = LoadOrErr.takeError();
1203 return;
1204 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001205 }
Lang Hames9e964f32016-03-25 17:25:34 +00001206
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001207 const char *DyldIdLoadCmd = nullptr;
Kevin Enderby90986e62016-09-26 21:11:03 +00001208 const char *FuncStartsLoadCmd = nullptr;
1209 const char *SplitInfoLoadCmd = nullptr;
1210 const char *CodeSignDrsLoadCmd = nullptr;
Kevin Enderby89baf992016-10-18 20:24:12 +00001211 const char *CodeSignLoadCmd = nullptr;
Kevin Enderby32359db2016-09-28 21:20:45 +00001212 const char *VersLoadCmd = nullptr;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001213 const char *SourceLoadCmd = nullptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001214 const char *EntryPointLoadCmd = nullptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001215 const char *EncryptLoadCmd = nullptr;
Kevin Enderby6f695822016-10-18 17:54:17 +00001216 const char *RoutinesLoadCmd = nullptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001217 const char *UnixThreadLoadCmd = nullptr;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001218 const char *TwoLevelHintsLoadCmd = nullptr;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001219 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +00001220 if (is64Bit()) {
1221 if (Load.C.cmdsize % 8 != 0) {
1222 // We have a hack here to allow 64-bit Mach-O core files to have
1223 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1224 // allowed since the macOS kernel produces them.
1225 if (getHeader().filetype != MachO::MH_CORE ||
1226 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1227 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1228 "multiple of 8");
1229 return;
1230 }
1231 }
1232 } else {
1233 if (Load.C.cmdsize % 4 != 0) {
1234 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1235 "multiple of 4");
1236 return;
1237 }
1238 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001239 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001240 if (Load.C.cmd == MachO::LC_SYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001241 if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001242 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001243 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001244 if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001245 Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001246 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001247 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001248 if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001249 "LC_DATA_IN_CODE", Elements,
1250 "data in code info")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001251 return;
Kevin Enderby9a509442015-01-27 21:28:24 +00001252 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001253 if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001254 "LC_LINKER_OPTIMIZATION_HINT",
1255 Elements, "linker optimization "
1256 "hints")))
Kevin Enderby9a509442015-01-27 21:28:24 +00001257 return;
Kevin Enderby90986e62016-09-26 21:11:03 +00001258 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001259 if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001260 "LC_FUNCTION_STARTS", Elements,
1261 "function starts data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001262 return;
1263 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001264 if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001265 "LC_SEGMENT_SPLIT_INFO", Elements,
1266 "split info data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001267 return;
1268 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001269 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001270 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1271 "code signing RDs data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001272 return;
Kevin Enderby89baf992016-10-18 20:24:12 +00001273 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001274 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001275 "LC_CODE_SIGNATURE", Elements,
1276 "code signature data")))
Kevin Enderby89baf992016-10-18 20:24:12 +00001277 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001278 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001279 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001280 "LC_DYLD_INFO", Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001281 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001282 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001283 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001284 "LC_DYLD_INFO_ONLY", Elements)))
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001285 return;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001286 } else if (Load.C.cmd == MachO::LC_UUID) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001287 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1288 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1289 "cmdsize");
1290 return;
1291 }
David Majnemer73cc6ff2014-11-13 19:48:56 +00001292 if (UuidLoadCmd) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001293 Err = malformedError("more than one LC_UUID command");
David Majnemer73cc6ff2014-11-13 19:48:56 +00001294 return;
1295 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001296 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001297 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001298 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1299 MachO::section_64>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001300 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001301 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001302 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001303 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001304 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1305 MachO::section>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001306 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001307 "LC_SEGMENT", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001308 return;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001309 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001310 if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001311 return;
1312 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001313 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001314 return;
1315 Libraries.push_back(Load.Ptr);
1316 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001317 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001318 return;
1319 Libraries.push_back(Load.Ptr);
1320 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001321 if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001322 return;
1323 Libraries.push_back(Load.Ptr);
1324 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001325 if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001326 return;
1327 Libraries.push_back(Load.Ptr);
1328 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001329 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001330 return;
Kevin Enderby980b2582014-06-05 21:21:57 +00001331 Libraries.push_back(Load.Ptr);
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001332 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001333 if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001334 return;
1335 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001336 if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001337 return;
1338 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001339 if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001340 return;
Kevin Enderby32359db2016-09-28 21:20:45 +00001341 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001342 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001343 "LC_VERSION_MIN_MACOSX")))
1344 return;
1345 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001346 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001347 "LC_VERSION_MIN_IPHONEOS")))
1348 return;
1349 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001350 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001351 "LC_VERSION_MIN_TVOS")))
1352 return;
1353 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001354 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001355 "LC_VERSION_MIN_WATCHOS")))
1356 return;
Kevin Enderbya4579c42017-01-19 17:36:31 +00001357 } else if (Load.C.cmd == MachO::LC_NOTE) {
1358 if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1359 return;
Steven Wu5b54a422017-01-23 20:07:55 +00001360 } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1361 if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1362 return;
Kevin Enderby76966bf2016-09-28 23:16:01 +00001363 } else if (Load.C.cmd == MachO::LC_RPATH) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001364 if ((Err = checkRpathCommand(*this, Load, I)))
Kevin Enderby76966bf2016-09-28 23:16:01 +00001365 return;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001366 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1367 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1368 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1369 " has incorrect cmdsize");
1370 return;
1371 }
1372 if (SourceLoadCmd) {
1373 Err = malformedError("more than one LC_SOURCE_VERSION command");
1374 return;
1375 }
1376 SourceLoadCmd = Load.Ptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001377 } else if (Load.C.cmd == MachO::LC_MAIN) {
1378 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1379 Err = malformedError("LC_MAIN command " + Twine(I) +
1380 " has incorrect cmdsize");
1381 return;
1382 }
1383 if (EntryPointLoadCmd) {
1384 Err = malformedError("more than one LC_MAIN command");
1385 return;
1386 }
1387 EntryPointLoadCmd = Load.Ptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001388 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1389 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1390 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1391 " has incorrect cmdsize");
1392 return;
1393 }
1394 MachO::encryption_info_command E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001395 getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1396 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001397 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1398 return;
1399 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1400 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1401 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1402 " has incorrect cmdsize");
1403 return;
1404 }
1405 MachO::encryption_info_command_64 E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001406 getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1407 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001408 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1409 return;
Kevin Enderby68fffa82016-10-11 21:04:39 +00001410 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001411 if ((Err = checkLinkerOptCommand(*this, Load, I)))
Kevin Enderby68fffa82016-10-11 21:04:39 +00001412 return;
Kevin Enderby2490de02016-10-17 22:09:25 +00001413 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1414 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1415 Err = malformedError("load command " + Twine(I) +
1416 " LC_SUB_FRAMEWORK cmdsize too small");
1417 return;
1418 }
1419 MachO::sub_framework_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001420 getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1421 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
Kevin Enderby2490de02016-10-17 22:09:25 +00001422 sizeof(MachO::sub_framework_command),
1423 "sub_framework_command", S.umbrella,
1424 "umbrella")))
1425 return;
1426 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1427 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1428 Err = malformedError("load command " + Twine(I) +
1429 " LC_SUB_UMBRELLA cmdsize too small");
1430 return;
1431 }
1432 MachO::sub_umbrella_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001433 getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1434 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
Kevin Enderby2490de02016-10-17 22:09:25 +00001435 sizeof(MachO::sub_umbrella_command),
1436 "sub_umbrella_command", S.sub_umbrella,
1437 "sub_umbrella")))
1438 return;
1439 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1440 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1441 Err = malformedError("load command " + Twine(I) +
1442 " LC_SUB_LIBRARY cmdsize too small");
1443 return;
1444 }
1445 MachO::sub_library_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001446 getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1447 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
Kevin Enderby2490de02016-10-17 22:09:25 +00001448 sizeof(MachO::sub_library_command),
1449 "sub_library_command", S.sub_library,
1450 "sub_library")))
1451 return;
1452 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1453 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1454 Err = malformedError("load command " + Twine(I) +
1455 " LC_SUB_CLIENT cmdsize too small");
1456 return;
1457 }
1458 MachO::sub_client_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001459 getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1460 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
Kevin Enderby2490de02016-10-17 22:09:25 +00001461 sizeof(MachO::sub_client_command),
1462 "sub_client_command", S.client, "client")))
1463 return;
Kevin Enderby6f695822016-10-18 17:54:17 +00001464 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1465 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1466 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1467 " has incorrect cmdsize");
1468 return;
1469 }
1470 if (RoutinesLoadCmd) {
1471 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1472 "command");
1473 return;
1474 }
1475 RoutinesLoadCmd = Load.Ptr;
1476 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1477 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1478 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1479 " has incorrect cmdsize");
1480 return;
1481 }
1482 if (RoutinesLoadCmd) {
1483 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1484 "command");
1485 return;
1486 }
1487 RoutinesLoadCmd = Load.Ptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001488 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001489 if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001490 return;
1491 if (UnixThreadLoadCmd) {
1492 Err = malformedError("more than one LC_UNIXTHREAD command");
1493 return;
1494 }
1495 UnixThreadLoadCmd = Load.Ptr;
1496 } else if (Load.C.cmd == MachO::LC_THREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001497 if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001498 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001499 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001500 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001501 if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001502 &TwoLevelHintsLoadCmd, Elements)))
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001503 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001504 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1505 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1506 Twine(Load.C.cmd) + " is obsolete and not "
1507 "supported");
1508 return;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001509 }
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001510 // TODO: generate a error for unknown load commands by default. But still
1511 // need work out an approach to allow or not allow unknown values like this
1512 // as an option for some uses like lldb.
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001513 if (I < LoadCommandCount - 1) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001514 if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +00001515 Load = *LoadOrErr;
1516 else {
1517 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001518 return;
1519 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001520 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001521 }
Kevin Enderby1829c682016-01-22 22:49:55 +00001522 if (!SymtabLoadCmd) {
1523 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001524 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +00001525 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +00001526 return;
1527 }
1528 } else if (DysymtabLoadCmd) {
1529 MachO::symtab_command Symtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001530 getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001531 MachO::dysymtab_command Dysymtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001532 getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001533 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001534 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001535 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001536 return;
1537 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001538 uint64_t BigSize = Dysymtab.ilocalsym;
1539 BigSize += Dysymtab.nlocalsym;
1540 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001541 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001542 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001543 return;
1544 }
1545 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001546 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001547 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001548 return;
1549 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001550 BigSize = Dysymtab.iextdefsym;
1551 BigSize += Dysymtab.nextdefsym;
1552 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001553 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +00001554 "load command extends past the end of the symbol "
1555 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001556 return;
1557 }
1558 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001559 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001560 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001561 return;
1562 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001563 BigSize = Dysymtab.iundefsym;
1564 BigSize += Dysymtab.nundefsym;
1565 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001566 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001567 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001568 return;
1569 }
1570 }
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001571 if ((getHeader().filetype == MachO::MH_DYLIB ||
1572 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1573 DyldIdLoadCmd == nullptr) {
1574 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1575 "filetype");
1576 return;
1577 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001578 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +00001579
1580 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001581}
1582
Kevin Enderby22fc0072016-11-14 20:57:04 +00001583Error MachOObjectFile::checkSymbolTable() const {
1584 uint32_t Flags = 0;
1585 if (is64Bit()) {
1586 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1587 Flags = H_64.flags;
1588 } else {
1589 MachO::mach_header H = MachOObjectFile::getHeader();
1590 Flags = H.flags;
1591 }
1592 uint8_t NType = 0;
1593 uint8_t NSect = 0;
1594 uint16_t NDesc = 0;
1595 uint32_t NStrx = 0;
1596 uint64_t NValue = 0;
1597 uint32_t SymbolIndex = 0;
1598 MachO::symtab_command S = getSymtabLoadCommand();
1599 for (const SymbolRef &Symbol : symbols()) {
1600 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1601 if (is64Bit()) {
1602 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1603 NType = STE_64.n_type;
1604 NSect = STE_64.n_sect;
1605 NDesc = STE_64.n_desc;
1606 NStrx = STE_64.n_strx;
1607 NValue = STE_64.n_value;
1608 } else {
1609 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1610 NType = STE.n_type;
1611 NType = STE.n_type;
1612 NSect = STE.n_sect;
1613 NDesc = STE.n_desc;
1614 NStrx = STE.n_strx;
1615 NValue = STE.n_value;
1616 }
1617 if ((NType & MachO::N_STAB) == 0 &&
1618 (NType & MachO::N_TYPE) == MachO::N_SECT) {
1619 if (NSect == 0 || NSect > Sections.size())
1620 return malformedError("bad section index: " + Twine((int)NSect) +
1621 " for symbol at index " + Twine(SymbolIndex));
1622 }
1623 if ((NType & MachO::N_STAB) == 0 &&
1624 (NType & MachO::N_TYPE) == MachO::N_INDR) {
1625 if (NValue >= S.strsize)
1626 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1627 "the end of string table, for N_INDR symbol at "
1628 "index " + Twine(SymbolIndex));
1629 }
1630 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1631 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1632 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1633 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1634 if (LibraryOrdinal != 0 &&
1635 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1636 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1637 LibraryOrdinal - 1 >= Libraries.size() ) {
1638 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1639 " for symbol at index " + Twine(SymbolIndex));
1640 }
1641 }
1642 if (NStrx >= S.strsize)
1643 return malformedError("bad string table index: " + Twine((int)NStrx) +
1644 " past the end of string table, for symbol at "
1645 "index " + Twine(SymbolIndex));
1646 SymbolIndex++;
1647 }
1648 return Error::success();
1649}
1650
Rafael Espindola5e812af2014-01-30 02:49:50 +00001651void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001652 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001653 sizeof(MachO::nlist_64) :
1654 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +00001655 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001656}
1657
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001658Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001659 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001660 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001661 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001662 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001663 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +00001664 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001665 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00001666 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001667}
1668
Rafael Espindola0e77a942014-12-10 20:46:55 +00001669unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1670 DataRefImpl DRI = Sec.getRawDataRefImpl();
Lang Hames697e7cd2016-12-04 01:56:10 +00001671 uint32_t Flags = getSectionFlags(*this, DRI);
Rafael Espindola0e77a942014-12-10 20:46:55 +00001672 return Flags & MachO::SECTION_TYPE;
1673}
1674
Rafael Espindola59128922015-06-24 18:14:41 +00001675uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1676 if (is64Bit()) {
1677 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1678 return Entry.n_value;
1679 }
1680 MachO::nlist Entry = getSymbolTableEntry(Sym);
1681 return Entry.n_value;
1682}
1683
Kevin Enderby980b2582014-06-05 21:21:57 +00001684// getIndirectName() returns the name of the alias'ed symbol who's string table
1685// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +00001686std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1687 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001688 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001689 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Rafael Espindola59128922015-06-24 18:14:41 +00001690 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1691 return object_error::parse_failed;
1692 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +00001693 if (NValue >= StringTable.size())
1694 return object_error::parse_failed;
1695 const char *Start = &StringTable.data()[NValue];
1696 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +00001697 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001698}
1699
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +00001700uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +00001701 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +00001702}
1703
Kevin Enderby931cb652016-06-24 18:24:42 +00001704Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +00001705 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001706}
1707
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001708uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +00001709 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001710 if (flags & SymbolRef::SF_Common) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001711 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001712 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001713 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001714 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001715}
1716
Rafael Espindolad7a32ea2015-06-24 10:20:30 +00001717uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001718 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001719}
1720
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001721Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001722MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001723 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001724 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001725
Rafael Espindola56f976f2013-04-18 18:08:55 +00001726 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001727 if (n_type & MachO::N_STAB)
1728 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001729
Charles Davis74ec8b02013-08-27 05:00:13 +00001730 switch (n_type & MachO::N_TYPE) {
1731 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001732 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +00001733 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001734 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001735 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001736 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001737 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +00001738 if (Sec->isData() || Sec->isBSS())
1739 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001740 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001741 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001742 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001743}
1744
Rafael Espindola20122a42014-01-31 20:57:12 +00001745uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001746 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001747
Charles Davis8bdfafd2013-09-01 04:28:48 +00001748 uint8_t MachOType = Entry.n_type;
1749 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001750
Rafael Espindola20122a42014-01-31 20:57:12 +00001751 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001752
Tim Northovereaef0742014-05-30 13:22:59 +00001753 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1754 Result |= SymbolRef::SF_Indirect;
1755
Rafael Espindolaa1356322013-11-02 05:03:24 +00001756 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001757 Result |= SymbolRef::SF_FormatSpecific;
1758
Charles Davis74ec8b02013-08-27 05:00:13 +00001759 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001760 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +00001761 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001762 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001763 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +00001764 else
1765 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001766 }
Lang Hames7e0692b2015-01-15 22:33:30 +00001767
1768 if (!(MachOType & MachO::N_PEXT))
1769 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001770 }
1771
Charles Davis74ec8b02013-08-27 05:00:13 +00001772 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +00001773 Result |= SymbolRef::SF_Weak;
1774
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001775 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1776 Result |= SymbolRef::SF_Thumb;
1777
Charles Davis74ec8b02013-08-27 05:00:13 +00001778 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001779 Result |= SymbolRef::SF_Absolute;
1780
Rafael Espindola20122a42014-01-31 20:57:12 +00001781 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001782}
1783
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001784Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +00001785MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001786 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001787 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001788
Rafael Espindola8bab8892015-08-07 23:27:14 +00001789 if (index == 0)
1790 return section_end();
1791 DataRefImpl DRI;
1792 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001793 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001794 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +00001795 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001796 }
Rafael Espindola8bab8892015-08-07 23:27:14 +00001797 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001798}
1799
Rafael Espindola6bf32212015-06-24 19:57:32 +00001800unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1801 MachO::nlist_base Entry =
Lang Hames697e7cd2016-12-04 01:56:10 +00001802 getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
Rafael Espindola6bf32212015-06-24 19:57:32 +00001803 return Entry.n_sect - 1;
1804}
1805
Rafael Espindola5e812af2014-01-30 02:49:50 +00001806void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001807 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001808}
1809
Rafael Espindola3acea392014-06-12 21:46:39 +00001810std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1811 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001812 ArrayRef<char> Raw = getSectionRawName(Sec);
1813 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +00001814 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001815}
1816
Rafael Espindola80291272014-10-08 15:28:58 +00001817uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1818 if (is64Bit())
1819 return getSection64(Sec).addr;
1820 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001821}
1822
George Rimara25d3292017-05-27 18:10:23 +00001823uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1824 return Sec.d.a;
1825}
1826
Rafael Espindola80291272014-10-08 15:28:58 +00001827uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +00001828 // In the case if a malformed Mach-O file where the section offset is past
1829 // the end of the file or some part of the section size is past the end of
1830 // the file return a size of zero or a size that covers the rest of the file
1831 // but does not extend past the end of the file.
1832 uint32_t SectOffset, SectType;
1833 uint64_t SectSize;
1834
1835 if (is64Bit()) {
1836 MachO::section_64 Sect = getSection64(Sec);
1837 SectOffset = Sect.offset;
1838 SectSize = Sect.size;
1839 SectType = Sect.flags & MachO::SECTION_TYPE;
1840 } else {
1841 MachO::section Sect = getSection(Sec);
1842 SectOffset = Sect.offset;
1843 SectSize = Sect.size;
1844 SectType = Sect.flags & MachO::SECTION_TYPE;
1845 }
1846 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1847 return SectSize;
1848 uint64_t FileSize = getData().size();
1849 if (SectOffset > FileSize)
1850 return 0;
1851 if (FileSize - SectOffset < SectSize)
1852 return FileSize - SectOffset;
1853 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001854}
1855
Rafael Espindola3acea392014-06-12 21:46:39 +00001856std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1857 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001858 uint32_t Offset;
1859 uint64_t Size;
1860
1861 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001862 MachO::section_64 Sect = getSection64(Sec);
1863 Offset = Sect.offset;
1864 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001865 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001866 MachO::section Sect = getSection(Sec);
1867 Offset = Sect.offset;
1868 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001869 }
1870
1871 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +00001872 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001873}
1874
Rafael Espindola80291272014-10-08 15:28:58 +00001875uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001876 uint32_t Align;
1877 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001878 MachO::section_64 Sect = getSection64(Sec);
1879 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001880 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001881 MachO::section Sect = getSection(Sec);
1882 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001883 }
1884
Rafael Espindola80291272014-10-08 15:28:58 +00001885 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001886}
1887
George Rimar401e4e52016-05-24 12:48:46 +00001888bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1889 return false;
1890}
1891
Rafael Espindola80291272014-10-08 15:28:58 +00001892bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001893 uint32_t Flags = getSectionFlags(*this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +00001894 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001895}
1896
Rafael Espindola80291272014-10-08 15:28:58 +00001897bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001898 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001899 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001900 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1901 !(SectionType == MachO::S_ZEROFILL ||
1902 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +00001903}
1904
Rafael Espindola80291272014-10-08 15:28:58 +00001905bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001906 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001907 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001908 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1909 (SectionType == MachO::S_ZEROFILL ||
1910 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +00001911}
1912
Rafael Espindola6bf32212015-06-24 19:57:32 +00001913unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1914 return Sec.getRawDataRefImpl().d.a;
1915}
1916
Rafael Espindola80291272014-10-08 15:28:58 +00001917bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +00001918 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +00001919 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +00001920}
1921
Steven Wuf2fe0142016-02-29 19:40:10 +00001922bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1923 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1924 StringRef SectName;
1925 if (!getSectionName(Sec, SectName))
1926 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1927 return false;
1928}
1929
Rui Ueyamabc654b12013-09-27 21:47:05 +00001930relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001931 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001932 Ret.d.a = Sec.d.a;
1933 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +00001934 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +00001935}
Rafael Espindolac0406e12013-04-08 20:45:01 +00001936
Rafael Espindola56f976f2013-04-18 18:08:55 +00001937relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +00001938MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001939 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001940 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001941 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001942 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001943 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001944 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001945 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001946 }
Eric Christopher7b015c72011-04-22 03:19:48 +00001947
Rafael Espindola56f976f2013-04-18 18:08:55 +00001948 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001949 Ret.d.a = Sec.d.a;
1950 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001951 return relocation_iterator(RelocationRef(Ret, this));
1952}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001953
Kevin Enderbyabf10f22017-06-22 17:41:22 +00001954relocation_iterator MachOObjectFile::extrel_begin() const {
1955 DataRefImpl Ret;
1956 Ret.d.a = 0; // Would normally be a section index.
1957 Ret.d.b = 0; // Index into the external relocations
1958 return relocation_iterator(RelocationRef(Ret, this));
1959}
1960
1961relocation_iterator MachOObjectFile::extrel_end() const {
1962 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
1963 DataRefImpl Ret;
1964 Ret.d.a = 0; // Would normally be a section index.
1965 Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
1966 return relocation_iterator(RelocationRef(Ret, this));
1967}
1968
Rafael Espindola5e812af2014-01-30 02:49:50 +00001969void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001970 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001971}
Owen Anderson171f4852011-10-24 23:20:07 +00001972
Rafael Espindola96d071c2015-06-29 23:29:12 +00001973uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Kevin Enderbyabf10f22017-06-22 17:41:22 +00001974 assert((getHeader().filetype == MachO::MH_OBJECT ||
1975 getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
1976 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001977 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +00001978 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +00001979}
1980
Rafael Espindola806f0062013-06-05 01:33:53 +00001981symbol_iterator
1982MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001983 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00001984 if (isRelocationScattered(RE))
1985 return symbol_end();
1986
Rafael Espindola56f976f2013-04-18 18:08:55 +00001987 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
1988 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00001989 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00001990 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00001991
Charles Davis8bdfafd2013-09-01 04:28:48 +00001992 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001993 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001994 sizeof(MachO::nlist_64) :
1995 sizeof(MachO::nlist);
1996 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001997 DataRefImpl Sym;
Lang Hames697e7cd2016-12-04 01:56:10 +00001998 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00001999 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002000}
2001
Keno Fischerc780e8e2015-05-21 21:24:32 +00002002section_iterator
2003MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2004 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2005}
2006
Rafael Espindola99c041b2015-06-30 01:53:01 +00002007uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002008 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00002009 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002010}
2011
Rafael Espindola41bb4322015-06-30 04:08:37 +00002012void MachOObjectFile::getRelocationTypeName(
2013 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002014 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00002015 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002016
2017 unsigned Arch = this->getArch();
2018
2019 switch (Arch) {
2020 case Triple::x86: {
2021 static const char *const Table[] = {
2022 "GENERIC_RELOC_VANILLA",
2023 "GENERIC_RELOC_PAIR",
2024 "GENERIC_RELOC_SECTDIFF",
2025 "GENERIC_RELOC_PB_LA_PTR",
2026 "GENERIC_RELOC_LOCAL_SECTDIFF",
2027 "GENERIC_RELOC_TLV" };
2028
Eric Christopher13250cb2013-12-06 02:33:38 +00002029 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002030 res = "Unknown";
2031 else
2032 res = Table[RType];
2033 break;
2034 }
2035 case Triple::x86_64: {
2036 static const char *const Table[] = {
2037 "X86_64_RELOC_UNSIGNED",
2038 "X86_64_RELOC_SIGNED",
2039 "X86_64_RELOC_BRANCH",
2040 "X86_64_RELOC_GOT_LOAD",
2041 "X86_64_RELOC_GOT",
2042 "X86_64_RELOC_SUBTRACTOR",
2043 "X86_64_RELOC_SIGNED_1",
2044 "X86_64_RELOC_SIGNED_2",
2045 "X86_64_RELOC_SIGNED_4",
2046 "X86_64_RELOC_TLV" };
2047
2048 if (RType > 9)
2049 res = "Unknown";
2050 else
2051 res = Table[RType];
2052 break;
2053 }
2054 case Triple::arm: {
2055 static const char *const Table[] = {
2056 "ARM_RELOC_VANILLA",
2057 "ARM_RELOC_PAIR",
2058 "ARM_RELOC_SECTDIFF",
2059 "ARM_RELOC_LOCAL_SECTDIFF",
2060 "ARM_RELOC_PB_LA_PTR",
2061 "ARM_RELOC_BR24",
2062 "ARM_THUMB_RELOC_BR22",
2063 "ARM_THUMB_32BIT_BRANCH",
2064 "ARM_RELOC_HALF",
2065 "ARM_RELOC_HALF_SECTDIFF" };
2066
2067 if (RType > 9)
2068 res = "Unknown";
2069 else
2070 res = Table[RType];
2071 break;
2072 }
Tim Northover00ed9962014-03-29 10:18:08 +00002073 case Triple::aarch64: {
2074 static const char *const Table[] = {
2075 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2076 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2077 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2078 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2079 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2080 "ARM64_RELOC_ADDEND"
2081 };
2082
2083 if (RType >= array_lengthof(Table))
2084 res = "Unknown";
2085 else
2086 res = Table[RType];
2087 break;
2088 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00002089 case Triple::ppc: {
2090 static const char *const Table[] = {
2091 "PPC_RELOC_VANILLA",
2092 "PPC_RELOC_PAIR",
2093 "PPC_RELOC_BR14",
2094 "PPC_RELOC_BR24",
2095 "PPC_RELOC_HI16",
2096 "PPC_RELOC_LO16",
2097 "PPC_RELOC_HA16",
2098 "PPC_RELOC_LO14",
2099 "PPC_RELOC_SECTDIFF",
2100 "PPC_RELOC_PB_LA_PTR",
2101 "PPC_RELOC_HI16_SECTDIFF",
2102 "PPC_RELOC_LO16_SECTDIFF",
2103 "PPC_RELOC_HA16_SECTDIFF",
2104 "PPC_RELOC_JBSR",
2105 "PPC_RELOC_LO14_SECTDIFF",
2106 "PPC_RELOC_LOCAL_SECTDIFF" };
2107
Eric Christopher13250cb2013-12-06 02:33:38 +00002108 if (RType > 15)
2109 res = "Unknown";
2110 else
2111 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00002112 break;
2113 }
2114 case Triple::UnknownArch:
2115 res = "Unknown";
2116 break;
2117 }
2118 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00002119}
2120
Keno Fischer281b6942015-05-30 19:44:53 +00002121uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2122 MachO::any_relocation_info RE = getRelocation(Rel);
2123 return getAnyRelocationLength(RE);
2124}
2125
Kevin Enderby980b2582014-06-05 21:21:57 +00002126//
2127// guessLibraryShortName() is passed a name of a dynamic library and returns a
2128// guess on what the short name is. Then name is returned as a substring of the
2129// StringRef Name passed in. The name of the dynamic library is recognized as
2130// a framework if it has one of the two following forms:
2131// Foo.framework/Versions/A/Foo
2132// Foo.framework/Foo
2133// Where A and Foo can be any string. And may contain a trailing suffix
2134// starting with an underbar. If the Name is recognized as a framework then
2135// isFramework is set to true else it is set to false. If the Name has a
2136// suffix then Suffix is set to the substring in Name that contains the suffix
2137// else it is set to a NULL StringRef.
2138//
2139// The Name of the dynamic library is recognized as a library name if it has
2140// one of the two following forms:
2141// libFoo.A.dylib
2142// libFoo.dylib
2143// The library may have a suffix trailing the name Foo of the form:
2144// libFoo_profile.A.dylib
2145// libFoo_profile.dylib
2146//
2147// The Name of the dynamic library is also recognized as a library name if it
2148// has the following form:
2149// Foo.qtx
2150//
2151// If the Name of the dynamic library is none of the forms above then a NULL
2152// StringRef is returned.
2153//
2154StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2155 bool &isFramework,
2156 StringRef &Suffix) {
2157 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2158 size_t a, b, c, d, Idx;
2159
2160 isFramework = false;
2161 Suffix = StringRef();
2162
2163 // Pull off the last component and make Foo point to it
2164 a = Name.rfind('/');
2165 if (a == Name.npos || a == 0)
2166 goto guess_library;
2167 Foo = Name.slice(a+1, Name.npos);
2168
2169 // Look for a suffix starting with a '_'
2170 Idx = Foo.rfind('_');
2171 if (Idx != Foo.npos && Foo.size() >= 2) {
2172 Suffix = Foo.slice(Idx, Foo.npos);
2173 Foo = Foo.slice(0, Idx);
2174 }
2175
2176 // First look for the form Foo.framework/Foo
2177 b = Name.rfind('/', a);
2178 if (b == Name.npos)
2179 Idx = 0;
2180 else
2181 Idx = b+1;
2182 F = Name.slice(Idx, Idx + Foo.size());
2183 DotFramework = Name.slice(Idx + Foo.size(),
2184 Idx + Foo.size() + sizeof(".framework/")-1);
2185 if (F == Foo && DotFramework == ".framework/") {
2186 isFramework = true;
2187 return Foo;
2188 }
2189
2190 // Next look for the form Foo.framework/Versions/A/Foo
2191 if (b == Name.npos)
2192 goto guess_library;
2193 c = Name.rfind('/', b);
2194 if (c == Name.npos || c == 0)
2195 goto guess_library;
2196 V = Name.slice(c+1, Name.npos);
2197 if (!V.startswith("Versions/"))
2198 goto guess_library;
2199 d = Name.rfind('/', c);
2200 if (d == Name.npos)
2201 Idx = 0;
2202 else
2203 Idx = d+1;
2204 F = Name.slice(Idx, Idx + Foo.size());
2205 DotFramework = Name.slice(Idx + Foo.size(),
2206 Idx + Foo.size() + sizeof(".framework/")-1);
2207 if (F == Foo && DotFramework == ".framework/") {
2208 isFramework = true;
2209 return Foo;
2210 }
2211
2212guess_library:
2213 // pull off the suffix after the "." and make a point to it
2214 a = Name.rfind('.');
2215 if (a == Name.npos || a == 0)
2216 return StringRef();
2217 Dylib = Name.slice(a, Name.npos);
2218 if (Dylib != ".dylib")
2219 goto guess_qtx;
2220
2221 // First pull off the version letter for the form Foo.A.dylib if any.
2222 if (a >= 3) {
2223 Dot = Name.slice(a-2, a-1);
2224 if (Dot == ".")
2225 a = a - 2;
2226 }
2227
2228 b = Name.rfind('/', a);
2229 if (b == Name.npos)
2230 b = 0;
2231 else
2232 b = b+1;
2233 // ignore any suffix after an underbar like Foo_profile.A.dylib
2234 Idx = Name.find('_', b);
2235 if (Idx != Name.npos && Idx != b) {
2236 Lib = Name.slice(b, Idx);
2237 Suffix = Name.slice(Idx, a);
2238 }
2239 else
2240 Lib = Name.slice(b, a);
2241 // There are incorrect library names of the form:
2242 // libATS.A_profile.dylib so check for these.
2243 if (Lib.size() >= 3) {
2244 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2245 if (Dot == ".")
2246 Lib = Lib.slice(0, Lib.size()-2);
2247 }
2248 return Lib;
2249
2250guess_qtx:
2251 Qtx = Name.slice(a, Name.npos);
2252 if (Qtx != ".qtx")
2253 return StringRef();
2254 b = Name.rfind('/', a);
2255 if (b == Name.npos)
2256 Lib = Name.slice(0, a);
2257 else
2258 Lib = Name.slice(b+1, a);
2259 // There are library names of the form: QT.A.qtx so check for these.
2260 if (Lib.size() >= 3) {
2261 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2262 if (Dot == ".")
2263 Lib = Lib.slice(0, Lib.size()-2);
2264 }
2265 return Lib;
2266}
2267
2268// getLibraryShortNameByIndex() is used to get the short name of the library
2269// for an undefined symbol in a linked Mach-O binary that was linked with the
2270// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2271// It is passed the index (0 - based) of the library as translated from
2272// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00002273std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00002274 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00002275 if (Index >= Libraries.size())
2276 return object_error::parse_failed;
2277
Kevin Enderby980b2582014-06-05 21:21:57 +00002278 // If the cache of LibrariesShortNames is not built up do that first for
2279 // all the Libraries.
2280 if (LibrariesShortNames.size() == 0) {
2281 for (unsigned i = 0; i < Libraries.size(); i++) {
2282 MachO::dylib_command D =
Lang Hames697e7cd2016-12-04 01:56:10 +00002283 getStruct<MachO::dylib_command>(*this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00002284 if (D.dylib.name >= D.cmdsize)
2285 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00002286 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00002287 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00002288 if (D.dylib.name+Name.size() >= D.cmdsize)
2289 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00002290 StringRef Suffix;
2291 bool isFramework;
2292 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00002293 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00002294 LibrariesShortNames.push_back(Name);
2295 else
2296 LibrariesShortNames.push_back(shortName);
2297 }
2298 }
2299
2300 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00002301 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00002302}
2303
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00002304uint32_t MachOObjectFile::getLibraryCount() const {
2305 return Libraries.size();
2306}
2307
Rafael Espindola76ad2322015-07-06 14:55:37 +00002308section_iterator
2309MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2310 DataRefImpl Sec;
2311 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2312 return section_iterator(SectionRef(Sec, this));
2313}
2314
Peter Collingbourne435890a2016-11-22 03:38:40 +00002315basic_symbol_iterator MachOObjectFile::symbol_begin() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00002316 DataRefImpl DRI;
2317 MachO::symtab_command Symtab = getSymtabLoadCommand();
2318 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2319 return basic_symbol_iterator(SymbolRef(DRI, this));
2320
Lang Hames36072da2014-05-12 21:39:59 +00002321 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002322}
2323
Peter Collingbourne435890a2016-11-22 03:38:40 +00002324basic_symbol_iterator MachOObjectFile::symbol_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002325 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00002326 MachO::symtab_command Symtab = getSymtabLoadCommand();
2327 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002328 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00002329
Rafael Espindola75c30362013-04-24 19:47:55 +00002330 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002331 sizeof(MachO::nlist_64) :
2332 sizeof(MachO::nlist);
2333 unsigned Offset = Symtab.symoff +
2334 Symtab.nsyms * SymbolTableEntrySize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002335 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002336 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002337}
2338
Lang Hames36072da2014-05-12 21:39:59 +00002339basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00002340 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00002341 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002342 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00002343 unsigned SymbolTableEntrySize =
2344 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00002345 DataRefImpl DRI;
Lang Hames697e7cd2016-12-04 01:56:10 +00002346 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Lang Hames36072da2014-05-12 21:39:59 +00002347 DRI.p += Index * SymbolTableEntrySize;
2348 return basic_symbol_iterator(SymbolRef(DRI, this));
2349}
2350
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002351uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2352 MachO::symtab_command Symtab = getSymtabLoadCommand();
2353 if (!SymtabLoadCmd)
2354 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2355 unsigned SymbolTableEntrySize =
2356 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2357 DataRefImpl DRIstart;
Lang Hames697e7cd2016-12-04 01:56:10 +00002358 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002359 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2360 return Index;
2361}
2362
Rafael Espindolab5155a52014-02-10 20:24:04 +00002363section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002364 DataRefImpl DRI;
2365 return section_iterator(SectionRef(DRI, this));
2366}
2367
Rafael Espindolab5155a52014-02-10 20:24:04 +00002368section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002369 DataRefImpl DRI;
2370 DRI.d.a = Sections.size();
2371 return section_iterator(SectionRef(DRI, this));
2372}
2373
Rafael Espindola56f976f2013-04-18 18:08:55 +00002374uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00002375 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00002376}
2377
Rafael Espindola56f976f2013-04-18 18:08:55 +00002378StringRef MachOObjectFile::getFileFormatName() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002379 unsigned CPUType = getCPUType(*this);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002380 if (!is64Bit()) {
2381 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002382 case MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002383 return "Mach-O 32-bit i386";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002384 case MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002385 return "Mach-O arm";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002386 case MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002387 return "Mach-O 32-bit ppc";
2388 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002389 return "Mach-O 32-bit unknown";
2390 }
2391 }
2392
Rafael Espindola56f976f2013-04-18 18:08:55 +00002393 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002394 case MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002395 return "Mach-O 64-bit x86-64";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002396 case MachO::CPU_TYPE_ARM64:
Tim Northover00ed9962014-03-29 10:18:08 +00002397 return "Mach-O arm64";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002398 case MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002399 return "Mach-O 64-bit ppc64";
2400 default:
2401 return "Mach-O 64-bit unknown";
2402 }
2403}
2404
Alexey Samsonove6388e62013-06-18 15:03:28 +00002405Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2406 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002407 case MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002408 return Triple::x86;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002409 case MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002410 return Triple::x86_64;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002411 case MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002412 return Triple::arm;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002413 case MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00002414 return Triple::aarch64;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002415 case MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002416 return Triple::ppc;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002417 case MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002418 return Triple::ppc64;
2419 default:
2420 return Triple::UnknownArch;
2421 }
2422}
2423
Tim Northover9e8eb412016-04-22 23:21:13 +00002424Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
Kevin Enderby59343a92016-12-16 22:54:02 +00002425 const char **McpuDefault,
2426 const char **ArchFlag) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002427 if (McpuDefault)
2428 *McpuDefault = nullptr;
Kevin Enderby59343a92016-12-16 22:54:02 +00002429 if (ArchFlag)
2430 *ArchFlag = nullptr;
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002431
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002432 switch (CPUType) {
2433 case MachO::CPU_TYPE_I386:
2434 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2435 case MachO::CPU_SUBTYPE_I386_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002436 if (ArchFlag)
2437 *ArchFlag = "i386";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002438 return Triple("i386-apple-darwin");
2439 default:
2440 return Triple();
2441 }
2442 case MachO::CPU_TYPE_X86_64:
2443 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2444 case MachO::CPU_SUBTYPE_X86_64_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002445 if (ArchFlag)
2446 *ArchFlag = "x86_64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002447 return Triple("x86_64-apple-darwin");
2448 case MachO::CPU_SUBTYPE_X86_64_H:
Kevin Enderby59343a92016-12-16 22:54:02 +00002449 if (ArchFlag)
2450 *ArchFlag = "x86_64h";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002451 return Triple("x86_64h-apple-darwin");
2452 default:
2453 return Triple();
2454 }
2455 case MachO::CPU_TYPE_ARM:
2456 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2457 case MachO::CPU_SUBTYPE_ARM_V4T:
Kevin Enderby59343a92016-12-16 22:54:02 +00002458 if (ArchFlag)
2459 *ArchFlag = "armv4t";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002460 return Triple("armv4t-apple-darwin");
2461 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
Kevin Enderby59343a92016-12-16 22:54:02 +00002462 if (ArchFlag)
2463 *ArchFlag = "armv5e";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002464 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002465 case MachO::CPU_SUBTYPE_ARM_XSCALE:
Kevin Enderby59343a92016-12-16 22:54:02 +00002466 if (ArchFlag)
2467 *ArchFlag = "xscale";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002468 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002469 case MachO::CPU_SUBTYPE_ARM_V6:
Kevin Enderby59343a92016-12-16 22:54:02 +00002470 if (ArchFlag)
2471 *ArchFlag = "armv6";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002472 return Triple("armv6-apple-darwin");
2473 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002474 if (McpuDefault)
2475 *McpuDefault = "cortex-m0";
Kevin Enderby59343a92016-12-16 22:54:02 +00002476 if (ArchFlag)
2477 *ArchFlag = "armv6m";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002478 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002479 case MachO::CPU_SUBTYPE_ARM_V7:
Kevin Enderby59343a92016-12-16 22:54:02 +00002480 if (ArchFlag)
2481 *ArchFlag = "armv7";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002482 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002483 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002484 if (McpuDefault)
2485 *McpuDefault = "cortex-m4";
Kevin Enderby59343a92016-12-16 22:54:02 +00002486 if (ArchFlag)
2487 *ArchFlag = "armv7em";
Tim Northover9e8eb412016-04-22 23:21:13 +00002488 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002489 case MachO::CPU_SUBTYPE_ARM_V7K:
Kevin Enderby7a165752017-01-24 23:41:04 +00002490 if (McpuDefault)
2491 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002492 if (ArchFlag)
2493 *ArchFlag = "armv7k";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002494 return Triple("armv7k-apple-darwin");
2495 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002496 if (McpuDefault)
2497 *McpuDefault = "cortex-m3";
Kevin Enderby59343a92016-12-16 22:54:02 +00002498 if (ArchFlag)
2499 *ArchFlag = "armv7m";
Tim Northover9e8eb412016-04-22 23:21:13 +00002500 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002501 case MachO::CPU_SUBTYPE_ARM_V7S:
Kevin Enderby7a165752017-01-24 23:41:04 +00002502 if (McpuDefault)
2503 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002504 if (ArchFlag)
2505 *ArchFlag = "armv7s";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002506 return Triple("armv7s-apple-darwin");
2507 default:
2508 return Triple();
2509 }
2510 case MachO::CPU_TYPE_ARM64:
2511 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2512 case MachO::CPU_SUBTYPE_ARM64_ALL:
Kevin Enderbydc412cc2017-02-10 19:27:10 +00002513 if (McpuDefault)
2514 *McpuDefault = "cyclone";
Kevin Enderby59343a92016-12-16 22:54:02 +00002515 if (ArchFlag)
2516 *ArchFlag = "arm64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002517 return Triple("arm64-apple-darwin");
2518 default:
2519 return Triple();
2520 }
2521 case MachO::CPU_TYPE_POWERPC:
2522 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2523 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002524 if (ArchFlag)
2525 *ArchFlag = "ppc";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002526 return Triple("ppc-apple-darwin");
2527 default:
2528 return Triple();
2529 }
2530 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00002531 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002532 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002533 if (ArchFlag)
2534 *ArchFlag = "ppc64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002535 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002536 default:
2537 return Triple();
2538 }
2539 default:
2540 return Triple();
2541 }
2542}
2543
2544Triple MachOObjectFile::getHostArch() {
2545 return Triple(sys::getDefaultTargetTriple());
2546}
2547
Rafael Espindola72318b42014-08-08 16:30:17 +00002548bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2549 return StringSwitch<bool>(ArchFlag)
2550 .Case("i386", true)
2551 .Case("x86_64", true)
2552 .Case("x86_64h", true)
2553 .Case("armv4t", true)
2554 .Case("arm", true)
2555 .Case("armv5e", true)
2556 .Case("armv6", true)
2557 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00002558 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002559 .Case("armv7em", true)
2560 .Case("armv7k", true)
2561 .Case("armv7m", true)
2562 .Case("armv7s", true)
2563 .Case("arm64", true)
2564 .Case("ppc", true)
2565 .Case("ppc64", true)
2566 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002567}
2568
Alexey Samsonove6388e62013-06-18 15:03:28 +00002569unsigned MachOObjectFile::getArch() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002570 return getArch(getCPUType(*this));
Alexey Samsonove6388e62013-06-18 15:03:28 +00002571}
2572
Tim Northover9e8eb412016-04-22 23:21:13 +00002573Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2574 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002575}
2576
Rui Ueyamabc654b12013-09-27 21:47:05 +00002577relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002578 DataRefImpl DRI;
2579 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002580 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002581}
2582
Rui Ueyamabc654b12013-09-27 21:47:05 +00002583relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002584 DataRefImpl DRI;
2585 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002586 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002587}
2588
Kevin Enderby273ae012013-06-06 17:20:50 +00002589dice_iterator MachOObjectFile::begin_dices() const {
2590 DataRefImpl DRI;
2591 if (!DataInCodeLoadCmd)
2592 return dice_iterator(DiceRef(DRI, this));
2593
Charles Davis8bdfafd2013-09-01 04:28:48 +00002594 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
Lang Hames697e7cd2016-12-04 01:56:10 +00002595 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00002596 return dice_iterator(DiceRef(DRI, this));
2597}
2598
2599dice_iterator MachOObjectFile::end_dices() const {
2600 DataRefImpl DRI;
2601 if (!DataInCodeLoadCmd)
2602 return dice_iterator(DiceRef(DRI, this));
2603
Charles Davis8bdfafd2013-09-01 04:28:48 +00002604 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2605 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002606 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Kevin Enderby273ae012013-06-06 17:20:50 +00002607 return dice_iterator(DiceRef(DRI, this));
2608}
2609
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002610ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
2611 ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002612
2613void ExportEntry::moveToFirst() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002614 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002615 pushNode(0);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002616 if (*E)
2617 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002618 pushDownUntilBottom();
2619}
2620
2621void ExportEntry::moveToEnd() {
2622 Stack.clear();
2623 Done = true;
2624}
2625
2626bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002627 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002628 if (Done || Other.Done)
2629 return (Done == Other.Done);
2630 // Not equal if different stack sizes.
2631 if (Stack.size() != Other.Stack.size())
2632 return false;
2633 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00002634 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00002635 return false;
2636 // Equal if all nodes in both stacks match.
2637 for (unsigned i=0; i < Stack.size(); ++i) {
2638 if (Stack[i].Start != Other.Stack[i].Start)
2639 return false;
2640 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002641 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002642}
2643
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002644uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002645 unsigned Count;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002646 uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002647 Ptr += Count;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002648 if (Ptr > Trie.end())
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002649 Ptr = Trie.end();
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002650 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002651}
2652
2653StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00002654 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002655}
2656
2657uint64_t ExportEntry::flags() const {
2658 return Stack.back().Flags;
2659}
2660
2661uint64_t ExportEntry::address() const {
2662 return Stack.back().Address;
2663}
2664
2665uint64_t ExportEntry::other() const {
2666 return Stack.back().Other;
2667}
2668
2669StringRef ExportEntry::otherName() const {
2670 const char* ImportName = Stack.back().ImportName;
2671 if (ImportName)
2672 return StringRef(ImportName);
2673 return StringRef();
2674}
2675
2676uint32_t ExportEntry::nodeOffset() const {
2677 return Stack.back().Start - Trie.begin();
2678}
2679
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002680ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002681 : Start(Ptr), Current(Ptr) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002682
2683void ExportEntry::pushNode(uint64_t offset) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002684 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002685 const uint8_t *Ptr = Trie.begin() + offset;
2686 NodeState State(Ptr);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002687 const char *error;
2688 uint64_t ExportInfoSize = readULEB128(State.Current, &error);
2689 if (error) {
2690 *E = malformedError("export info size " + Twine(error) + " in export trie "
2691 "data at node: 0x" + utohexstr(offset));
2692 moveToEnd();
2693 return;
2694 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002695 State.IsExportNode = (ExportInfoSize != 0);
2696 const uint8_t* Children = State.Current + ExportInfoSize;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002697 if (Children > Trie.end()) {
2698 *E = malformedError("export info size: 0x" + utohexstr(ExportInfoSize) +
2699 " in export trie data at node: 0x" + utohexstr(offset) +
2700 " too big and extends past end of trie data");
2701 moveToEnd();
2702 return;
2703 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002704 if (State.IsExportNode) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002705 const uint8_t *ExportStart = State.Current;
2706 State.Flags = readULEB128(State.Current, &error);
2707 if (error) {
2708 *E = malformedError("flags " + Twine(error) + " in export trie data at "
2709 "node: 0x" + utohexstr(offset));
2710 moveToEnd();
2711 return;
2712 }
2713 uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
2714 if (State.Flags != 0 &&
2715 (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
2716 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
2717 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
2718 *E = malformedError("unsupported exported symbol kind: "
2719 + Twine((int)Kind) + " in flags: 0x" + utohexstr(State.Flags) +
2720 " in export trie data at node: 0x" + utohexstr(offset));
2721 moveToEnd();
2722 return;
2723 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002724 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2725 State.Address = 0;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002726 State.Other = readULEB128(State.Current, &error); // dylib ordinal
2727 if (error) {
2728 *E = malformedError("dylib ordinal of re-export " + Twine(error) +
2729 " in export trie data at node: 0x" + utohexstr(offset));
2730 moveToEnd();
2731 return;
2732 }
2733 if (O != nullptr) {
2734 if (State.Other > O->getLibraryCount()) {
2735 *E = malformedError("bad library ordinal: " + Twine((int)State.Other)
2736 + " (max " + Twine((int)O->getLibraryCount()) + ") in export "
2737 "trie data at node: 0x" + utohexstr(offset));
2738 moveToEnd();
2739 return;
2740 }
2741 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002742 State.ImportName = reinterpret_cast<const char*>(State.Current);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002743 if (*State.ImportName == '\0') {
2744 State.Current++;
2745 } else {
2746 const uint8_t *End = State.Current + 1;
2747 if (End >= Trie.end()) {
2748 *E = malformedError("import name of re-export in export trie data at "
2749 "node: 0x" + utohexstr(offset) + " starts past end of trie "
2750 "data");
2751 moveToEnd();
2752 return;
2753 }
2754 while(*End != '\0' && End < Trie.end())
2755 End++;
2756 if (*End != '\0') {
2757 *E = malformedError("import name of re-export in export trie data at "
2758 "node: 0x" + utohexstr(offset) + " extends past end of trie "
2759 "data");
2760 moveToEnd();
2761 return;
2762 }
2763 State.Current = End + 1;
2764 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002765 } else {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002766 State.Address = readULEB128(State.Current, &error);
2767 if (error) {
2768 *E = malformedError("address " + Twine(error) + " in export trie data "
2769 "at node: 0x" + utohexstr(offset));
2770 moveToEnd();
2771 return;
2772 }
2773 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
2774 State.Other = readULEB128(State.Current, &error);
2775 if (error) {
2776 *E = malformedError("resolver of stub and resolver " + Twine(error) +
2777 " in export trie data at node: 0x" + utohexstr(offset));
2778 moveToEnd();
2779 return;
2780 }
2781 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002782 }
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002783 if(ExportStart + ExportInfoSize != State.Current) {
2784 *E = malformedError("inconsistant export info size: 0x" +
2785 utohexstr(ExportInfoSize) + " where actual size was: 0x" +
2786 utohexstr(State.Current - ExportStart) + " in export trie data "
2787 "at node: 0x" + utohexstr(offset));
2788 moveToEnd();
2789 return;
2790 }
2791 }
Kevin Enderby8100cde2017-07-24 20:33:41 +00002792 State.ChildCount = *Children;
2793 if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002794 *E = malformedError("byte for count of childern in export trie data at "
2795 "node: 0x" + utohexstr(offset) + " extends past end of trie data");
2796 moveToEnd();
2797 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002798 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002799 State.Current = Children + 1;
2800 State.NextChildIndex = 0;
2801 State.ParentStringLength = CumulativeString.size();
2802 Stack.push_back(State);
2803}
2804
2805void ExportEntry::pushDownUntilBottom() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002806 ErrorAsOutParameter ErrAsOutParam(E);
2807 const char *error;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002808 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2809 NodeState &Top = Stack.back();
2810 CumulativeString.resize(Top.ParentStringLength);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002811 for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002812 char C = *Top.Current;
2813 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002814 }
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002815 if (Top.Current >= Trie.end()) {
2816 *E = malformedError("edge sub-string in export trie data at node: 0x" +
2817 utohexstr(Top.Start - Trie.begin()) + " for child #" +
2818 Twine((int)Top.NextChildIndex) + " extends past end of trie data");
2819 moveToEnd();
2820 return;
2821 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002822 Top.Current += 1;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002823 uint64_t childNodeIndex = readULEB128(Top.Current, &error);
2824 if (error) {
2825 *E = malformedError("child node offset " + Twine(error) +
2826 " in export trie data at node: 0x" +
2827 utohexstr(Top.Start - Trie.begin()));
2828 moveToEnd();
2829 return;
2830 }
2831 for (const NodeState &node : nodes()) {
2832 if (node.Start == Trie.begin() + childNodeIndex){
2833 *E = malformedError("loop in childern in export trie data at node: 0x" +
2834 utohexstr(Top.Start - Trie.begin()) + " back to node: 0x" +
2835 utohexstr(childNodeIndex));
2836 moveToEnd();
2837 return;
2838 }
2839 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002840 Top.NextChildIndex += 1;
2841 pushNode(childNodeIndex);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002842 if (*E)
2843 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002844 }
2845 if (!Stack.back().IsExportNode) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002846 *E = malformedError("node is not an export node in export trie data at "
2847 "node: 0x" + utohexstr(Stack.back().Start - Trie.begin()));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002848 moveToEnd();
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002849 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002850 }
2851}
2852
2853// We have a trie data structure and need a way to walk it that is compatible
2854// with the C++ iterator model. The solution is a non-recursive depth first
2855// traversal where the iterator contains a stack of parent nodes along with a
2856// string that is the accumulation of all edge strings along the parent chain
2857// to this point.
2858//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00002859// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00002860// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002861// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002862//
2863// The algorithm for moveNext() is to keep moving down the leftmost unvisited
2864// child until hitting a node with no children (which is an export node or
2865// else the trie is malformed). On the way down, each node is pushed on the
2866// stack ivar. If there is no more ways down, it pops up one and tries to go
2867// down a sibling path until a childless node is reached.
2868void ExportEntry::moveNext() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002869 assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
2870 if (!Stack.back().IsExportNode) {
2871 *E = malformedError("node is not an export node in export trie data at "
2872 "node: 0x" + utohexstr(Stack.back().Start - Trie.begin()));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002873 moveToEnd();
2874 return;
2875 }
2876
2877 Stack.pop_back();
2878 while (!Stack.empty()) {
2879 NodeState &Top = Stack.back();
2880 if (Top.NextChildIndex < Top.ChildCount) {
2881 pushDownUntilBottom();
2882 // Now at the next export node.
2883 return;
2884 } else {
2885 if (Top.IsExportNode) {
2886 // This node has no children but is itself an export node.
2887 CumulativeString.resize(Top.ParentStringLength);
2888 return;
2889 }
2890 Stack.pop_back();
2891 }
2892 }
2893 Done = true;
2894}
2895
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002896iterator_range<export_iterator>
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002897MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
2898 const MachOObjectFile *O) {
2899 ExportEntry Start(&E, O, Trie);
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002900 if (Trie.empty())
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00002901 Start.moveToEnd();
2902 else
2903 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002904
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002905 ExportEntry Finish(&E, O, Trie);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002906 Finish.moveToEnd();
2907
Craig Topper15576e12015-12-06 05:08:07 +00002908 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002909}
2910
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002911iterator_range<export_iterator> MachOObjectFile::exports(Error &Err,
2912 const MachOObjectFile *O) const {
2913 return exports(Err, getDyldInfoExportsTrie(), O);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002914}
2915
Kevin Enderbya8d256c2017-03-20 19:46:55 +00002916MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
2917 ArrayRef<uint8_t> Bytes, bool is64Bit)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002918 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
2919 PointerSize(is64Bit ? 8 : 4) {}
Nick Kledzikac431442014-09-12 21:34:15 +00002920
2921void MachORebaseEntry::moveToFirst() {
2922 Ptr = Opcodes.begin();
2923 moveNext();
2924}
2925
2926void MachORebaseEntry::moveToEnd() {
2927 Ptr = Opcodes.end();
2928 RemainingLoopCount = 0;
2929 Done = true;
2930}
2931
2932void MachORebaseEntry::moveNext() {
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002933 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikac431442014-09-12 21:34:15 +00002934 // If in the middle of some loop, move to next rebasing in loop.
2935 SegmentOffset += AdvanceAmount;
2936 if (RemainingLoopCount) {
2937 --RemainingLoopCount;
2938 return;
2939 }
Juergen Ributzkacad12492017-03-30 19:56:50 +00002940 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
2941 // pointer size. Therefore it is possible to reach the end without ever having
2942 // seen REBASE_OPCODE_DONE.
2943 if (Ptr == Opcodes.end()) {
Nick Kledzikac431442014-09-12 21:34:15 +00002944 Done = true;
2945 return;
2946 }
2947 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002948 while (More) {
Nick Kledzikac431442014-09-12 21:34:15 +00002949 // Parse next opcode and set up next loop.
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002950 const uint8_t *OpcodeStart = Ptr;
Nick Kledzikac431442014-09-12 21:34:15 +00002951 uint8_t Byte = *Ptr++;
2952 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
2953 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002954 uint32_t Count, Skip;
2955 const char *error = nullptr;
Nick Kledzikac431442014-09-12 21:34:15 +00002956 switch (Opcode) {
2957 case MachO::REBASE_OPCODE_DONE:
2958 More = false;
2959 Done = true;
2960 moveToEnd();
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002961 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
Nick Kledzikac431442014-09-12 21:34:15 +00002962 break;
2963 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
2964 RebaseType = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002965 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
2966 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
2967 Twine((int)RebaseType) + " for opcode at: 0x" +
2968 utohexstr(OpcodeStart - Opcodes.begin()));
2969 moveToEnd();
2970 return;
2971 }
Nick Kledzikac431442014-09-12 21:34:15 +00002972 DEBUG_WITH_TYPE(
2973 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002974 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
2975 << "RebaseType=" << (int) RebaseType << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00002976 break;
2977 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2978 SegmentIndex = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002979 SegmentOffset = readULEB128(&error);
2980 if (error) {
2981 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
2982 Twine(error) + " for opcode at: 0x" +
2983 utohexstr(OpcodeStart - Opcodes.begin()));
2984 moveToEnd();
2985 return;
2986 }
2987 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2988 true);
2989 if (error) {
2990 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
2991 Twine(error) + " for opcode at: 0x" +
2992 utohexstr(OpcodeStart - Opcodes.begin()));
2993 moveToEnd();
2994 return;
2995 }
Nick Kledzikac431442014-09-12 21:34:15 +00002996 DEBUG_WITH_TYPE(
2997 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002998 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2999 << "SegmentIndex=" << SegmentIndex << ", "
3000 << format("SegmentOffset=0x%06X", SegmentOffset)
3001 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003002 break;
3003 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003004 SegmentOffset += readULEB128(&error);
3005 if (error) {
3006 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
3007 Twine(error) + " for opcode at: 0x" +
3008 utohexstr(OpcodeStart - Opcodes.begin()));
3009 moveToEnd();
3010 return;
3011 }
3012 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3013 true);
3014 if (error) {
3015 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
3016 Twine(error) + " for opcode at: 0x" +
3017 utohexstr(OpcodeStart - Opcodes.begin()));
3018 moveToEnd();
3019 return;
3020 }
Nick Kledzikac431442014-09-12 21:34:15 +00003021 DEBUG_WITH_TYPE("mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003022 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3023 << format("SegmentOffset=0x%06X",
3024 SegmentOffset) << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003025 break;
3026 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003027 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3028 true);
3029 if (error) {
3030 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3031 Twine(error) + " for opcode at: 0x" +
3032 utohexstr(OpcodeStart - Opcodes.begin()));
3033 moveToEnd();
3034 return;
3035 }
Nick Kledzikac431442014-09-12 21:34:15 +00003036 SegmentOffset += ImmValue * PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003037 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3038 false);
3039 if (error) {
3040 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3041 " (after adding immediate times the pointer size) " +
3042 Twine(error) + " for opcode at: 0x" +
3043 utohexstr(OpcodeStart - Opcodes.begin()));
3044 moveToEnd();
3045 return;
3046 }
Nick Kledzikac431442014-09-12 21:34:15 +00003047 DEBUG_WITH_TYPE("mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003048 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3049 << format("SegmentOffset=0x%06X",
3050 SegmentOffset) << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003051 break;
3052 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003053 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3054 true);
3055 if (error) {
3056 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3057 Twine(error) + " for opcode at: 0x" +
3058 utohexstr(OpcodeStart - Opcodes.begin()));
3059 moveToEnd();
3060 return;
3061 }
Nick Kledzikac431442014-09-12 21:34:15 +00003062 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003063 Skip = 0;
3064 Count = ImmValue;
3065 if (ImmValue != 0)
3066 RemainingLoopCount = ImmValue - 1;
3067 else
3068 RemainingLoopCount = 0;
3069 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3070 SegmentIndex, SegmentOffset);
3071 if (error) {
3072 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES "
3073 + Twine(error) + " for opcode at: 0x" +
3074 utohexstr(OpcodeStart - Opcodes.begin()));
3075 moveToEnd();
3076 return;
3077 }
Nick Kledzikac431442014-09-12 21:34:15 +00003078 DEBUG_WITH_TYPE(
3079 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003080 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3081 << format("SegmentOffset=0x%06X", SegmentOffset)
3082 << ", AdvanceAmount=" << AdvanceAmount
3083 << ", RemainingLoopCount=" << RemainingLoopCount
3084 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003085 return;
3086 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003087 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3088 true);
3089 if (error) {
3090 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3091 Twine(error) + " for opcode at: 0x" +
3092 utohexstr(OpcodeStart - Opcodes.begin()));
3093 moveToEnd();
3094 return;
3095 }
Nick Kledzikac431442014-09-12 21:34:15 +00003096 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003097 Skip = 0;
3098 Count = readULEB128(&error);
3099 if (error) {
3100 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3101 Twine(error) + " for opcode at: 0x" +
3102 utohexstr(OpcodeStart - Opcodes.begin()));
3103 moveToEnd();
3104 return;
3105 }
3106 if (Count != 0)
3107 RemainingLoopCount = Count - 1;
3108 else
3109 RemainingLoopCount = 0;
3110 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3111 SegmentIndex, SegmentOffset);
3112 if (error) {
3113 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES "
3114 + Twine(error) + " for opcode at: 0x" +
3115 utohexstr(OpcodeStart - Opcodes.begin()));
3116 moveToEnd();
3117 return;
3118 }
Nick Kledzikac431442014-09-12 21:34:15 +00003119 DEBUG_WITH_TYPE(
3120 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003121 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3122 << format("SegmentOffset=0x%06X", SegmentOffset)
3123 << ", AdvanceAmount=" << AdvanceAmount
3124 << ", RemainingLoopCount=" << RemainingLoopCount
3125 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003126 return;
3127 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003128 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3129 true);
3130 if (error) {
3131 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3132 Twine(error) + " for opcode at: 0x" +
3133 utohexstr(OpcodeStart - Opcodes.begin()));
3134 moveToEnd();
3135 return;
3136 }
3137 Skip = readULEB128(&error);
3138 if (error) {
3139 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3140 Twine(error) + " for opcode at: 0x" +
3141 utohexstr(OpcodeStart - Opcodes.begin()));
3142 moveToEnd();
3143 return;
3144 }
3145 AdvanceAmount = Skip + PointerSize;
3146 Count = 1;
Nick Kledzikac431442014-09-12 21:34:15 +00003147 RemainingLoopCount = 0;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003148 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3149 SegmentIndex, SegmentOffset);
3150 if (error) {
3151 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB "
3152 + Twine(error) + " for opcode at: 0x" +
3153 utohexstr(OpcodeStart - Opcodes.begin()));
3154 moveToEnd();
3155 return;
3156 }
Nick Kledzikac431442014-09-12 21:34:15 +00003157 DEBUG_WITH_TYPE(
3158 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003159 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3160 << format("SegmentOffset=0x%06X", SegmentOffset)
3161 << ", AdvanceAmount=" << AdvanceAmount
3162 << ", RemainingLoopCount=" << RemainingLoopCount
3163 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003164 return;
3165 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003166 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3167 true);
3168 if (error) {
3169 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3170 "ULEB " + Twine(error) + " for opcode at: 0x" +
3171 utohexstr(OpcodeStart - Opcodes.begin()));
3172 moveToEnd();
3173 return;
3174 }
3175 Count = readULEB128(&error);
3176 if (error) {
3177 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3178 "ULEB " + Twine(error) + " for opcode at: 0x" +
3179 utohexstr(OpcodeStart - Opcodes.begin()));
3180 moveToEnd();
3181 return;
3182 }
3183 if (Count != 0)
3184 RemainingLoopCount = Count - 1;
3185 else
3186 RemainingLoopCount = 0;
3187 Skip = readULEB128(&error);
3188 if (error) {
3189 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3190 "ULEB " + Twine(error) + " for opcode at: 0x" +
3191 utohexstr(OpcodeStart - Opcodes.begin()));
3192 moveToEnd();
3193 return;
3194 }
3195 AdvanceAmount = Skip + PointerSize;
3196
3197 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3198 SegmentIndex, SegmentOffset);
3199 if (error) {
3200 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3201 "ULEB " + Twine(error) + " for opcode at: 0x" +
3202 utohexstr(OpcodeStart - Opcodes.begin()));
3203 moveToEnd();
3204 return;
3205 }
Nick Kledzikac431442014-09-12 21:34:15 +00003206 DEBUG_WITH_TYPE(
3207 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003208 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3209 << format("SegmentOffset=0x%06X", SegmentOffset)
3210 << ", AdvanceAmount=" << AdvanceAmount
3211 << ", RemainingLoopCount=" << RemainingLoopCount
3212 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003213 return;
3214 default:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003215 *E = malformedError("bad rebase info (bad opcode value 0x" +
3216 utohexstr(Opcode) + " for opcode at: 0x" +
3217 utohexstr(OpcodeStart - Opcodes.begin()));
3218 moveToEnd();
3219 return;
Nick Kledzikac431442014-09-12 21:34:15 +00003220 }
3221 }
3222}
3223
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003224uint64_t MachORebaseEntry::readULEB128(const char **error) {
Nick Kledzikac431442014-09-12 21:34:15 +00003225 unsigned Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003226 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzikac431442014-09-12 21:34:15 +00003227 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003228 if (Ptr > Opcodes.end())
Nick Kledzikac431442014-09-12 21:34:15 +00003229 Ptr = Opcodes.end();
Nick Kledzikac431442014-09-12 21:34:15 +00003230 return Result;
3231}
3232
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003233int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzikac431442014-09-12 21:34:15 +00003234
3235uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3236
3237StringRef MachORebaseEntry::typeName() const {
3238 switch (RebaseType) {
3239 case MachO::REBASE_TYPE_POINTER:
3240 return "pointer";
3241 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3242 return "text abs32";
3243 case MachO::REBASE_TYPE_TEXT_PCREL32:
3244 return "text rel32";
3245 }
3246 return "unknown";
3247}
3248
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003249// For use with the SegIndex of a checked Mach-O Rebase entry
3250// to get the segment name.
3251StringRef MachORebaseEntry::segmentName() const {
3252 return O->BindRebaseSegmentName(SegmentIndex);
3253}
3254
3255// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3256// to get the section name.
3257StringRef MachORebaseEntry::sectionName() const {
3258 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3259}
3260
3261// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3262// to get the address.
3263uint64_t MachORebaseEntry::address() const {
3264 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3265}
3266
Nick Kledzikac431442014-09-12 21:34:15 +00003267bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003268#ifdef EXPENSIVE_CHECKS
Nick Kledzikac431442014-09-12 21:34:15 +00003269 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003270#else
3271 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3272#endif
Nick Kledzikac431442014-09-12 21:34:15 +00003273 return (Ptr == Other.Ptr) &&
3274 (RemainingLoopCount == Other.RemainingLoopCount) &&
3275 (Done == Other.Done);
3276}
3277
3278iterator_range<rebase_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003279MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3280 ArrayRef<uint8_t> Opcodes, bool is64) {
3281 if (O->BindRebaseSectionTable == nullptr)
3282 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3283 MachORebaseEntry Start(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003284 Start.moveToFirst();
3285
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003286 MachORebaseEntry Finish(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003287 Finish.moveToEnd();
3288
Craig Topper15576e12015-12-06 05:08:07 +00003289 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00003290}
3291
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003292iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3293 return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
Nick Kledzikac431442014-09-12 21:34:15 +00003294}
3295
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003296MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3297 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003298 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3299 PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
Nick Kledzik56ebef42014-09-16 01:41:51 +00003300
3301void MachOBindEntry::moveToFirst() {
3302 Ptr = Opcodes.begin();
3303 moveNext();
3304}
3305
3306void MachOBindEntry::moveToEnd() {
3307 Ptr = Opcodes.end();
3308 RemainingLoopCount = 0;
3309 Done = true;
3310}
3311
3312void MachOBindEntry::moveNext() {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003313 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003314 // If in the middle of some loop, move to next binding in loop.
3315 SegmentOffset += AdvanceAmount;
3316 if (RemainingLoopCount) {
3317 --RemainingLoopCount;
3318 return;
3319 }
Juergen Ributzkacad12492017-03-30 19:56:50 +00003320 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3321 // pointer size. Therefore it is possible to reach the end without ever having
3322 // seen BIND_OPCODE_DONE.
3323 if (Ptr == Opcodes.end()) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003324 Done = true;
3325 return;
3326 }
3327 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003328 while (More) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003329 // Parse next opcode and set up next loop.
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003330 const uint8_t *OpcodeStart = Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003331 uint8_t Byte = *Ptr++;
3332 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3333 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3334 int8_t SignExtended;
3335 const uint8_t *SymStart;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003336 uint32_t Count, Skip;
3337 const char *error = nullptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003338 switch (Opcode) {
3339 case MachO::BIND_OPCODE_DONE:
3340 if (TableKind == Kind::Lazy) {
3341 // Lazying bindings have a DONE opcode between entries. Need to ignore
3342 // it to advance to next entry. But need not if this is last entry.
3343 bool NotLastEntry = false;
3344 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3345 if (*P) {
3346 NotLastEntry = true;
3347 }
3348 }
3349 if (NotLastEntry)
3350 break;
3351 }
3352 More = false;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003353 moveToEnd();
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003354 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003355 break;
3356 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003357 if (TableKind == Kind::Weak) {
3358 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3359 "weak bind table for opcode at: 0x" +
3360 utohexstr(OpcodeStart - Opcodes.begin()));
3361 moveToEnd();
3362 return;
3363 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003364 Ordinal = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003365 LibraryOrdinalSet = true;
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003366 if (ImmValue > O->getLibraryCount()) {
3367 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3368 "library ordinal: " + Twine((int)ImmValue) + " (max " +
3369 Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" +
3370 utohexstr(OpcodeStart - Opcodes.begin()));
3371 moveToEnd();
3372 return;
3373 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003374 DEBUG_WITH_TYPE(
3375 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003376 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3377 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003378 break;
3379 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003380 if (TableKind == Kind::Weak) {
3381 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3382 "weak bind table for opcode at: 0x" +
3383 utohexstr(OpcodeStart - Opcodes.begin()));
3384 moveToEnd();
3385 return;
3386 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003387 Ordinal = readULEB128(&error);
3388 LibraryOrdinalSet = true;
3389 if (error) {
3390 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3391 Twine(error) + " for opcode at: 0x" +
3392 utohexstr(OpcodeStart - Opcodes.begin()));
3393 moveToEnd();
3394 return;
3395 }
3396 if (Ordinal > (int)O->getLibraryCount()) {
3397 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3398 "library ordinal: " + Twine((int)Ordinal) + " (max " +
3399 Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" +
3400 utohexstr(OpcodeStart - Opcodes.begin()));
3401 moveToEnd();
3402 return;
3403 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003404 DEBUG_WITH_TYPE(
3405 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003406 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3407 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003408 break;
3409 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003410 if (TableKind == Kind::Weak) {
3411 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3412 "weak bind table for opcode at: 0x" +
3413 utohexstr(OpcodeStart - Opcodes.begin()));
3414 moveToEnd();
3415 return;
3416 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003417 if (ImmValue) {
3418 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3419 Ordinal = SignExtended;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003420 if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3421 *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3422 "special ordinal: " + Twine((int)Ordinal) + " for opcode at: "
3423 "0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3424 moveToEnd();
3425 return;
3426 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003427 } else
3428 Ordinal = 0;
Steven Wu97e2cf82017-05-31 22:17:43 +00003429 LibraryOrdinalSet = true;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003430 DEBUG_WITH_TYPE(
3431 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003432 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3433 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003434 break;
3435 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3436 Flags = ImmValue;
3437 SymStart = Ptr;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003438 while (*Ptr && (Ptr < Opcodes.end())) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003439 ++Ptr;
3440 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003441 if (Ptr == Opcodes.end()) {
3442 *E = malformedError("for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3443 "symbol name extends past opcodes for opcode at: 0x" +
3444 utohexstr(OpcodeStart - Opcodes.begin()));
3445 moveToEnd();
3446 return;
3447 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003448 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3449 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00003450 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003451 DEBUG_WITH_TYPE(
3452 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003453 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3454 << "SymbolName=" << SymbolName << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003455 if (TableKind == Kind::Weak) {
3456 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3457 return;
3458 }
3459 break;
3460 case MachO::BIND_OPCODE_SET_TYPE_IMM:
3461 BindType = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003462 if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
3463 *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3464 Twine((int)ImmValue) + " for opcode at: 0x" +
3465 utohexstr(OpcodeStart - Opcodes.begin()));
3466 moveToEnd();
3467 return;
3468 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003469 DEBUG_WITH_TYPE(
3470 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003471 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3472 << "BindType=" << (int)BindType << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003473 break;
3474 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003475 Addend = readSLEB128(&error);
3476 if (error) {
3477 *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " +
3478 Twine(error) + " for opcode at: 0x" +
3479 utohexstr(OpcodeStart - Opcodes.begin()));
3480 moveToEnd();
3481 return;
3482 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003483 DEBUG_WITH_TYPE(
3484 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003485 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3486 << "Addend=" << Addend << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003487 break;
3488 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3489 SegmentIndex = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003490 SegmentOffset = readULEB128(&error);
3491 if (error) {
3492 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3493 Twine(error) + " for opcode at: 0x" +
3494 utohexstr(OpcodeStart - Opcodes.begin()));
3495 moveToEnd();
3496 return;
3497 }
3498 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3499 if (error) {
3500 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3501 Twine(error) + " for opcode at: 0x" +
3502 utohexstr(OpcodeStart - Opcodes.begin()));
3503 moveToEnd();
3504 return;
3505 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003506 DEBUG_WITH_TYPE(
3507 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003508 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3509 << "SegmentIndex=" << SegmentIndex << ", "
3510 << format("SegmentOffset=0x%06X", SegmentOffset)
3511 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003512 break;
3513 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003514 SegmentOffset += readULEB128(&error);
3515 if (error) {
3516 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " +
3517 Twine(error) + " for opcode at: 0x" +
3518 utohexstr(OpcodeStart - Opcodes.begin()));
3519 moveToEnd();
3520 return;
3521 }
3522 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3523 if (error) {
3524 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " +
3525 Twine(error) + " for opcode at: 0x" +
3526 utohexstr(OpcodeStart - Opcodes.begin()));
3527 moveToEnd();
3528 return;
3529 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003530 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003531 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3532 << format("SegmentOffset=0x%06X",
3533 SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003534 break;
3535 case MachO::BIND_OPCODE_DO_BIND:
3536 AdvanceAmount = PointerSize;
3537 RemainingLoopCount = 0;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003538 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3539 if (error) {
3540 *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
3541 " for opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3542 moveToEnd();
3543 return;
3544 }
3545 if (SymbolName == StringRef()) {
3546 *E = malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3547 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3548 utohexstr(OpcodeStart - Opcodes.begin()));
3549 moveToEnd();
3550 return;
3551 }
3552 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3553 *E = malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3554 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3555 utohexstr(OpcodeStart - Opcodes.begin()));
3556 moveToEnd();
3557 return;
3558 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003559 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003560 dbgs() << "BIND_OPCODE_DO_BIND: "
3561 << format("SegmentOffset=0x%06X",
3562 SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003563 return;
3564 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003565 if (TableKind == Kind::Lazy) {
3566 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3567 "lazy bind table for opcode at: 0x" +
3568 utohexstr(OpcodeStart - Opcodes.begin()));
3569 moveToEnd();
3570 return;
3571 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003572 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3573 if (error) {
3574 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3575 Twine(error) + " for opcode at: 0x" +
3576 utohexstr(OpcodeStart - Opcodes.begin()));
3577 moveToEnd();
3578 return;
3579 }
3580 if (SymbolName == StringRef()) {
3581 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3582 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3583 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3584 moveToEnd();
3585 return;
3586 }
3587 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3588 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3589 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3590 utohexstr(OpcodeStart - Opcodes.begin()));
3591 moveToEnd();
3592 return;
3593 }
3594 AdvanceAmount = readULEB128(&error) + PointerSize;
3595 if (error) {
3596 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3597 Twine(error) + " for opcode at: 0x" +
3598 utohexstr(OpcodeStart - Opcodes.begin()));
3599 moveToEnd();
3600 return;
3601 }
3602 // Note, this is not really an error until the next bind but make no sense
3603 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3604 // bind operation.
3605 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3606 AdvanceAmount, false);
3607 if (error) {
3608 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3609 "ULEB) " + Twine(error) + " for opcode at: 0x" +
3610 utohexstr(OpcodeStart - Opcodes.begin()));
3611 moveToEnd();
3612 return;
3613 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003614 RemainingLoopCount = 0;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003615 DEBUG_WITH_TYPE(
3616 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003617 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3618 << format("SegmentOffset=0x%06X", SegmentOffset)
3619 << ", AdvanceAmount=" << AdvanceAmount
3620 << ", RemainingLoopCount=" << RemainingLoopCount
3621 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003622 return;
3623 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003624 if (TableKind == Kind::Lazy) {
3625 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3626 "allowed in lazy bind table for opcode at: 0x" +
3627 utohexstr(OpcodeStart - Opcodes.begin()));
3628 moveToEnd();
3629 return;
3630 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003631 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3632 if (error) {
3633 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3634 Twine(error) + " for opcode at: 0x" +
3635 utohexstr(OpcodeStart - Opcodes.begin()));
3636 moveToEnd();
3637 return;
3638 }
3639 if (SymbolName == StringRef()) {
3640 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3641 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3642 "opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3643 moveToEnd();
3644 return;
3645 }
3646 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3647 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3648 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3649 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3650 moveToEnd();
3651 return;
3652 }
Nick Kledzik3b2aa052014-10-18 01:21:02 +00003653 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003654 RemainingLoopCount = 0;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003655 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3656 AdvanceAmount, false);
3657 if (error) {
3658 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3659 " (after adding immediate times the pointer size) " +
3660 Twine(error) + " for opcode at: 0x" +
3661 utohexstr(OpcodeStart - Opcodes.begin()));
3662 moveToEnd();
3663 return;
3664 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003665 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003666 dbgs()
Nick Kledzik56ebef42014-09-16 01:41:51 +00003667 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003668 << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003669 return;
3670 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003671 if (TableKind == Kind::Lazy) {
3672 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3673 "allowed in lazy bind table for opcode at: 0x" +
3674 utohexstr(OpcodeStart - Opcodes.begin()));
3675 moveToEnd();
3676 return;
3677 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003678 Count = readULEB128(&error);
3679 if (Count != 0)
3680 RemainingLoopCount = Count - 1;
3681 else
3682 RemainingLoopCount = 0;
3683 if (error) {
3684 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3685 " (count value) " + Twine(error) + " for opcode at"
3686 ": 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3687 moveToEnd();
3688 return;
3689 }
3690 Skip = readULEB128(&error);
3691 AdvanceAmount = Skip + PointerSize;
3692 if (error) {
3693 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3694 " (skip value) " + Twine(error) + " for opcode at"
3695 ": 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3696 moveToEnd();
3697 return;
3698 }
3699 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3700 if (error) {
3701 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3702 + Twine(error) + " for opcode at: 0x" +
3703 utohexstr(OpcodeStart - Opcodes.begin()));
3704 moveToEnd();
3705 return;
3706 }
3707 if (SymbolName == StringRef()) {
3708 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3709 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3710 "opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3711 moveToEnd();
3712 return;
3713 }
3714 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3715 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3716 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3717 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3718 moveToEnd();
3719 return;
3720 }
3721 error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
3722 SegmentIndex, SegmentOffset);
3723 if (error) {
3724 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3725 + Twine(error) + " for opcode at: 0x" +
3726 utohexstr(OpcodeStart - Opcodes.begin()));
3727 moveToEnd();
3728 return;
3729 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003730 DEBUG_WITH_TYPE(
3731 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003732 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3733 << format("SegmentOffset=0x%06X", SegmentOffset)
3734 << ", AdvanceAmount=" << AdvanceAmount
3735 << ", RemainingLoopCount=" << RemainingLoopCount
3736 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003737 return;
3738 default:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003739 *E = malformedError("bad bind info (bad opcode value 0x" +
3740 utohexstr(Opcode) + " for opcode at: 0x" +
3741 utohexstr(OpcodeStart - Opcodes.begin()));
3742 moveToEnd();
3743 return;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003744 }
3745 }
3746}
3747
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003748uint64_t MachOBindEntry::readULEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003749 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003750 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003751 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003752 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003753 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003754 return Result;
3755}
3756
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003757int64_t MachOBindEntry::readSLEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003758 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003759 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003760 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003761 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003762 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003763 return Result;
3764}
3765
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003766int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003767
3768uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3769
3770StringRef MachOBindEntry::typeName() const {
3771 switch (BindType) {
3772 case MachO::BIND_TYPE_POINTER:
3773 return "pointer";
3774 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3775 return "text abs32";
3776 case MachO::BIND_TYPE_TEXT_PCREL32:
3777 return "text rel32";
3778 }
3779 return "unknown";
3780}
3781
3782StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3783
3784int64_t MachOBindEntry::addend() const { return Addend; }
3785
3786uint32_t MachOBindEntry::flags() const { return Flags; }
3787
3788int MachOBindEntry::ordinal() const { return Ordinal; }
3789
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003790// For use with the SegIndex of a checked Mach-O Bind entry
3791// to get the segment name.
3792StringRef MachOBindEntry::segmentName() const {
3793 return O->BindRebaseSegmentName(SegmentIndex);
3794}
3795
3796// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3797// to get the section name.
3798StringRef MachOBindEntry::sectionName() const {
3799 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3800}
3801
3802// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3803// to get the address.
3804uint64_t MachOBindEntry::address() const {
3805 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3806}
3807
Nick Kledzik56ebef42014-09-16 01:41:51 +00003808bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003809#ifdef EXPENSIVE_CHECKS
Nick Kledzik56ebef42014-09-16 01:41:51 +00003810 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003811#else
3812 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3813#endif
Nick Kledzik56ebef42014-09-16 01:41:51 +00003814 return (Ptr == Other.Ptr) &&
3815 (RemainingLoopCount == Other.RemainingLoopCount) &&
3816 (Done == Other.Done);
3817}
3818
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003819// Build table of sections so SegIndex/SegOffset pairs can be translated.
3820BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
3821 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
3822 StringRef CurSegName;
3823 uint64_t CurSegAddress;
3824 for (const SectionRef &Section : Obj->sections()) {
3825 SectionInfo Info;
3826 Section.getName(Info.SectionName);
3827 Info.Address = Section.getAddress();
3828 Info.Size = Section.getSize();
3829 Info.SegmentName =
3830 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
3831 if (!Info.SegmentName.equals(CurSegName)) {
3832 ++CurSegIndex;
3833 CurSegName = Info.SegmentName;
3834 CurSegAddress = Info.Address;
3835 }
3836 Info.SegmentIndex = CurSegIndex - 1;
3837 Info.OffsetInSegment = Info.Address - CurSegAddress;
3838 Info.SegmentStartAddress = CurSegAddress;
3839 Sections.push_back(Info);
3840 }
3841 MaxSegIndex = CurSegIndex;
3842}
3843
3844// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003845// validate a MachOBindEntry or MachORebaseEntry.
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003846const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
3847 uint64_t SegOffset,
3848 bool endInvalid) {
3849 if (SegIndex == -1)
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003850 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003851 if (SegIndex >= MaxSegIndex)
3852 return "bad segIndex (too large)";
3853 for (const SectionInfo &SI : Sections) {
3854 if (SI.SegmentIndex != SegIndex)
3855 continue;
3856 if (SI.OffsetInSegment > SegOffset)
3857 continue;
3858 if (SegOffset > (SI.OffsetInSegment + SI.Size))
3859 continue;
3860 if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
3861 continue;
3862 return nullptr;
3863 }
3864 return "bad segOffset, too large";
3865}
3866
3867// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003868// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
3869// MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
3870// REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
3871// been already checked.
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003872const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
3873 uint8_t PointerSize,
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003874 int32_t SegIndex,
3875 uint64_t SegOffset) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003876 const SectionInfo &SI = findSection(SegIndex, SegOffset);
3877 uint64_t addr = SI.SegmentStartAddress + SegOffset;
3878 if (addr >= SI.Address + SI.Size)
3879 return "bad segOffset, too large";
3880 uint64_t i = 0;
3881 if (Count > 1)
3882 i = (Skip + PointerSize) * (Count - 1);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003883 else if (Count == 1)
3884 i = Skip + PointerSize;
3885 if (addr + i >= SI.Address + SI.Size) {
3886 // For rebase opcodes they can step from one section to another.
3887 uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
3888 const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
3889 if (error)
3890 return "bad count and skip, too large";
3891 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003892 return nullptr;
3893}
3894
3895// For use with the SegIndex of a checked Mach-O Bind or Rebase entry
3896// to get the segment name.
3897StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
3898 for (const SectionInfo &SI : Sections) {
3899 if (SI.SegmentIndex == SegIndex)
3900 return SI.SegmentName;
3901 }
3902 llvm_unreachable("invalid SegIndex");
3903}
3904
3905// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3906// to get the SectionInfo.
3907const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
3908 int32_t SegIndex, uint64_t SegOffset) {
3909 for (const SectionInfo &SI : Sections) {
3910 if (SI.SegmentIndex != SegIndex)
3911 continue;
3912 if (SI.OffsetInSegment > SegOffset)
3913 continue;
3914 if (SegOffset >= (SI.OffsetInSegment + SI.Size))
3915 continue;
3916 return SI;
3917 }
3918 llvm_unreachable("SegIndex and SegOffset not in any section");
3919}
3920
3921// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3922// entry to get the section name.
3923StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
3924 uint64_t SegOffset) {
3925 return findSection(SegIndex, SegOffset).SectionName;
3926}
3927
3928// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3929// entry to get the address.
3930uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
3931 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
3932 return SI.SegmentStartAddress + OffsetInSeg;
3933}
3934
Nick Kledzik56ebef42014-09-16 01:41:51 +00003935iterator_range<bind_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003936MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003937 ArrayRef<uint8_t> Opcodes, bool is64,
Nick Kledzik56ebef42014-09-16 01:41:51 +00003938 MachOBindEntry::Kind BKind) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003939 if (O->BindRebaseSectionTable == nullptr)
3940 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003941 MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003942 Start.moveToFirst();
3943
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003944 MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003945 Finish.moveToEnd();
3946
Craig Topper15576e12015-12-06 05:08:07 +00003947 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00003948}
3949
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003950iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003951 return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00003952 MachOBindEntry::Kind::Regular);
3953}
3954
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003955iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003956 return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00003957 MachOBindEntry::Kind::Lazy);
3958}
3959
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003960iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003961 return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00003962 MachOBindEntry::Kind::Weak);
3963}
3964
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00003965MachOObjectFile::load_command_iterator
3966MachOObjectFile::begin_load_commands() const {
3967 return LoadCommands.begin();
3968}
3969
3970MachOObjectFile::load_command_iterator
3971MachOObjectFile::end_load_commands() const {
3972 return LoadCommands.end();
3973}
3974
3975iterator_range<MachOObjectFile::load_command_iterator>
3976MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00003977 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00003978}
3979
Rafael Espindola56f976f2013-04-18 18:08:55 +00003980StringRef
3981MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
3982 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
3983 return parseSegmentOrSectionName(Raw.data());
3984}
3985
3986ArrayRef<char>
3987MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00003988 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003989 const section_base *Base =
3990 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00003991 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003992}
3993
3994ArrayRef<char>
3995MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00003996 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003997 const section_base *Base =
3998 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00003999 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004000}
4001
4002bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00004003MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00004004 const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004005 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00004006 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00004007 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004008}
4009
Eric Christopher1d62c252013-07-22 22:25:07 +00004010unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004011 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004012 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00004013 return RE.r_word1 & 0xffffff;
4014 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004015}
4016
Eric Christopher1d62c252013-07-22 22:25:07 +00004017bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004018 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004019 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00004020 return (RE.r_word1 >> 27) & 1;
4021 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004022}
4023
Eric Christopher1d62c252013-07-22 22:25:07 +00004024bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004025 const MachO::any_relocation_info &RE) const {
4026 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004027}
4028
Eric Christopher1d62c252013-07-22 22:25:07 +00004029uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004030 const MachO::any_relocation_info &RE) const {
4031 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004032}
4033
Kevin Enderby9907d0a2014-11-04 00:43:16 +00004034uint32_t MachOObjectFile::getScatteredRelocationType(
4035 const MachO::any_relocation_info &RE) const {
4036 return (RE.r_word0 >> 24) & 0xf;
4037}
4038
Eric Christopher1d62c252013-07-22 22:25:07 +00004039unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004040 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004041 if (isRelocationScattered(RE))
4042 return getScatteredRelocationAddress(RE);
4043 return getPlainRelocationAddress(RE);
4044}
4045
Charles Davis8bdfafd2013-09-01 04:28:48 +00004046unsigned MachOObjectFile::getAnyRelocationPCRel(
4047 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004048 if (isRelocationScattered(RE))
Lang Hames697e7cd2016-12-04 01:56:10 +00004049 return getScatteredRelocationPCRel(RE);
4050 return getPlainRelocationPCRel(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004051}
4052
Eric Christopher1d62c252013-07-22 22:25:07 +00004053unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004054 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004055 if (isRelocationScattered(RE))
4056 return getScatteredRelocationLength(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00004057 return getPlainRelocationLength(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004058}
4059
4060unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00004061MachOObjectFile::getAnyRelocationType(
4062 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004063 if (isRelocationScattered(RE))
4064 return getScatteredRelocationType(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00004065 return getPlainRelocationType(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004066}
4067
Rafael Espindola52501032013-04-30 15:40:54 +00004068SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00004069MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004070 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00004071 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00004072 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00004073 unsigned SecNum = getPlainRelocationSymbolNum(RE);
4074 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
4075 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00004076 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00004077 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00004078 return SectionRef(DRI, this);
4079}
4080
Charles Davis8bdfafd2013-09-01 04:28:48 +00004081MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00004082 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00004083 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004084}
4085
Charles Davis8bdfafd2013-09-01 04:28:48 +00004086MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00004087 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00004088 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004089}
4090
Charles Davis8bdfafd2013-09-01 04:28:48 +00004091MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00004092 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004093 const char *Sec = getSectionPtr(*this, L, Index);
4094 return getStruct<MachO::section>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004095}
4096
Charles Davis8bdfafd2013-09-01 04:28:48 +00004097MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4098 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004099 const char *Sec = getSectionPtr(*this, L, Index);
4100 return getStruct<MachO::section_64>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004101}
4102
Charles Davis8bdfafd2013-09-01 04:28:48 +00004103MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00004104MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00004105 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004106 return getStruct<MachO::nlist>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004107}
4108
Charles Davis8bdfafd2013-09-01 04:28:48 +00004109MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00004110MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00004111 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004112 return getStruct<MachO::nlist_64>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004113}
4114
Charles Davis8bdfafd2013-09-01 04:28:48 +00004115MachO::linkedit_data_command
4116MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004117 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004118}
4119
Charles Davis8bdfafd2013-09-01 04:28:48 +00004120MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00004121MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004122 return getStruct<MachO::segment_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004123}
4124
Charles Davis8bdfafd2013-09-01 04:28:48 +00004125MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00004126MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004127 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004128}
4129
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00004130MachO::linker_option_command
4131MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004132 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004133}
4134
Jim Grosbach448334a2014-03-18 22:09:05 +00004135MachO::version_min_command
4136MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004137 return getStruct<MachO::version_min_command>(*this, L.Ptr);
Jim Grosbach448334a2014-03-18 22:09:05 +00004138}
4139
Kevin Enderbya4579c42017-01-19 17:36:31 +00004140MachO::note_command
4141MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
4142 return getStruct<MachO::note_command>(*this, L.Ptr);
4143}
4144
Steven Wu5b54a422017-01-23 20:07:55 +00004145MachO::build_version_command
4146MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
4147 return getStruct<MachO::build_version_command>(*this, L.Ptr);
4148}
4149
4150MachO::build_tool_version
4151MachOObjectFile::getBuildToolVersion(unsigned index) const {
4152 return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
4153}
4154
Tim Northover8f9590b2014-06-30 14:40:57 +00004155MachO::dylib_command
4156MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004157 return getStruct<MachO::dylib_command>(*this, L.Ptr);
Tim Northover8f9590b2014-06-30 14:40:57 +00004158}
4159
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004160MachO::dyld_info_command
4161MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004162 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004163}
4164
4165MachO::dylinker_command
4166MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004167 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004168}
4169
4170MachO::uuid_command
4171MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004172 return getStruct<MachO::uuid_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004173}
4174
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004175MachO::rpath_command
4176MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004177 return getStruct<MachO::rpath_command>(*this, L.Ptr);
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004178}
4179
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004180MachO::source_version_command
4181MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004182 return getStruct<MachO::source_version_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004183}
4184
4185MachO::entry_point_command
4186MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004187 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004188}
4189
Kevin Enderby0804f4672014-12-16 23:25:52 +00004190MachO::encryption_info_command
4191MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004192 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
Kevin Enderby0804f4672014-12-16 23:25:52 +00004193}
4194
Kevin Enderby57538292014-12-17 01:01:30 +00004195MachO::encryption_info_command_64
4196MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004197 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
Kevin Enderby57538292014-12-17 01:01:30 +00004198}
4199
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004200MachO::sub_framework_command
4201MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004202 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004203}
Tim Northover8f9590b2014-06-30 14:40:57 +00004204
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004205MachO::sub_umbrella_command
4206MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004207 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004208}
4209
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004210MachO::sub_library_command
4211MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004212 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004213}
4214
Kevin Enderby186eac32014-12-19 21:06:24 +00004215MachO::sub_client_command
4216MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004217 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
Kevin Enderby186eac32014-12-19 21:06:24 +00004218}
4219
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004220MachO::routines_command
4221MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004222 return getStruct<MachO::routines_command>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004223}
4224
4225MachO::routines_command_64
4226MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004227 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004228}
4229
Kevin Enderby48ef5342014-12-23 22:56:39 +00004230MachO::thread_command
4231MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004232 return getStruct<MachO::thread_command>(*this, L.Ptr);
Kevin Enderby48ef5342014-12-23 22:56:39 +00004233}
4234
Charles Davis8bdfafd2013-09-01 04:28:48 +00004235MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00004236MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00004237 uint32_t Offset;
Kevin Enderbyabf10f22017-06-22 17:41:22 +00004238 if (getHeader().filetype == MachO::MH_OBJECT) {
4239 DataRefImpl Sec;
4240 Sec.d.a = Rel.d.a;
4241 if (is64Bit()) {
4242 MachO::section_64 Sect = getSection64(Sec);
4243 Offset = Sect.reloff;
4244 } else {
4245 MachO::section Sect = getSection(Sec);
4246 Offset = Sect.reloff;
4247 }
Rafael Espindola128b8112014-04-03 23:51:28 +00004248 } else {
Kevin Enderbyabf10f22017-06-22 17:41:22 +00004249 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
4250 Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
Rafael Espindola128b8112014-04-03 23:51:28 +00004251 }
4252
4253 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004254 getPtr(*this, Offset)) + Rel.d.b;
Rafael Espindola128b8112014-04-03 23:51:28 +00004255 return getStruct<MachO::any_relocation_info>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004256 *this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00004257}
4258
Charles Davis8bdfafd2013-09-01 04:28:48 +00004259MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00004260MachOObjectFile::getDice(DataRefImpl Rel) const {
4261 const char *P = reinterpret_cast<const char *>(Rel.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004262 return getStruct<MachO::data_in_code_entry>(*this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00004263}
4264
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004265const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00004266 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004267}
4268
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004269const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4270 assert(is64Bit());
4271 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004272}
4273
Charles Davis8bdfafd2013-09-01 04:28:48 +00004274uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4275 const MachO::dysymtab_command &DLC,
4276 unsigned Index) const {
4277 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
Lang Hames697e7cd2016-12-04 01:56:10 +00004278 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004279}
4280
Charles Davis8bdfafd2013-09-01 04:28:48 +00004281MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00004282MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4283 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004284 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
Lang Hames697e7cd2016-12-04 01:56:10 +00004285 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004286}
4287
Charles Davis8bdfafd2013-09-01 04:28:48 +00004288MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004289 if (SymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004290 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004291
4292 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4293 MachO::symtab_command Cmd;
4294 Cmd.cmd = MachO::LC_SYMTAB;
4295 Cmd.cmdsize = sizeof(MachO::symtab_command);
4296 Cmd.symoff = 0;
4297 Cmd.nsyms = 0;
4298 Cmd.stroff = 0;
4299 Cmd.strsize = 0;
4300 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004301}
4302
Charles Davis8bdfafd2013-09-01 04:28:48 +00004303MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004304 if (DysymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004305 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004306
4307 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4308 MachO::dysymtab_command Cmd;
4309 Cmd.cmd = MachO::LC_DYSYMTAB;
4310 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4311 Cmd.ilocalsym = 0;
4312 Cmd.nlocalsym = 0;
4313 Cmd.iextdefsym = 0;
4314 Cmd.nextdefsym = 0;
4315 Cmd.iundefsym = 0;
4316 Cmd.nundefsym = 0;
4317 Cmd.tocoff = 0;
4318 Cmd.ntoc = 0;
4319 Cmd.modtaboff = 0;
4320 Cmd.nmodtab = 0;
4321 Cmd.extrefsymoff = 0;
4322 Cmd.nextrefsyms = 0;
4323 Cmd.indirectsymoff = 0;
4324 Cmd.nindirectsyms = 0;
4325 Cmd.extreloff = 0;
4326 Cmd.nextrel = 0;
4327 Cmd.locreloff = 0;
4328 Cmd.nlocrel = 0;
4329 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004330}
4331
Charles Davis8bdfafd2013-09-01 04:28:48 +00004332MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00004333MachOObjectFile::getDataInCodeLoadCommand() const {
4334 if (DataInCodeLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004335 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00004336
4337 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00004338 MachO::linkedit_data_command Cmd;
4339 Cmd.cmd = MachO::LC_DATA_IN_CODE;
4340 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4341 Cmd.dataoff = 0;
4342 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00004343 return Cmd;
4344}
4345
Kevin Enderby9a509442015-01-27 21:28:24 +00004346MachO::linkedit_data_command
4347MachOObjectFile::getLinkOptHintsLoadCommand() const {
4348 if (LinkOptHintsLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004349 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
Kevin Enderby9a509442015-01-27 21:28:24 +00004350
4351 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4352 // fields.
4353 MachO::linkedit_data_command Cmd;
4354 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4355 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4356 Cmd.dataoff = 0;
4357 Cmd.datasize = 0;
4358 return Cmd;
4359}
4360
Nick Kledzikd04bc352014-08-30 00:20:14 +00004361ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004362 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004363 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004364
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004365 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004366 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004367 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004368 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00004369 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004370}
4371
4372ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004373 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004374 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004375
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004376 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004377 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004378 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004379 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004380 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004381}
4382
4383ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004384 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004385 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004386
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004387 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004388 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004389 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004390 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004391 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004392}
4393
4394ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004395 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004396 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004397
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004398 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004399 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004400 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004401 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004402 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004403}
4404
4405ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004406 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004407 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004408
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004409 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004410 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004411 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004412 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00004413 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004414}
4415
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004416ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
4417 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004418 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00004419 // Returning a pointer is fine as uuid doesn't need endian swapping.
4420 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00004421 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004422}
Nick Kledzikd04bc352014-08-30 00:20:14 +00004423
Rafael Espindola6e040c02013-04-26 20:07:33 +00004424StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004425 MachO::symtab_command S = getSymtabLoadCommand();
4426 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004427}
4428
Rafael Espindola56f976f2013-04-18 18:08:55 +00004429bool MachOObjectFile::is64Bit() const {
4430 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00004431 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004432}
4433
4434void MachOObjectFile::ReadULEB128s(uint64_t Index,
4435 SmallVectorImpl<uint64_t> &Out) const {
4436 DataExtractor extractor(ObjectFile::getData(), true, 0);
4437
4438 uint32_t offset = Index;
4439 uint64_t data = 0;
4440 while (uint64_t delta = extractor.getULEB128(&offset)) {
4441 data += delta;
4442 Out.push_back(data);
4443 }
4444}
4445
Rafael Espindolac66d7612014-08-17 19:09:37 +00004446bool MachOObjectFile::isRelocatableObject() const {
4447 return getHeader().filetype == MachO::MH_OBJECT;
4448}
4449
Lang Hamesff044b12016-03-25 23:11:52 +00004450Expected<std::unique_ptr<MachOObjectFile>>
Kevin Enderby79d6c632016-10-24 21:15:11 +00004451ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4452 uint32_t UniversalCputype,
4453 uint32_t UniversalIndex) {
Rafael Espindola48af1c22014-08-19 18:44:46 +00004454 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00004455 if (Magic == "\xFE\xED\xFA\xCE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004456 return MachOObjectFile::create(Buffer, false, false,
4457 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004458 if (Magic == "\xCE\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004459 return MachOObjectFile::create(Buffer, true, false,
4460 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004461 if (Magic == "\xFE\xED\xFA\xCF")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004462 return MachOObjectFile::create(Buffer, false, true,
4463 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004464 if (Magic == "\xCF\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004465 return MachOObjectFile::create(Buffer, true, true,
4466 UniversalCputype, UniversalIndex);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00004467 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00004468 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004469}
Wolfgang Pieb77d3e932017-06-06 01:22:34 +00004470
4471StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
4472 return StringSwitch<StringRef>(Name)
4473 .Case("debug_str_offs", "debug_str_offsets")
4474 .Default(Name);
4475}