blob: a32533b003b28e4300f44489444f94cb23b77fd9 [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/StringRef.h"
Rafael Espindola72318b42014-08-08 16:30:17 +000020#include "llvm/ADT/StringSwitch.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/ADT/Triple.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000022#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/MachO.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000024#include "llvm/Object/Error.h"
25#include "llvm/Object/MachO.h"
26#include "llvm/Object/ObjectFile.h"
27#include "llvm/Object/SymbolicFile.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000028#include "llvm/Support/DataExtractor.h"
Nick Kledzikac431442014-09-12 21:34:15 +000029#include "llvm/Support/Debug.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000030#include "llvm/Support/Error.h"
31#include "llvm/Support/ErrorHandling.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000032#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000033#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000034#include "llvm/Support/LEB128.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000035#include "llvm/Support/MemoryBuffer.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000036#include "llvm/Support/SwapByteOrder.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000037#include "llvm/Support/raw_ostream.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000038#include <algorithm>
39#include <cassert>
40#include <cstddef>
41#include <cstdint>
Eric Christopher7b015c72011-04-22 03:19:48 +000042#include <cstring>
43#include <limits>
Kevin Enderbyd5039402016-10-31 20:29:48 +000044#include <list>
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000045#include <memory>
46#include <string>
47#include <system_error>
Eric Christopher7b015c72011-04-22 03:19:48 +000048
49using namespace llvm;
50using namespace object;
51
Artyom Skrobov7d602f72014-07-20 12:08:28 +000052namespace {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000053
Artyom Skrobov7d602f72014-07-20 12:08:28 +000054 struct section_base {
55 char sectname[16];
56 char segname[16];
57 };
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000058
59} // end anonymous namespace
Rafael Espindola56f976f2013-04-18 18:08:55 +000060
Benjamin Kramer760e00b2017-08-20 15:13:39 +000061static Error malformedError(const Twine &Msg) {
62 return make_error<GenericBinaryError>("truncated or malformed object (" +
63 Msg + ")",
Kevin Enderby89134962016-05-05 23:41:05 +000064 object_error::parse_failed);
Lang Hames9e964f32016-03-25 17:25:34 +000065}
66
Alexey Samsonov9f336632015-06-04 19:45:22 +000067// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000068template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000069static T getStruct(const MachOObjectFile &O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000070 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000071 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Filipe Cabecinhas40139502015-01-15 22:52:38 +000072 report_fatal_error("Malformed MachO file.");
73
Rafael Espindola3cdeb172013-04-19 13:45:05 +000074 T Cmd;
75 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000076 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000077 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000078 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000079}
80
Alexey Samsonov9f336632015-06-04 19:45:22 +000081template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000082static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000083 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000084 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000085 return malformedError("Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000086
87 T Cmd;
88 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000089 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Alexey Samsonov9f336632015-06-04 19:45:22 +000090 MachO::swapStruct(Cmd);
91 return Cmd;
92}
93
Rafael Espindola6e040c02013-04-26 20:07:33 +000094static const char *
Lang Hames697e7cd2016-12-04 01:56:10 +000095getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
Rafael Espindola6e040c02013-04-26 20:07:33 +000096 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000097 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
98
Lang Hames697e7cd2016-12-04 01:56:10 +000099 bool Is64 = O.is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +0000100 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
101 sizeof(MachO::segment_command);
102 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
103 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000104
105 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +0000106 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +0000107}
108
Lang Hames697e7cd2016-12-04 01:56:10 +0000109static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
110 return O.getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +0000111}
112
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000113static MachO::nlist_base
Lang Hames697e7cd2016-12-04 01:56:10 +0000114getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +0000115 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000116 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +0000117}
118
Rafael Espindola56f976f2013-04-18 18:08:55 +0000119static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000120 if (P[15] == 0)
121 // Null terminated.
122 return P;
123 // Not null terminated, so this is a 16 char string.
124 return StringRef(P, 16);
125}
126
Lang Hames697e7cd2016-12-04 01:56:10 +0000127static unsigned getCPUType(const MachOObjectFile &O) {
128 return O.getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000129}
130
Charles Davis8bdfafd2013-09-01 04:28:48 +0000131static uint32_t
132getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
133 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000134}
135
136static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000137getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
138 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000139}
140
Lang Hames697e7cd2016-12-04 01:56:10 +0000141static bool getPlainRelocationPCRel(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000142 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000143 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000144 return (RE.r_word1 >> 24) & 1;
145 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000146}
147
148static bool
Lang Hames697e7cd2016-12-04 01:56:10 +0000149getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000150 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000151}
152
Lang Hames697e7cd2016-12-04 01:56:10 +0000153static unsigned getPlainRelocationLength(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000154 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000155 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000156 return (RE.r_word1 >> 25) & 3;
157 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000158}
159
160static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000161getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
162 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000163}
164
Lang Hames697e7cd2016-12-04 01:56:10 +0000165static unsigned getPlainRelocationType(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000166 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000167 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000168 return RE.r_word1 >> 28;
169 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000170}
171
Lang Hames697e7cd2016-12-04 01:56:10 +0000172static uint32_t getSectionFlags(const MachOObjectFile &O,
Rafael Espindola56f976f2013-04-18 18:08:55 +0000173 DataRefImpl Sec) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000174 if (O.is64Bit()) {
175 MachO::section_64 Sect = O.getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000176 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000177 }
Lang Hames697e7cd2016-12-04 01:56:10 +0000178 MachO::section Sect = O.getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000179 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000180}
181
Lang Hames9e964f32016-03-25 17:25:34 +0000182static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000183getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000184 uint32_t LoadCommandIndex) {
Lang Hames9e964f32016-03-25 17:25:34 +0000185 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
186 if (CmdOrErr->cmdsize < 8)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000187 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000188 " with size less than 8 bytes");
Lang Hames9e964f32016-03-25 17:25:34 +0000189 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
190 } else
191 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000192}
193
Lang Hames9e964f32016-03-25 17:25:34 +0000194static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000195getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
196 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
197 : sizeof(MachO::mach_header);
198 if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000199 return malformedError("load command 0 extends past the end all load "
Kevin Enderby89134962016-05-05 23:41:05 +0000200 "commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000201 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000202}
203
Lang Hames9e964f32016-03-25 17:25:34 +0000204static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000205getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000206 const MachOObjectFile::LoadCommandInfo &L) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000207 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
208 : sizeof(MachO::mach_header);
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000209 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
Lang Hames697e7cd2016-12-04 01:56:10 +0000210 Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000211 return malformedError("load command " + Twine(LoadCommandIndex + 1) +
Kevin Enderby89134962016-05-05 23:41:05 +0000212 " extends past the end all load commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000213 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000214}
215
Alexey Samsonov9f336632015-06-04 19:45:22 +0000216template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +0000217static void parseHeader(const MachOObjectFile &Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000218 Error &Err) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000219 if (sizeof(T) > Obj.getData().size()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000220 Err = malformedError("the mach header extends past the end of the "
Kevin Enderby89134962016-05-05 23:41:05 +0000221 "file");
Kevin Enderby87025742016-04-13 21:17:58 +0000222 return;
223 }
Lang Hames9e964f32016-03-25 17:25:34 +0000224 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
225 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000226 else
Lang Hames9e964f32016-03-25 17:25:34 +0000227 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000228}
229
Kevin Enderbyd5039402016-10-31 20:29:48 +0000230// This is used to check for overlapping of Mach-O elements.
231struct MachOElement {
232 uint64_t Offset;
233 uint64_t Size;
234 const char *Name;
235};
236
237static Error checkOverlappingElement(std::list<MachOElement> &Elements,
238 uint64_t Offset, uint64_t Size,
239 const char *Name) {
240 if (Size == 0)
241 return Error::success();
242
243 for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
244 auto E = *it;
245 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
246 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
247 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
248 return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
249 " with a size of " + Twine(Size) + ", overlaps " +
250 E.Name + " at offset " + Twine(E.Offset) + " with "
251 "a size of " + Twine(E.Size));
252 auto nt = it;
253 nt++;
254 if (nt != Elements.end()) {
255 auto N = *nt;
256 if (Offset + Size <= N.Offset) {
257 Elements.insert(nt, {Offset, Size, Name});
258 return Error::success();
259 }
260 }
261 }
262 Elements.push_back({Offset, Size, Name});
263 return Error::success();
264}
265
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000266// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
267// sections to \param Sections, and optionally sets
268// \param IsPageZeroSegment to true.
Kevin Enderbyc614d282016-08-12 20:10:25 +0000269template <typename Segment, typename Section>
Lang Hames9e964f32016-03-25 17:25:34 +0000270static Error parseSegmentLoadCommand(
Lang Hames697e7cd2016-12-04 01:56:10 +0000271 const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000272 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000273 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
274 std::list<MachOElement> &Elements) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000275 const unsigned SegmentLoadSize = sizeof(Segment);
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000276 if (Load.C.cmdsize < SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000277 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000278 " " + CmdName + " cmdsize too small");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000279 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
280 Segment S = SegOrErr.get();
281 const unsigned SectionSize = sizeof(Section);
Lang Hames697e7cd2016-12-04 01:56:10 +0000282 uint64_t FileSize = Obj.getData().size();
Lang Hames9e964f32016-03-25 17:25:34 +0000283 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
284 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000285 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000286 " inconsistent cmdsize in " + CmdName +
Kevin Enderby89134962016-05-05 23:41:05 +0000287 " for the number of sections");
Lang Hames9e964f32016-03-25 17:25:34 +0000288 for (unsigned J = 0; J < S.nsects; ++J) {
289 const char *Sec = getSectionPtr(Obj, Load, J);
290 Sections.push_back(Sec);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000291 Section s = getStruct<Section>(Obj, Sec);
Lang Hames697e7cd2016-12-04 01:56:10 +0000292 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
293 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000294 s.flags != MachO::S_ZEROFILL &&
295 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
296 s.offset > FileSize)
297 return malformedError("offset field of section " + Twine(J) + " in " +
298 CmdName + " command " + Twine(LoadCommandIndex) +
299 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000300 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
301 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000302 s.flags != MachO::S_ZEROFILL &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000303 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
304 s.offset < SizeOfHeaders && s.size != 0)
Kevin Enderbyc614d282016-08-12 20:10:25 +0000305 return malformedError("offset field of section " + Twine(J) + " in " +
306 CmdName + " command " + Twine(LoadCommandIndex) +
307 " not past the headers of the file");
308 uint64_t BigSize = s.offset;
309 BigSize += s.size;
Lang Hames697e7cd2016-12-04 01:56:10 +0000310 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
311 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000312 s.flags != MachO::S_ZEROFILL &&
313 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
314 BigSize > FileSize)
315 return malformedError("offset field plus size field of section " +
316 Twine(J) + " in " + CmdName + " command " +
317 Twine(LoadCommandIndex) +
318 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000319 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
320 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000321 s.flags != MachO::S_ZEROFILL &&
322 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
323 s.size > S.filesize)
324 return malformedError("size field of section " +
325 Twine(J) + " in " + CmdName + " command " +
326 Twine(LoadCommandIndex) +
327 " greater than the segment");
Lang Hames697e7cd2016-12-04 01:56:10 +0000328 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
329 Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000330 s.addr < S.vmaddr)
331 return malformedError("addr field of section " + Twine(J) + " in " +
332 CmdName + " command " + Twine(LoadCommandIndex) +
333 " less than the segment's vmaddr");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000334 BigSize = s.addr;
335 BigSize += s.size;
336 uint64_t BigEnd = S.vmaddr;
337 BigEnd += S.vmsize;
338 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000339 return malformedError("addr field plus size of section " + Twine(J) +
340 " in " + CmdName + " command " +
341 Twine(LoadCommandIndex) +
342 " greater than than "
Kevin Enderbyc614d282016-08-12 20:10:25 +0000343 "the segment's vmaddr plus vmsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000344 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
345 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000346 s.flags != MachO::S_ZEROFILL &&
347 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
348 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
349 "section contents"))
350 return Err;
Kevin Enderbyc614d282016-08-12 20:10:25 +0000351 if (s.reloff > FileSize)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000352 return malformedError("reloff field of section " + Twine(J) + " in " +
353 CmdName + " command " + Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000354 " extends past the end of the file");
355 BigSize = s.nreloc;
356 BigSize *= sizeof(struct MachO::relocation_info);
357 BigSize += s.reloff;
358 if (BigSize > FileSize)
359 return malformedError("reloff field plus nreloc field times sizeof("
360 "struct relocation_info) of section " +
361 Twine(J) + " in " + CmdName + " command " +
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000362 Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000363 " extends past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000364 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
365 sizeof(struct
366 MachO::relocation_info),
367 "section relocation entries"))
368 return Err;
Lang Hames9e964f32016-03-25 17:25:34 +0000369 }
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000370 if (S.fileoff > FileSize)
371 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000372 " fileoff field in " + CmdName +
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000373 " extends past the end of the file");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000374 uint64_t BigSize = S.fileoff;
375 BigSize += S.filesize;
376 if (BigSize > FileSize)
377 return malformedError("load command " + Twine(LoadCommandIndex) +
378 " fileoff field plus filesize field in " +
379 CmdName + " extends past the end of the file");
380 if (S.vmsize != 0 && S.filesize > S.vmsize)
381 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby86d8bd12017-02-07 21:20:44 +0000382 " filesize field in " + CmdName +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000383 " greater than vmsize field");
Lang Hames9e964f32016-03-25 17:25:34 +0000384 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
385 } else
386 return SegOrErr.takeError();
387
388 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000389}
390
Lang Hames697e7cd2016-12-04 01:56:10 +0000391static Error checkSymtabCommand(const MachOObjectFile &Obj,
Kevin Enderby0e52c922016-08-26 19:34:07 +0000392 const MachOObjectFile::LoadCommandInfo &Load,
393 uint32_t LoadCommandIndex,
Kevin Enderbyd5039402016-10-31 20:29:48 +0000394 const char **SymtabLoadCmd,
395 std::list<MachOElement> &Elements) {
Kevin Enderby0e52c922016-08-26 19:34:07 +0000396 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
397 return malformedError("load command " + Twine(LoadCommandIndex) +
398 " LC_SYMTAB cmdsize too small");
399 if (*SymtabLoadCmd != nullptr)
400 return malformedError("more than one LC_SYMTAB command");
401 MachO::symtab_command Symtab =
402 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
403 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
404 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
405 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000406 uint64_t FileSize = Obj.getData().size();
Kevin Enderby0e52c922016-08-26 19:34:07 +0000407 if (Symtab.symoff > FileSize)
408 return malformedError("symoff field of LC_SYMTAB command " +
409 Twine(LoadCommandIndex) + " extends past the end "
410 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000411 uint64_t SymtabSize = Symtab.nsyms;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000412 const char *struct_nlist_name;
Lang Hames697e7cd2016-12-04 01:56:10 +0000413 if (Obj.is64Bit()) {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000414 SymtabSize *= sizeof(MachO::nlist_64);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000415 struct_nlist_name = "struct nlist_64";
416 } else {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000417 SymtabSize *= sizeof(MachO::nlist);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000418 struct_nlist_name = "struct nlist";
419 }
Kevin Enderbyd5039402016-10-31 20:29:48 +0000420 uint64_t BigSize = SymtabSize;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000421 BigSize += Symtab.symoff;
422 if (BigSize > FileSize)
423 return malformedError("symoff field plus nsyms field times sizeof(" +
424 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
425 Twine(LoadCommandIndex) + " extends past the end "
426 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000427 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
428 "symbol table"))
429 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000430 if (Symtab.stroff > FileSize)
431 return malformedError("stroff field of LC_SYMTAB command " +
432 Twine(LoadCommandIndex) + " extends past the end "
433 "of the file");
434 BigSize = Symtab.stroff;
435 BigSize += Symtab.strsize;
436 if (BigSize > FileSize)
437 return malformedError("stroff field plus strsize field of LC_SYMTAB "
438 "command " + Twine(LoadCommandIndex) + " extends "
439 "past the end of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000440 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
441 Symtab.strsize, "string table"))
442 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000443 *SymtabLoadCmd = Load.Ptr;
444 return Error::success();
445}
446
Lang Hames697e7cd2016-12-04 01:56:10 +0000447static Error checkDysymtabCommand(const MachOObjectFile &Obj,
448 const MachOObjectFile::LoadCommandInfo &Load,
449 uint32_t LoadCommandIndex,
450 const char **DysymtabLoadCmd,
451 std::list<MachOElement> &Elements) {
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000452 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
453 return malformedError("load command " + Twine(LoadCommandIndex) +
454 " LC_DYSYMTAB cmdsize too small");
455 if (*DysymtabLoadCmd != nullptr)
456 return malformedError("more than one LC_DYSYMTAB command");
457 MachO::dysymtab_command Dysymtab =
458 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
459 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
460 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
461 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000462 uint64_t FileSize = Obj.getData().size();
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000463 if (Dysymtab.tocoff > FileSize)
464 return malformedError("tocoff field of LC_DYSYMTAB command " +
465 Twine(LoadCommandIndex) + " extends past the end of "
466 "the file");
467 uint64_t BigSize = Dysymtab.ntoc;
468 BigSize *= sizeof(MachO::dylib_table_of_contents);
469 BigSize += Dysymtab.tocoff;
470 if (BigSize > FileSize)
471 return malformedError("tocoff field plus ntoc field times sizeof(struct "
472 "dylib_table_of_contents) of LC_DYSYMTAB command " +
473 Twine(LoadCommandIndex) + " extends past the end of "
474 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000475 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
476 Dysymtab.ntoc * sizeof(struct
477 MachO::dylib_table_of_contents),
478 "table of contents"))
479 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000480 if (Dysymtab.modtaboff > FileSize)
481 return malformedError("modtaboff field of LC_DYSYMTAB command " +
482 Twine(LoadCommandIndex) + " extends past the end of "
483 "the file");
484 BigSize = Dysymtab.nmodtab;
485 const char *struct_dylib_module_name;
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000486 uint64_t sizeof_modtab;
Lang Hames697e7cd2016-12-04 01:56:10 +0000487 if (Obj.is64Bit()) {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000488 sizeof_modtab = sizeof(MachO::dylib_module_64);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000489 struct_dylib_module_name = "struct dylib_module_64";
490 } else {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000491 sizeof_modtab = sizeof(MachO::dylib_module);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000492 struct_dylib_module_name = "struct dylib_module";
493 }
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000494 BigSize *= sizeof_modtab;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000495 BigSize += Dysymtab.modtaboff;
496 if (BigSize > FileSize)
497 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
498 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
499 "command " + Twine(LoadCommandIndex) + " extends "
500 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000501 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
502 Dysymtab.nmodtab * sizeof_modtab,
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000503 "module table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000504 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000505 if (Dysymtab.extrefsymoff > FileSize)
506 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
507 Twine(LoadCommandIndex) + " extends past the end of "
508 "the file");
509 BigSize = Dysymtab.nextrefsyms;
510 BigSize *= sizeof(MachO::dylib_reference);
511 BigSize += Dysymtab.extrefsymoff;
512 if (BigSize > FileSize)
513 return malformedError("extrefsymoff field plus nextrefsyms field times "
514 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
515 "command " + Twine(LoadCommandIndex) + " extends "
516 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000517 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
518 Dysymtab.nextrefsyms *
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000519 sizeof(MachO::dylib_reference),
520 "reference table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000521 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000522 if (Dysymtab.indirectsymoff > FileSize)
523 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
524 Twine(LoadCommandIndex) + " extends past the end of "
525 "the file");
526 BigSize = Dysymtab.nindirectsyms;
527 BigSize *= sizeof(uint32_t);
528 BigSize += Dysymtab.indirectsymoff;
529 if (BigSize > FileSize)
530 return malformedError("indirectsymoff field plus nindirectsyms field times "
531 "sizeof(uint32_t) of LC_DYSYMTAB command " +
532 Twine(LoadCommandIndex) + " extends past the end of "
533 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000534 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
535 Dysymtab.nindirectsyms *
536 sizeof(uint32_t),
537 "indirect table"))
538 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000539 if (Dysymtab.extreloff > FileSize)
540 return malformedError("extreloff field of LC_DYSYMTAB command " +
541 Twine(LoadCommandIndex) + " extends past the end of "
542 "the file");
543 BigSize = Dysymtab.nextrel;
544 BigSize *= sizeof(MachO::relocation_info);
545 BigSize += Dysymtab.extreloff;
546 if (BigSize > FileSize)
547 return malformedError("extreloff field plus nextrel field times sizeof"
548 "(struct relocation_info) of LC_DYSYMTAB command " +
549 Twine(LoadCommandIndex) + " extends past the end of "
550 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000551 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
552 Dysymtab.nextrel *
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000553 sizeof(MachO::relocation_info),
554 "external relocation table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000555 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000556 if (Dysymtab.locreloff > FileSize)
557 return malformedError("locreloff field of LC_DYSYMTAB command " +
558 Twine(LoadCommandIndex) + " extends past the end of "
559 "the file");
560 BigSize = Dysymtab.nlocrel;
561 BigSize *= sizeof(MachO::relocation_info);
562 BigSize += Dysymtab.locreloff;
563 if (BigSize > FileSize)
564 return malformedError("locreloff field plus nlocrel field times sizeof"
565 "(struct relocation_info) of LC_DYSYMTAB command " +
566 Twine(LoadCommandIndex) + " extends past the end of "
567 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000568 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
569 Dysymtab.nlocrel *
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000570 sizeof(MachO::relocation_info),
571 "local relocation table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000572 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000573 *DysymtabLoadCmd = Load.Ptr;
574 return Error::success();
575}
576
Lang Hames697e7cd2016-12-04 01:56:10 +0000577static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000578 const MachOObjectFile::LoadCommandInfo &Load,
579 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000580 const char **LoadCmd, const char *CmdName,
581 std::list<MachOElement> &Elements,
582 const char *ElementName) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000583 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
584 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
585 CmdName + " cmdsize too small");
586 if (*LoadCmd != nullptr)
587 return malformedError("more than one " + Twine(CmdName) + " command");
588 MachO::linkedit_data_command LinkData =
589 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
590 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
591 return malformedError(Twine(CmdName) + " command " +
592 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000593 uint64_t FileSize = Obj.getData().size();
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000594 if (LinkData.dataoff > FileSize)
595 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
596 Twine(LoadCommandIndex) + " extends past the end of "
597 "the file");
598 uint64_t BigSize = LinkData.dataoff;
599 BigSize += LinkData.datasize;
600 if (BigSize > FileSize)
601 return malformedError("dataoff field plus datasize field of " +
602 Twine(CmdName) + " command " +
603 Twine(LoadCommandIndex) + " extends past the end of "
604 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000605 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
606 LinkData.datasize, ElementName))
607 return Err;
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000608 *LoadCmd = Load.Ptr;
609 return Error::success();
610}
611
Lang Hames697e7cd2016-12-04 01:56:10 +0000612static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000613 const MachOObjectFile::LoadCommandInfo &Load,
614 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000615 const char **LoadCmd, const char *CmdName,
616 std::list<MachOElement> &Elements) {
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000617 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
618 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
619 CmdName + " cmdsize too small");
620 if (*LoadCmd != nullptr)
621 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
622 "command");
623 MachO::dyld_info_command DyldInfo =
624 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
625 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
626 return malformedError(Twine(CmdName) + " command " +
627 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000628 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000629 if (DyldInfo.rebase_off > FileSize)
630 return malformedError("rebase_off field of " + Twine(CmdName) +
631 " command " + Twine(LoadCommandIndex) + " extends "
632 "past the end of the file");
633 uint64_t BigSize = DyldInfo.rebase_off;
634 BigSize += DyldInfo.rebase_size;
635 if (BigSize > FileSize)
636 return malformedError("rebase_off field plus rebase_size field of " +
637 Twine(CmdName) + " command " +
638 Twine(LoadCommandIndex) + " extends past the end of "
639 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000640 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
641 DyldInfo.rebase_size,
642 "dyld rebase info"))
643 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000644 if (DyldInfo.bind_off > FileSize)
645 return malformedError("bind_off field of " + Twine(CmdName) +
646 " command " + Twine(LoadCommandIndex) + " extends "
647 "past the end of the file");
648 BigSize = DyldInfo.bind_off;
649 BigSize += DyldInfo.bind_size;
650 if (BigSize > FileSize)
651 return malformedError("bind_off field plus bind_size field of " +
652 Twine(CmdName) + " command " +
653 Twine(LoadCommandIndex) + " extends past the end of "
654 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000655 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
656 DyldInfo.bind_size,
657 "dyld bind info"))
658 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000659 if (DyldInfo.weak_bind_off > FileSize)
660 return malformedError("weak_bind_off field of " + Twine(CmdName) +
661 " command " + Twine(LoadCommandIndex) + " extends "
662 "past the end of the file");
663 BigSize = DyldInfo.weak_bind_off;
664 BigSize += DyldInfo.weak_bind_size;
665 if (BigSize > FileSize)
666 return malformedError("weak_bind_off field plus weak_bind_size field of " +
667 Twine(CmdName) + " command " +
668 Twine(LoadCommandIndex) + " extends past the end of "
669 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000670 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
671 DyldInfo.weak_bind_size,
672 "dyld weak bind info"))
673 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000674 if (DyldInfo.lazy_bind_off > FileSize)
675 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
676 " command " + Twine(LoadCommandIndex) + " extends "
677 "past the end of the file");
678 BigSize = DyldInfo.lazy_bind_off;
679 BigSize += DyldInfo.lazy_bind_size;
680 if (BigSize > FileSize)
681 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
682 Twine(CmdName) + " command " +
683 Twine(LoadCommandIndex) + " extends past the end of "
684 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000685 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
686 DyldInfo.lazy_bind_size,
687 "dyld lazy bind info"))
688 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000689 if (DyldInfo.export_off > FileSize)
690 return malformedError("export_off field of " + Twine(CmdName) +
691 " command " + Twine(LoadCommandIndex) + " extends "
692 "past the end of the file");
693 BigSize = DyldInfo.export_off;
694 BigSize += DyldInfo.export_size;
695 if (BigSize > FileSize)
696 return malformedError("export_off field plus export_size field of " +
697 Twine(CmdName) + " command " +
698 Twine(LoadCommandIndex) + " extends past the end of "
699 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000700 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
701 DyldInfo.export_size,
702 "dyld export info"))
703 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000704 *LoadCmd = Load.Ptr;
705 return Error::success();
706}
707
Lang Hames697e7cd2016-12-04 01:56:10 +0000708static Error checkDylibCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000709 const MachOObjectFile::LoadCommandInfo &Load,
710 uint32_t LoadCommandIndex, const char *CmdName) {
711 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
712 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
713 CmdName + " cmdsize too small");
714 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
715 if (D.dylib.name < sizeof(MachO::dylib_command))
716 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
717 CmdName + " name.offset field too small, not past "
718 "the end of the dylib_command struct");
719 if (D.dylib.name >= D.cmdsize)
720 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
721 CmdName + " name.offset field extends past the end "
722 "of the load command");
723 // Make sure there is a null between the starting offset of the name and
724 // the end of the load command.
725 uint32_t i;
726 const char *P = (const char *)Load.Ptr;
727 for (i = D.dylib.name; i < D.cmdsize; i++)
728 if (P[i] == '\0')
729 break;
730 if (i >= D.cmdsize)
731 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
732 CmdName + " library name extends past the end of the "
733 "load command");
734 return Error::success();
735}
736
Lang Hames697e7cd2016-12-04 01:56:10 +0000737static Error checkDylibIdCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000738 const MachOObjectFile::LoadCommandInfo &Load,
739 uint32_t LoadCommandIndex,
740 const char **LoadCmd) {
741 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
742 "LC_ID_DYLIB"))
743 return Err;
744 if (*LoadCmd != nullptr)
745 return malformedError("more than one LC_ID_DYLIB command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000746 if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
747 Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000748 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
749 "file type");
750 *LoadCmd = Load.Ptr;
751 return Error::success();
752}
753
Lang Hames697e7cd2016-12-04 01:56:10 +0000754static Error checkDyldCommand(const MachOObjectFile &Obj,
Kevin Enderby3e490ef2016-09-27 23:24:13 +0000755 const MachOObjectFile::LoadCommandInfo &Load,
756 uint32_t LoadCommandIndex, const char *CmdName) {
757 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
758 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
759 CmdName + " cmdsize too small");
760 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
761 if (D.name < sizeof(MachO::dylinker_command))
762 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
763 CmdName + " name.offset field too small, not past "
764 "the end of the dylinker_command struct");
765 if (D.name >= D.cmdsize)
766 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
767 CmdName + " name.offset field extends past the end "
768 "of the load command");
769 // Make sure there is a null between the starting offset of the name and
770 // the end of the load command.
771 uint32_t i;
772 const char *P = (const char *)Load.Ptr;
773 for (i = D.name; i < D.cmdsize; i++)
774 if (P[i] == '\0')
775 break;
776 if (i >= D.cmdsize)
777 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
778 CmdName + " dyld name extends past the end of the "
779 "load command");
780 return Error::success();
781}
782
Lang Hames697e7cd2016-12-04 01:56:10 +0000783static Error checkVersCommand(const MachOObjectFile &Obj,
Kevin Enderby32359db2016-09-28 21:20:45 +0000784 const MachOObjectFile::LoadCommandInfo &Load,
785 uint32_t LoadCommandIndex,
786 const char **LoadCmd, const char *CmdName) {
787 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
788 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
789 CmdName + " has incorrect cmdsize");
790 if (*LoadCmd != nullptr)
791 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
792 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
793 "LC_VERSION_MIN_WATCHOS command");
794 *LoadCmd = Load.Ptr;
795 return Error::success();
796}
797
Kevin Enderbya4579c42017-01-19 17:36:31 +0000798static Error checkNoteCommand(const MachOObjectFile &Obj,
799 const MachOObjectFile::LoadCommandInfo &Load,
800 uint32_t LoadCommandIndex,
801 std::list<MachOElement> &Elements) {
802 if (Load.C.cmdsize != sizeof(MachO::note_command))
803 return malformedError("load command " + Twine(LoadCommandIndex) +
804 " LC_NOTE has incorrect cmdsize");
805 MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
806 uint64_t FileSize = Obj.getData().size();
807 if (Nt.offset > FileSize)
808 return malformedError("offset field of LC_NOTE command " +
809 Twine(LoadCommandIndex) + " extends "
810 "past the end of the file");
811 uint64_t BigSize = Nt.offset;
812 BigSize += Nt.size;
813 if (BigSize > FileSize)
814 return malformedError("size field plus offset field of LC_NOTE command " +
815 Twine(LoadCommandIndex) + " extends past the end of "
816 "the file");
817 if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
818 "LC_NOTE data"))
819 return Err;
820 return Error::success();
821}
822
Steven Wu5b54a422017-01-23 20:07:55 +0000823static Error
824parseBuildVersionCommand(const MachOObjectFile &Obj,
825 const MachOObjectFile::LoadCommandInfo &Load,
826 SmallVectorImpl<const char*> &BuildTools,
827 uint32_t LoadCommandIndex) {
828 MachO::build_version_command BVC =
829 getStruct<MachO::build_version_command>(Obj, Load.Ptr);
830 if (Load.C.cmdsize !=
831 sizeof(MachO::build_version_command) +
832 BVC.ntools * sizeof(MachO::build_tool_version))
833 return malformedError("load command " + Twine(LoadCommandIndex) +
834 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
835
836 auto Start = Load.Ptr + sizeof(MachO::build_version_command);
837 BuildTools.resize(BVC.ntools);
838 for (unsigned i = 0; i < BVC.ntools; ++i)
839 BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
840
841 return Error::success();
842}
843
Lang Hames697e7cd2016-12-04 01:56:10 +0000844static Error checkRpathCommand(const MachOObjectFile &Obj,
Kevin Enderby76966bf2016-09-28 23:16:01 +0000845 const MachOObjectFile::LoadCommandInfo &Load,
846 uint32_t LoadCommandIndex) {
847 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
848 return malformedError("load command " + Twine(LoadCommandIndex) +
849 " LC_RPATH cmdsize too small");
850 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
851 if (R.path < sizeof(MachO::rpath_command))
852 return malformedError("load command " + Twine(LoadCommandIndex) +
853 " LC_RPATH path.offset field too small, not past "
854 "the end of the rpath_command struct");
855 if (R.path >= R.cmdsize)
856 return malformedError("load command " + Twine(LoadCommandIndex) +
857 " LC_RPATH path.offset field extends past the end "
858 "of the load command");
859 // Make sure there is a null between the starting offset of the path and
860 // the end of the load command.
861 uint32_t i;
862 const char *P = (const char *)Load.Ptr;
863 for (i = R.path; i < R.cmdsize; i++)
864 if (P[i] == '\0')
865 break;
866 if (i >= R.cmdsize)
867 return malformedError("load command " + Twine(LoadCommandIndex) +
868 " LC_RPATH library name extends past the end of the "
869 "load command");
870 return Error::success();
871}
872
Lang Hames697e7cd2016-12-04 01:56:10 +0000873static Error checkEncryptCommand(const MachOObjectFile &Obj,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000874 const MachOObjectFile::LoadCommandInfo &Load,
875 uint32_t LoadCommandIndex,
876 uint64_t cryptoff, uint64_t cryptsize,
877 const char **LoadCmd, const char *CmdName) {
878 if (*LoadCmd != nullptr)
879 return malformedError("more than one LC_ENCRYPTION_INFO and or "
880 "LC_ENCRYPTION_INFO_64 command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000881 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000882 if (cryptoff > FileSize)
883 return malformedError("cryptoff field of " + Twine(CmdName) +
884 " command " + Twine(LoadCommandIndex) + " extends "
885 "past the end of the file");
886 uint64_t BigSize = cryptoff;
887 BigSize += cryptsize;
888 if (BigSize > FileSize)
889 return malformedError("cryptoff field plus cryptsize field of " +
890 Twine(CmdName) + " command " +
891 Twine(LoadCommandIndex) + " extends past the end of "
892 "the file");
893 *LoadCmd = Load.Ptr;
894 return Error::success();
895}
896
Lang Hames697e7cd2016-12-04 01:56:10 +0000897static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
Kevin Enderby68fffa82016-10-11 21:04:39 +0000898 const MachOObjectFile::LoadCommandInfo &Load,
899 uint32_t LoadCommandIndex) {
900 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
901 return malformedError("load command " + Twine(LoadCommandIndex) +
902 " LC_LINKER_OPTION cmdsize too small");
903 MachO::linker_option_command L =
904 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
905 // Make sure the count of strings is correct.
906 const char *string = (const char *)Load.Ptr +
907 sizeof(struct MachO::linker_option_command);
908 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
909 uint32_t i = 0;
910 while (left > 0) {
911 while (*string == '\0' && left > 0) {
912 string++;
913 left--;
914 }
915 if (left > 0) {
916 i++;
917 uint32_t NullPos = StringRef(string, left).find('\0');
918 uint32_t len = std::min(NullPos, left) + 1;
919 string += len;
920 left -= len;
921 }
922 }
923 if (L.count != i)
924 return malformedError("load command " + Twine(LoadCommandIndex) +
925 " LC_LINKER_OPTION string count " + Twine(L.count) +
926 " does not match number of strings");
927 return Error::success();
928}
929
Lang Hames697e7cd2016-12-04 01:56:10 +0000930static Error checkSubCommand(const MachOObjectFile &Obj,
Kevin Enderby2490de02016-10-17 22:09:25 +0000931 const MachOObjectFile::LoadCommandInfo &Load,
932 uint32_t LoadCommandIndex, const char *CmdName,
933 size_t SizeOfCmd, const char *CmdStructName,
934 uint32_t PathOffset, const char *PathFieldName) {
935 if (PathOffset < SizeOfCmd)
936 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
937 CmdName + " " + PathFieldName + ".offset field too "
938 "small, not past the end of the " + CmdStructName);
939 if (PathOffset >= Load.C.cmdsize)
940 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
941 CmdName + " " + PathFieldName + ".offset field "
942 "extends past the end of the load command");
943 // Make sure there is a null between the starting offset of the path and
944 // the end of the load command.
945 uint32_t i;
946 const char *P = (const char *)Load.Ptr;
947 for (i = PathOffset; i < Load.C.cmdsize; i++)
948 if (P[i] == '\0')
949 break;
950 if (i >= Load.C.cmdsize)
951 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
952 CmdName + " " + PathFieldName + " name extends past "
953 "the end of the load command");
954 return Error::success();
955}
956
Lang Hames697e7cd2016-12-04 01:56:10 +0000957static Error checkThreadCommand(const MachOObjectFile &Obj,
Kevin Enderby210030b2016-10-19 23:44:34 +0000958 const MachOObjectFile::LoadCommandInfo &Load,
959 uint32_t LoadCommandIndex,
960 const char *CmdName) {
961 if (Load.C.cmdsize < sizeof(MachO::thread_command))
962 return malformedError("load command " + Twine(LoadCommandIndex) +
963 CmdName + " cmdsize too small");
964 MachO::thread_command T =
965 getStruct<MachO::thread_command>(Obj, Load.Ptr);
966 const char *state = Load.Ptr + sizeof(MachO::thread_command);
967 const char *end = Load.Ptr + T.cmdsize;
968 uint32_t nflavor = 0;
969 uint32_t cputype = getCPUType(Obj);
970 while (state < end) {
971 if(state + sizeof(uint32_t) > end)
972 return malformedError("load command " + Twine(LoadCommandIndex) +
973 "flavor in " + CmdName + " extends past end of "
974 "command");
975 uint32_t flavor;
976 memcpy(&flavor, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000977 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000978 sys::swapByteOrder(flavor);
979 state += sizeof(uint32_t);
980
981 if(state + sizeof(uint32_t) > end)
982 return malformedError("load command " + Twine(LoadCommandIndex) +
983 " count in " + CmdName + " extends past end of "
984 "command");
985 uint32_t count;
986 memcpy(&count, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000987 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000988 sys::swapByteOrder(count);
989 state += sizeof(uint32_t);
990
Kevin Enderbyc3a035d2017-01-23 21:13:29 +0000991 if (cputype == MachO::CPU_TYPE_I386) {
992 if (flavor == MachO::x86_THREAD_STATE32) {
993 if (count != MachO::x86_THREAD_STATE32_COUNT)
994 return malformedError("load command " + Twine(LoadCommandIndex) +
995 " count not x86_THREAD_STATE32_COUNT for "
996 "flavor number " + Twine(nflavor) + " which is "
997 "a x86_THREAD_STATE32 flavor in " + CmdName +
998 " command");
999 if (state + sizeof(MachO::x86_thread_state32_t) > end)
1000 return malformedError("load command " + Twine(LoadCommandIndex) +
1001 " x86_THREAD_STATE32 extends past end of "
1002 "command in " + CmdName + " command");
1003 state += sizeof(MachO::x86_thread_state32_t);
1004 } else {
1005 return malformedError("load command " + Twine(LoadCommandIndex) +
1006 " unknown flavor (" + Twine(flavor) + ") for "
1007 "flavor number " + Twine(nflavor) + " in " +
1008 CmdName + " command");
1009 }
1010 } else if (cputype == MachO::CPU_TYPE_X86_64) {
Kevin Enderby210030b2016-10-19 23:44:34 +00001011 if (flavor == MachO::x86_THREAD_STATE64) {
1012 if (count != MachO::x86_THREAD_STATE64_COUNT)
1013 return malformedError("load command " + Twine(LoadCommandIndex) +
1014 " count not x86_THREAD_STATE64_COUNT for "
1015 "flavor number " + Twine(nflavor) + " which is "
1016 "a x86_THREAD_STATE64 flavor in " + CmdName +
1017 " command");
1018 if (state + sizeof(MachO::x86_thread_state64_t) > end)
1019 return malformedError("load command " + Twine(LoadCommandIndex) +
1020 " x86_THREAD_STATE64 extends past end of "
1021 "command in " + CmdName + " command");
1022 state += sizeof(MachO::x86_thread_state64_t);
1023 } else {
1024 return malformedError("load command " + Twine(LoadCommandIndex) +
1025 " unknown flavor (" + Twine(flavor) + ") for "
1026 "flavor number " + Twine(nflavor) + " in " +
1027 CmdName + " command");
1028 }
1029 } else if (cputype == MachO::CPU_TYPE_ARM) {
1030 if (flavor == MachO::ARM_THREAD_STATE) {
1031 if (count != MachO::ARM_THREAD_STATE_COUNT)
1032 return malformedError("load command " + Twine(LoadCommandIndex) +
1033 " count not ARM_THREAD_STATE_COUNT for "
1034 "flavor number " + Twine(nflavor) + " which is "
1035 "a ARM_THREAD_STATE flavor in " + CmdName +
1036 " command");
1037 if (state + sizeof(MachO::arm_thread_state32_t) > end)
1038 return malformedError("load command " + Twine(LoadCommandIndex) +
1039 " ARM_THREAD_STATE extends past end of "
1040 "command in " + CmdName + " command");
1041 state += sizeof(MachO::arm_thread_state32_t);
1042 } else {
1043 return malformedError("load command " + Twine(LoadCommandIndex) +
1044 " unknown flavor (" + Twine(flavor) + ") for "
1045 "flavor number " + Twine(nflavor) + " in " +
1046 CmdName + " command");
1047 }
Kevin Enderby7747cb52016-11-03 20:51:28 +00001048 } else if (cputype == MachO::CPU_TYPE_ARM64) {
1049 if (flavor == MachO::ARM_THREAD_STATE64) {
1050 if (count != MachO::ARM_THREAD_STATE64_COUNT)
1051 return malformedError("load command " + Twine(LoadCommandIndex) +
1052 " count not ARM_THREAD_STATE64_COUNT for "
1053 "flavor number " + Twine(nflavor) + " which is "
1054 "a ARM_THREAD_STATE64 flavor in " + CmdName +
1055 " command");
1056 if (state + sizeof(MachO::arm_thread_state64_t) > end)
1057 return malformedError("load command " + Twine(LoadCommandIndex) +
1058 " ARM_THREAD_STATE64 extends past end of "
1059 "command in " + CmdName + " command");
1060 state += sizeof(MachO::arm_thread_state64_t);
1061 } else {
1062 return malformedError("load command " + Twine(LoadCommandIndex) +
1063 " unknown flavor (" + Twine(flavor) + ") for "
1064 "flavor number " + Twine(nflavor) + " in " +
1065 CmdName + " command");
1066 }
Kevin Enderby210030b2016-10-19 23:44:34 +00001067 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1068 if (flavor == MachO::PPC_THREAD_STATE) {
1069 if (count != MachO::PPC_THREAD_STATE_COUNT)
1070 return malformedError("load command " + Twine(LoadCommandIndex) +
1071 " count not PPC_THREAD_STATE_COUNT for "
1072 "flavor number " + Twine(nflavor) + " which is "
1073 "a PPC_THREAD_STATE flavor in " + CmdName +
1074 " command");
1075 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1076 return malformedError("load command " + Twine(LoadCommandIndex) +
1077 " PPC_THREAD_STATE extends past end of "
1078 "command in " + CmdName + " command");
1079 state += sizeof(MachO::ppc_thread_state32_t);
1080 } else {
1081 return malformedError("load command " + Twine(LoadCommandIndex) +
1082 " unknown flavor (" + Twine(flavor) + ") for "
1083 "flavor number " + Twine(nflavor) + " in " +
1084 CmdName + " command");
1085 }
1086 } else {
1087 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1088 "command " + Twine(LoadCommandIndex) + " for " +
1089 CmdName + " command can't be checked");
1090 }
1091 nflavor++;
1092 }
1093 return Error::success();
1094}
1095
Lang Hames697e7cd2016-12-04 01:56:10 +00001096static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001097 const MachOObjectFile::LoadCommandInfo
1098 &Load,
1099 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001100 const char **LoadCmd,
1101 std::list<MachOElement> &Elements) {
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001102 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1103 return malformedError("load command " + Twine(LoadCommandIndex) +
1104 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1105 if (*LoadCmd != nullptr)
1106 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1107 MachO::twolevel_hints_command Hints =
1108 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
Lang Hames697e7cd2016-12-04 01:56:10 +00001109 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001110 if (Hints.offset > FileSize)
1111 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1112 Twine(LoadCommandIndex) + " extends past the end of "
1113 "the file");
1114 uint64_t BigSize = Hints.nhints;
1115 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint);
1116 BigSize += Hints.offset;
1117 if (BigSize > FileSize)
1118 return malformedError("offset field plus nhints times sizeof(struct "
1119 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1120 Twine(LoadCommandIndex) + " extends past the end of "
1121 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001122 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1123 sizeof(MachO::twolevel_hint),
1124 "two level hints"))
1125 return Err;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001126 *LoadCmd = Load.Ptr;
1127 return Error::success();
1128}
1129
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001130// Returns true if the libObject code does not support the load command and its
1131// contents. The cmd value it is treated as an unknown load command but with
1132// an error message that says the cmd value is obsolete.
1133static bool isLoadCommandObsolete(uint32_t cmd) {
1134 if (cmd == MachO::LC_SYMSEG ||
1135 cmd == MachO::LC_LOADFVMLIB ||
1136 cmd == MachO::LC_IDFVMLIB ||
1137 cmd == MachO::LC_IDENT ||
1138 cmd == MachO::LC_FVMFILE ||
1139 cmd == MachO::LC_PREPAGE ||
1140 cmd == MachO::LC_PREBOUND_DYLIB ||
1141 cmd == MachO::LC_TWOLEVEL_HINTS ||
1142 cmd == MachO::LC_PREBIND_CKSUM)
1143 return true;
1144 return false;
1145}
1146
Lang Hames82627642016-03-25 21:59:14 +00001147Expected<std::unique_ptr<MachOObjectFile>>
1148MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001149 bool Is64Bits, uint32_t UniversalCputype,
1150 uint32_t UniversalIndex) {
Mehdi Amini41af4302016-11-11 04:28:40 +00001151 Error Err = Error::success();
Lang Hames82627642016-03-25 21:59:14 +00001152 std::unique_ptr<MachOObjectFile> Obj(
1153 new MachOObjectFile(std::move(Object), IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001154 Is64Bits, Err, UniversalCputype,
1155 UniversalIndex));
Lang Hames82627642016-03-25 21:59:14 +00001156 if (Err)
1157 return std::move(Err);
1158 return std::move(Obj);
1159}
1160
Rafael Espindola48af1c22014-08-19 18:44:46 +00001161MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001162 bool Is64bits, Error &Err,
1163 uint32_t UniversalCputype,
1164 uint32_t UniversalIndex)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00001165 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
Lang Hames5e51a2e2016-07-22 16:11:25 +00001166 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001167 uint64_t SizeOfHeaders;
Kevin Enderby79d6c632016-10-24 21:15:11 +00001168 uint32_t cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001169 if (is64Bit()) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001170 parseHeader(*this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001171 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001172 cputype = Header64.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001173 } else {
Lang Hames697e7cd2016-12-04 01:56:10 +00001174 parseHeader(*this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001175 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001176 cputype = Header.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001177 }
Lang Hames9e964f32016-03-25 17:25:34 +00001178 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +00001179 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +00001180 SizeOfHeaders += getHeader().sizeofcmds;
1181 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001182 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +00001183 return;
1184 }
Kevin Enderby79d6c632016-10-24 21:15:11 +00001185 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1186 Err = malformedError("universal header architecture: " +
1187 Twine(UniversalIndex) + "'s cputype does not match "
1188 "object file's mach header");
1189 return;
1190 }
Kevin Enderbyd5039402016-10-31 20:29:48 +00001191 std::list<MachOElement> Elements;
1192 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001193
1194 uint32_t LoadCommandCount = getHeader().ncmds;
Lang Hames9e964f32016-03-25 17:25:34 +00001195 LoadCommandInfo Load;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001196 if (LoadCommandCount != 0) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001197 if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001198 Load = *LoadOrErr;
1199 else {
1200 Err = LoadOrErr.takeError();
1201 return;
1202 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001203 }
Lang Hames9e964f32016-03-25 17:25:34 +00001204
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001205 const char *DyldIdLoadCmd = nullptr;
Kevin Enderby90986e62016-09-26 21:11:03 +00001206 const char *FuncStartsLoadCmd = nullptr;
1207 const char *SplitInfoLoadCmd = nullptr;
1208 const char *CodeSignDrsLoadCmd = nullptr;
Kevin Enderby89baf992016-10-18 20:24:12 +00001209 const char *CodeSignLoadCmd = nullptr;
Kevin Enderby32359db2016-09-28 21:20:45 +00001210 const char *VersLoadCmd = nullptr;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001211 const char *SourceLoadCmd = nullptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001212 const char *EntryPointLoadCmd = nullptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001213 const char *EncryptLoadCmd = nullptr;
Kevin Enderby6f695822016-10-18 17:54:17 +00001214 const char *RoutinesLoadCmd = nullptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001215 const char *UnixThreadLoadCmd = nullptr;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001216 const char *TwoLevelHintsLoadCmd = nullptr;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001217 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +00001218 if (is64Bit()) {
1219 if (Load.C.cmdsize % 8 != 0) {
1220 // We have a hack here to allow 64-bit Mach-O core files to have
1221 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1222 // allowed since the macOS kernel produces them.
1223 if (getHeader().filetype != MachO::MH_CORE ||
1224 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1225 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1226 "multiple of 8");
1227 return;
1228 }
1229 }
1230 } else {
1231 if (Load.C.cmdsize % 4 != 0) {
1232 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1233 "multiple of 4");
1234 return;
1235 }
1236 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001237 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001238 if (Load.C.cmd == MachO::LC_SYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001239 if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001240 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001241 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001242 if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001243 Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001244 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001245 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001246 if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001247 "LC_DATA_IN_CODE", Elements,
1248 "data in code info")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001249 return;
Kevin Enderby9a509442015-01-27 21:28:24 +00001250 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001251 if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001252 "LC_LINKER_OPTIMIZATION_HINT",
1253 Elements, "linker optimization "
1254 "hints")))
Kevin Enderby9a509442015-01-27 21:28:24 +00001255 return;
Kevin Enderby90986e62016-09-26 21:11:03 +00001256 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001257 if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001258 "LC_FUNCTION_STARTS", Elements,
1259 "function starts data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001260 return;
1261 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001262 if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001263 "LC_SEGMENT_SPLIT_INFO", Elements,
1264 "split info data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001265 return;
1266 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001267 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001268 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1269 "code signing RDs data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001270 return;
Kevin Enderby89baf992016-10-18 20:24:12 +00001271 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001272 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001273 "LC_CODE_SIGNATURE", Elements,
1274 "code signature data")))
Kevin Enderby89baf992016-10-18 20:24:12 +00001275 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001276 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001277 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001278 "LC_DYLD_INFO", Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001279 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001280 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001281 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001282 "LC_DYLD_INFO_ONLY", Elements)))
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001283 return;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001284 } else if (Load.C.cmd == MachO::LC_UUID) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001285 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1286 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1287 "cmdsize");
1288 return;
1289 }
David Majnemer73cc6ff2014-11-13 19:48:56 +00001290 if (UuidLoadCmd) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001291 Err = malformedError("more than one LC_UUID command");
David Majnemer73cc6ff2014-11-13 19:48:56 +00001292 return;
1293 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001294 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001295 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001296 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1297 MachO::section_64>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001298 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001299 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001300 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001301 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001302 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1303 MachO::section>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001304 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001305 "LC_SEGMENT", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001306 return;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001307 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001308 if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001309 return;
1310 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001311 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001312 return;
1313 Libraries.push_back(Load.Ptr);
1314 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001315 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001316 return;
1317 Libraries.push_back(Load.Ptr);
1318 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001319 if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001320 return;
1321 Libraries.push_back(Load.Ptr);
1322 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001323 if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001324 return;
1325 Libraries.push_back(Load.Ptr);
1326 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001327 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001328 return;
Kevin Enderby980b2582014-06-05 21:21:57 +00001329 Libraries.push_back(Load.Ptr);
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001330 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001331 if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001332 return;
1333 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001334 if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001335 return;
1336 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001337 if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001338 return;
Kevin Enderby32359db2016-09-28 21:20:45 +00001339 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001340 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001341 "LC_VERSION_MIN_MACOSX")))
1342 return;
1343 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001344 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001345 "LC_VERSION_MIN_IPHONEOS")))
1346 return;
1347 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001348 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001349 "LC_VERSION_MIN_TVOS")))
1350 return;
1351 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001352 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001353 "LC_VERSION_MIN_WATCHOS")))
1354 return;
Kevin Enderbya4579c42017-01-19 17:36:31 +00001355 } else if (Load.C.cmd == MachO::LC_NOTE) {
1356 if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1357 return;
Steven Wu5b54a422017-01-23 20:07:55 +00001358 } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1359 if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1360 return;
Kevin Enderby76966bf2016-09-28 23:16:01 +00001361 } else if (Load.C.cmd == MachO::LC_RPATH) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001362 if ((Err = checkRpathCommand(*this, Load, I)))
Kevin Enderby76966bf2016-09-28 23:16:01 +00001363 return;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001364 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1365 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1366 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1367 " has incorrect cmdsize");
1368 return;
1369 }
1370 if (SourceLoadCmd) {
1371 Err = malformedError("more than one LC_SOURCE_VERSION command");
1372 return;
1373 }
1374 SourceLoadCmd = Load.Ptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001375 } else if (Load.C.cmd == MachO::LC_MAIN) {
1376 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1377 Err = malformedError("LC_MAIN command " + Twine(I) +
1378 " has incorrect cmdsize");
1379 return;
1380 }
1381 if (EntryPointLoadCmd) {
1382 Err = malformedError("more than one LC_MAIN command");
1383 return;
1384 }
1385 EntryPointLoadCmd = Load.Ptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001386 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1387 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1388 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1389 " has incorrect cmdsize");
1390 return;
1391 }
1392 MachO::encryption_info_command E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001393 getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1394 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001395 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1396 return;
1397 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1398 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1399 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1400 " has incorrect cmdsize");
1401 return;
1402 }
1403 MachO::encryption_info_command_64 E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001404 getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1405 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001406 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1407 return;
Kevin Enderby68fffa82016-10-11 21:04:39 +00001408 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001409 if ((Err = checkLinkerOptCommand(*this, Load, I)))
Kevin Enderby68fffa82016-10-11 21:04:39 +00001410 return;
Kevin Enderby2490de02016-10-17 22:09:25 +00001411 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1412 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1413 Err = malformedError("load command " + Twine(I) +
1414 " LC_SUB_FRAMEWORK cmdsize too small");
1415 return;
1416 }
1417 MachO::sub_framework_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001418 getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1419 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
Kevin Enderby2490de02016-10-17 22:09:25 +00001420 sizeof(MachO::sub_framework_command),
1421 "sub_framework_command", S.umbrella,
1422 "umbrella")))
1423 return;
1424 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1425 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1426 Err = malformedError("load command " + Twine(I) +
1427 " LC_SUB_UMBRELLA cmdsize too small");
1428 return;
1429 }
1430 MachO::sub_umbrella_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001431 getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1432 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
Kevin Enderby2490de02016-10-17 22:09:25 +00001433 sizeof(MachO::sub_umbrella_command),
1434 "sub_umbrella_command", S.sub_umbrella,
1435 "sub_umbrella")))
1436 return;
1437 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1438 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1439 Err = malformedError("load command " + Twine(I) +
1440 " LC_SUB_LIBRARY cmdsize too small");
1441 return;
1442 }
1443 MachO::sub_library_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001444 getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1445 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
Kevin Enderby2490de02016-10-17 22:09:25 +00001446 sizeof(MachO::sub_library_command),
1447 "sub_library_command", S.sub_library,
1448 "sub_library")))
1449 return;
1450 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1451 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1452 Err = malformedError("load command " + Twine(I) +
1453 " LC_SUB_CLIENT cmdsize too small");
1454 return;
1455 }
1456 MachO::sub_client_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001457 getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1458 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
Kevin Enderby2490de02016-10-17 22:09:25 +00001459 sizeof(MachO::sub_client_command),
1460 "sub_client_command", S.client, "client")))
1461 return;
Kevin Enderby6f695822016-10-18 17:54:17 +00001462 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1463 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1464 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1465 " has incorrect cmdsize");
1466 return;
1467 }
1468 if (RoutinesLoadCmd) {
1469 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1470 "command");
1471 return;
1472 }
1473 RoutinesLoadCmd = Load.Ptr;
1474 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1475 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1476 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1477 " has incorrect cmdsize");
1478 return;
1479 }
1480 if (RoutinesLoadCmd) {
1481 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1482 "command");
1483 return;
1484 }
1485 RoutinesLoadCmd = Load.Ptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001486 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001487 if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001488 return;
1489 if (UnixThreadLoadCmd) {
1490 Err = malformedError("more than one LC_UNIXTHREAD command");
1491 return;
1492 }
1493 UnixThreadLoadCmd = Load.Ptr;
1494 } else if (Load.C.cmd == MachO::LC_THREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001495 if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001496 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001497 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001498 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001499 if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001500 &TwoLevelHintsLoadCmd, Elements)))
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001501 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001502 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1503 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1504 Twine(Load.C.cmd) + " is obsolete and not "
1505 "supported");
1506 return;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001507 }
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001508 // TODO: generate a error for unknown load commands by default. But still
1509 // need work out an approach to allow or not allow unknown values like this
1510 // as an option for some uses like lldb.
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001511 if (I < LoadCommandCount - 1) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001512 if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +00001513 Load = *LoadOrErr;
1514 else {
1515 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001516 return;
1517 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001518 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001519 }
Kevin Enderby1829c682016-01-22 22:49:55 +00001520 if (!SymtabLoadCmd) {
1521 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001522 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +00001523 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +00001524 return;
1525 }
1526 } else if (DysymtabLoadCmd) {
1527 MachO::symtab_command Symtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001528 getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001529 MachO::dysymtab_command Dysymtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001530 getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001531 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001532 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001533 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001534 return;
1535 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001536 uint64_t BigSize = Dysymtab.ilocalsym;
1537 BigSize += Dysymtab.nlocalsym;
1538 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001539 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001540 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001541 return;
1542 }
1543 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001544 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001545 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001546 return;
1547 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001548 BigSize = Dysymtab.iextdefsym;
1549 BigSize += Dysymtab.nextdefsym;
1550 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001551 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +00001552 "load command extends past the end of the symbol "
1553 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001554 return;
1555 }
1556 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001557 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001558 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001559 return;
1560 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001561 BigSize = Dysymtab.iundefsym;
1562 BigSize += Dysymtab.nundefsym;
1563 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001564 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001565 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001566 return;
1567 }
1568 }
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001569 if ((getHeader().filetype == MachO::MH_DYLIB ||
1570 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1571 DyldIdLoadCmd == nullptr) {
1572 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1573 "filetype");
1574 return;
1575 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001576 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +00001577
1578 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001579}
1580
Kevin Enderby22fc0072016-11-14 20:57:04 +00001581Error MachOObjectFile::checkSymbolTable() const {
1582 uint32_t Flags = 0;
1583 if (is64Bit()) {
1584 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1585 Flags = H_64.flags;
1586 } else {
1587 MachO::mach_header H = MachOObjectFile::getHeader();
1588 Flags = H.flags;
1589 }
1590 uint8_t NType = 0;
1591 uint8_t NSect = 0;
1592 uint16_t NDesc = 0;
1593 uint32_t NStrx = 0;
1594 uint64_t NValue = 0;
1595 uint32_t SymbolIndex = 0;
1596 MachO::symtab_command S = getSymtabLoadCommand();
1597 for (const SymbolRef &Symbol : symbols()) {
1598 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1599 if (is64Bit()) {
1600 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1601 NType = STE_64.n_type;
1602 NSect = STE_64.n_sect;
1603 NDesc = STE_64.n_desc;
1604 NStrx = STE_64.n_strx;
1605 NValue = STE_64.n_value;
1606 } else {
1607 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1608 NType = STE.n_type;
1609 NType = STE.n_type;
1610 NSect = STE.n_sect;
1611 NDesc = STE.n_desc;
1612 NStrx = STE.n_strx;
1613 NValue = STE.n_value;
1614 }
1615 if ((NType & MachO::N_STAB) == 0 &&
1616 (NType & MachO::N_TYPE) == MachO::N_SECT) {
1617 if (NSect == 0 || NSect > Sections.size())
1618 return malformedError("bad section index: " + Twine((int)NSect) +
1619 " for symbol at index " + Twine(SymbolIndex));
1620 }
1621 if ((NType & MachO::N_STAB) == 0 &&
1622 (NType & MachO::N_TYPE) == MachO::N_INDR) {
1623 if (NValue >= S.strsize)
1624 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1625 "the end of string table, for N_INDR symbol at "
1626 "index " + Twine(SymbolIndex));
1627 }
1628 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1629 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1630 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1631 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1632 if (LibraryOrdinal != 0 &&
1633 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1634 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1635 LibraryOrdinal - 1 >= Libraries.size() ) {
1636 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1637 " for symbol at index " + Twine(SymbolIndex));
1638 }
1639 }
1640 if (NStrx >= S.strsize)
1641 return malformedError("bad string table index: " + Twine((int)NStrx) +
1642 " past the end of string table, for symbol at "
1643 "index " + Twine(SymbolIndex));
1644 SymbolIndex++;
1645 }
1646 return Error::success();
1647}
1648
Rafael Espindola5e812af2014-01-30 02:49:50 +00001649void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001650 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001651 sizeof(MachO::nlist_64) :
1652 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +00001653 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001654}
1655
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001656Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001657 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001658 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001659 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001660 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001661 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +00001662 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001663 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00001664 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001665}
1666
Rafael Espindola0e77a942014-12-10 20:46:55 +00001667unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1668 DataRefImpl DRI = Sec.getRawDataRefImpl();
Lang Hames697e7cd2016-12-04 01:56:10 +00001669 uint32_t Flags = getSectionFlags(*this, DRI);
Rafael Espindola0e77a942014-12-10 20:46:55 +00001670 return Flags & MachO::SECTION_TYPE;
1671}
1672
Rafael Espindola59128922015-06-24 18:14:41 +00001673uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1674 if (is64Bit()) {
1675 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1676 return Entry.n_value;
1677 }
1678 MachO::nlist Entry = getSymbolTableEntry(Sym);
1679 return Entry.n_value;
1680}
1681
Kevin Enderby980b2582014-06-05 21:21:57 +00001682// getIndirectName() returns the name of the alias'ed symbol who's string table
1683// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +00001684std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1685 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001686 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001687 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Rafael Espindola59128922015-06-24 18:14:41 +00001688 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1689 return object_error::parse_failed;
1690 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +00001691 if (NValue >= StringTable.size())
1692 return object_error::parse_failed;
1693 const char *Start = &StringTable.data()[NValue];
1694 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +00001695 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001696}
1697
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +00001698uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +00001699 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +00001700}
1701
Kevin Enderby931cb652016-06-24 18:24:42 +00001702Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +00001703 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001704}
1705
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001706uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +00001707 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001708 if (flags & SymbolRef::SF_Common) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001709 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001710 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001711 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001712 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001713}
1714
Rafael Espindolad7a32ea2015-06-24 10:20:30 +00001715uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001716 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001717}
1718
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001719Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001720MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001721 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001722 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001723
Rafael Espindola56f976f2013-04-18 18:08:55 +00001724 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001725 if (n_type & MachO::N_STAB)
1726 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001727
Charles Davis74ec8b02013-08-27 05:00:13 +00001728 switch (n_type & MachO::N_TYPE) {
1729 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001730 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +00001731 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001732 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001733 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001734 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001735 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +00001736 if (Sec->isData() || Sec->isBSS())
1737 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001738 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001739 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001740 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001741}
1742
Rafael Espindola20122a42014-01-31 20:57:12 +00001743uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001744 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001745
Charles Davis8bdfafd2013-09-01 04:28:48 +00001746 uint8_t MachOType = Entry.n_type;
1747 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001748
Rafael Espindola20122a42014-01-31 20:57:12 +00001749 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001750
Tim Northovereaef0742014-05-30 13:22:59 +00001751 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1752 Result |= SymbolRef::SF_Indirect;
1753
Rafael Espindolaa1356322013-11-02 05:03:24 +00001754 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001755 Result |= SymbolRef::SF_FormatSpecific;
1756
Charles Davis74ec8b02013-08-27 05:00:13 +00001757 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001758 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +00001759 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001760 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001761 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +00001762 else
1763 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001764 }
Lang Hames7e0692b2015-01-15 22:33:30 +00001765
1766 if (!(MachOType & MachO::N_PEXT))
1767 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001768 }
1769
Charles Davis74ec8b02013-08-27 05:00:13 +00001770 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +00001771 Result |= SymbolRef::SF_Weak;
1772
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001773 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1774 Result |= SymbolRef::SF_Thumb;
1775
Charles Davis74ec8b02013-08-27 05:00:13 +00001776 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001777 Result |= SymbolRef::SF_Absolute;
1778
Rafael Espindola20122a42014-01-31 20:57:12 +00001779 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001780}
1781
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001782Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +00001783MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001784 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001785 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001786
Rafael Espindola8bab8892015-08-07 23:27:14 +00001787 if (index == 0)
1788 return section_end();
1789 DataRefImpl DRI;
1790 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001791 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001792 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +00001793 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001794 }
Rafael Espindola8bab8892015-08-07 23:27:14 +00001795 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001796}
1797
Rafael Espindola6bf32212015-06-24 19:57:32 +00001798unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1799 MachO::nlist_base Entry =
Lang Hames697e7cd2016-12-04 01:56:10 +00001800 getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
Rafael Espindola6bf32212015-06-24 19:57:32 +00001801 return Entry.n_sect - 1;
1802}
1803
Rafael Espindola5e812af2014-01-30 02:49:50 +00001804void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001805 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001806}
1807
Rafael Espindola3acea392014-06-12 21:46:39 +00001808std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1809 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001810 ArrayRef<char> Raw = getSectionRawName(Sec);
1811 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +00001812 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001813}
1814
Rafael Espindola80291272014-10-08 15:28:58 +00001815uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1816 if (is64Bit())
1817 return getSection64(Sec).addr;
1818 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001819}
1820
George Rimara25d3292017-05-27 18:10:23 +00001821uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1822 return Sec.d.a;
1823}
1824
Rafael Espindola80291272014-10-08 15:28:58 +00001825uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +00001826 // In the case if a malformed Mach-O file where the section offset is past
1827 // the end of the file or some part of the section size is past the end of
1828 // the file return a size of zero or a size that covers the rest of the file
1829 // but does not extend past the end of the file.
1830 uint32_t SectOffset, SectType;
1831 uint64_t SectSize;
1832
1833 if (is64Bit()) {
1834 MachO::section_64 Sect = getSection64(Sec);
1835 SectOffset = Sect.offset;
1836 SectSize = Sect.size;
1837 SectType = Sect.flags & MachO::SECTION_TYPE;
1838 } else {
1839 MachO::section Sect = getSection(Sec);
1840 SectOffset = Sect.offset;
1841 SectSize = Sect.size;
1842 SectType = Sect.flags & MachO::SECTION_TYPE;
1843 }
1844 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1845 return SectSize;
1846 uint64_t FileSize = getData().size();
1847 if (SectOffset > FileSize)
1848 return 0;
1849 if (FileSize - SectOffset < SectSize)
1850 return FileSize - SectOffset;
1851 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001852}
1853
Rafael Espindola3acea392014-06-12 21:46:39 +00001854std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1855 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001856 uint32_t Offset;
1857 uint64_t Size;
1858
1859 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001860 MachO::section_64 Sect = getSection64(Sec);
1861 Offset = Sect.offset;
1862 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001863 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001864 MachO::section Sect = getSection(Sec);
1865 Offset = Sect.offset;
1866 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001867 }
1868
1869 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +00001870 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001871}
1872
Rafael Espindola80291272014-10-08 15:28:58 +00001873uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001874 uint32_t Align;
1875 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001876 MachO::section_64 Sect = getSection64(Sec);
1877 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001878 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001879 MachO::section Sect = getSection(Sec);
1880 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001881 }
1882
Rafael Espindola80291272014-10-08 15:28:58 +00001883 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001884}
1885
George Rimar401e4e52016-05-24 12:48:46 +00001886bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1887 return false;
1888}
1889
Rafael Espindola80291272014-10-08 15:28:58 +00001890bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001891 uint32_t Flags = getSectionFlags(*this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +00001892 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001893}
1894
Rafael Espindola80291272014-10-08 15:28:58 +00001895bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001896 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001897 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001898 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1899 !(SectionType == MachO::S_ZEROFILL ||
1900 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +00001901}
1902
Rafael Espindola80291272014-10-08 15:28:58 +00001903bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001904 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001905 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001906 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1907 (SectionType == MachO::S_ZEROFILL ||
1908 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +00001909}
1910
Rafael Espindola6bf32212015-06-24 19:57:32 +00001911unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1912 return Sec.getRawDataRefImpl().d.a;
1913}
1914
Rafael Espindola80291272014-10-08 15:28:58 +00001915bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +00001916 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +00001917 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +00001918}
1919
Steven Wuf2fe0142016-02-29 19:40:10 +00001920bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1921 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1922 StringRef SectName;
1923 if (!getSectionName(Sec, SectName))
1924 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1925 return false;
1926}
1927
Rui Ueyamabc654b12013-09-27 21:47:05 +00001928relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001929 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001930 Ret.d.a = Sec.d.a;
1931 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +00001932 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +00001933}
Rafael Espindolac0406e12013-04-08 20:45:01 +00001934
Rafael Espindola56f976f2013-04-18 18:08:55 +00001935relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +00001936MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001937 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001938 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001939 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001940 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001941 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001942 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001943 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001944 }
Eric Christopher7b015c72011-04-22 03:19:48 +00001945
Rafael Espindola56f976f2013-04-18 18:08:55 +00001946 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001947 Ret.d.a = Sec.d.a;
1948 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001949 return relocation_iterator(RelocationRef(Ret, this));
1950}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001951
Kevin Enderbyabf10f22017-06-22 17:41:22 +00001952relocation_iterator MachOObjectFile::extrel_begin() const {
1953 DataRefImpl Ret;
1954 Ret.d.a = 0; // Would normally be a section index.
1955 Ret.d.b = 0; // Index into the external relocations
1956 return relocation_iterator(RelocationRef(Ret, this));
1957}
1958
1959relocation_iterator MachOObjectFile::extrel_end() const {
1960 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
1961 DataRefImpl Ret;
1962 Ret.d.a = 0; // Would normally be a section index.
1963 Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
1964 return relocation_iterator(RelocationRef(Ret, this));
1965}
1966
Rafael Espindola5e812af2014-01-30 02:49:50 +00001967void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001968 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001969}
Owen Anderson171f4852011-10-24 23:20:07 +00001970
Rafael Espindola96d071c2015-06-29 23:29:12 +00001971uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Kevin Enderbyabf10f22017-06-22 17:41:22 +00001972 assert((getHeader().filetype == MachO::MH_OBJECT ||
1973 getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
1974 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001975 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +00001976 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +00001977}
1978
Rafael Espindola806f0062013-06-05 01:33:53 +00001979symbol_iterator
1980MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001981 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00001982 if (isRelocationScattered(RE))
1983 return symbol_end();
1984
Rafael Espindola56f976f2013-04-18 18:08:55 +00001985 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
1986 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00001987 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00001988 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00001989
Charles Davis8bdfafd2013-09-01 04:28:48 +00001990 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001991 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001992 sizeof(MachO::nlist_64) :
1993 sizeof(MachO::nlist);
1994 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001995 DataRefImpl Sym;
Lang Hames697e7cd2016-12-04 01:56:10 +00001996 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00001997 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001998}
1999
Keno Fischerc780e8e2015-05-21 21:24:32 +00002000section_iterator
2001MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2002 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2003}
2004
Rafael Espindola99c041b2015-06-30 01:53:01 +00002005uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002006 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00002007 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002008}
2009
Rafael Espindola41bb4322015-06-30 04:08:37 +00002010void MachOObjectFile::getRelocationTypeName(
2011 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002012 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00002013 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002014
2015 unsigned Arch = this->getArch();
2016
2017 switch (Arch) {
2018 case Triple::x86: {
2019 static const char *const Table[] = {
2020 "GENERIC_RELOC_VANILLA",
2021 "GENERIC_RELOC_PAIR",
2022 "GENERIC_RELOC_SECTDIFF",
2023 "GENERIC_RELOC_PB_LA_PTR",
2024 "GENERIC_RELOC_LOCAL_SECTDIFF",
2025 "GENERIC_RELOC_TLV" };
2026
Eric Christopher13250cb2013-12-06 02:33:38 +00002027 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002028 res = "Unknown";
2029 else
2030 res = Table[RType];
2031 break;
2032 }
2033 case Triple::x86_64: {
2034 static const char *const Table[] = {
2035 "X86_64_RELOC_UNSIGNED",
2036 "X86_64_RELOC_SIGNED",
2037 "X86_64_RELOC_BRANCH",
2038 "X86_64_RELOC_GOT_LOAD",
2039 "X86_64_RELOC_GOT",
2040 "X86_64_RELOC_SUBTRACTOR",
2041 "X86_64_RELOC_SIGNED_1",
2042 "X86_64_RELOC_SIGNED_2",
2043 "X86_64_RELOC_SIGNED_4",
2044 "X86_64_RELOC_TLV" };
2045
2046 if (RType > 9)
2047 res = "Unknown";
2048 else
2049 res = Table[RType];
2050 break;
2051 }
2052 case Triple::arm: {
2053 static const char *const Table[] = {
2054 "ARM_RELOC_VANILLA",
2055 "ARM_RELOC_PAIR",
2056 "ARM_RELOC_SECTDIFF",
2057 "ARM_RELOC_LOCAL_SECTDIFF",
2058 "ARM_RELOC_PB_LA_PTR",
2059 "ARM_RELOC_BR24",
2060 "ARM_THUMB_RELOC_BR22",
2061 "ARM_THUMB_32BIT_BRANCH",
2062 "ARM_RELOC_HALF",
2063 "ARM_RELOC_HALF_SECTDIFF" };
2064
2065 if (RType > 9)
2066 res = "Unknown";
2067 else
2068 res = Table[RType];
2069 break;
2070 }
Tim Northover00ed9962014-03-29 10:18:08 +00002071 case Triple::aarch64: {
2072 static const char *const Table[] = {
2073 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2074 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2075 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2076 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2077 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2078 "ARM64_RELOC_ADDEND"
2079 };
2080
2081 if (RType >= array_lengthof(Table))
2082 res = "Unknown";
2083 else
2084 res = Table[RType];
2085 break;
2086 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00002087 case Triple::ppc: {
2088 static const char *const Table[] = {
2089 "PPC_RELOC_VANILLA",
2090 "PPC_RELOC_PAIR",
2091 "PPC_RELOC_BR14",
2092 "PPC_RELOC_BR24",
2093 "PPC_RELOC_HI16",
2094 "PPC_RELOC_LO16",
2095 "PPC_RELOC_HA16",
2096 "PPC_RELOC_LO14",
2097 "PPC_RELOC_SECTDIFF",
2098 "PPC_RELOC_PB_LA_PTR",
2099 "PPC_RELOC_HI16_SECTDIFF",
2100 "PPC_RELOC_LO16_SECTDIFF",
2101 "PPC_RELOC_HA16_SECTDIFF",
2102 "PPC_RELOC_JBSR",
2103 "PPC_RELOC_LO14_SECTDIFF",
2104 "PPC_RELOC_LOCAL_SECTDIFF" };
2105
Eric Christopher13250cb2013-12-06 02:33:38 +00002106 if (RType > 15)
2107 res = "Unknown";
2108 else
2109 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00002110 break;
2111 }
2112 case Triple::UnknownArch:
2113 res = "Unknown";
2114 break;
2115 }
2116 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00002117}
2118
Keno Fischer281b6942015-05-30 19:44:53 +00002119uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2120 MachO::any_relocation_info RE = getRelocation(Rel);
2121 return getAnyRelocationLength(RE);
2122}
2123
Kevin Enderby980b2582014-06-05 21:21:57 +00002124//
2125// guessLibraryShortName() is passed a name of a dynamic library and returns a
2126// guess on what the short name is. Then name is returned as a substring of the
2127// StringRef Name passed in. The name of the dynamic library is recognized as
2128// a framework if it has one of the two following forms:
2129// Foo.framework/Versions/A/Foo
2130// Foo.framework/Foo
2131// Where A and Foo can be any string. And may contain a trailing suffix
2132// starting with an underbar. If the Name is recognized as a framework then
2133// isFramework is set to true else it is set to false. If the Name has a
2134// suffix then Suffix is set to the substring in Name that contains the suffix
2135// else it is set to a NULL StringRef.
2136//
2137// The Name of the dynamic library is recognized as a library name if it has
2138// one of the two following forms:
2139// libFoo.A.dylib
2140// libFoo.dylib
2141// The library may have a suffix trailing the name Foo of the form:
2142// libFoo_profile.A.dylib
2143// libFoo_profile.dylib
2144//
2145// The Name of the dynamic library is also recognized as a library name if it
2146// has the following form:
2147// Foo.qtx
2148//
2149// If the Name of the dynamic library is none of the forms above then a NULL
2150// StringRef is returned.
2151//
2152StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2153 bool &isFramework,
2154 StringRef &Suffix) {
2155 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2156 size_t a, b, c, d, Idx;
2157
2158 isFramework = false;
2159 Suffix = StringRef();
2160
2161 // Pull off the last component and make Foo point to it
2162 a = Name.rfind('/');
2163 if (a == Name.npos || a == 0)
2164 goto guess_library;
2165 Foo = Name.slice(a+1, Name.npos);
2166
2167 // Look for a suffix starting with a '_'
2168 Idx = Foo.rfind('_');
2169 if (Idx != Foo.npos && Foo.size() >= 2) {
2170 Suffix = Foo.slice(Idx, Foo.npos);
2171 Foo = Foo.slice(0, Idx);
2172 }
2173
2174 // First look for the form Foo.framework/Foo
2175 b = Name.rfind('/', a);
2176 if (b == Name.npos)
2177 Idx = 0;
2178 else
2179 Idx = b+1;
2180 F = Name.slice(Idx, Idx + Foo.size());
2181 DotFramework = Name.slice(Idx + Foo.size(),
2182 Idx + Foo.size() + sizeof(".framework/")-1);
2183 if (F == Foo && DotFramework == ".framework/") {
2184 isFramework = true;
2185 return Foo;
2186 }
2187
2188 // Next look for the form Foo.framework/Versions/A/Foo
2189 if (b == Name.npos)
2190 goto guess_library;
2191 c = Name.rfind('/', b);
2192 if (c == Name.npos || c == 0)
2193 goto guess_library;
2194 V = Name.slice(c+1, Name.npos);
2195 if (!V.startswith("Versions/"))
2196 goto guess_library;
2197 d = Name.rfind('/', c);
2198 if (d == Name.npos)
2199 Idx = 0;
2200 else
2201 Idx = d+1;
2202 F = Name.slice(Idx, Idx + Foo.size());
2203 DotFramework = Name.slice(Idx + Foo.size(),
2204 Idx + Foo.size() + sizeof(".framework/")-1);
2205 if (F == Foo && DotFramework == ".framework/") {
2206 isFramework = true;
2207 return Foo;
2208 }
2209
2210guess_library:
2211 // pull off the suffix after the "." and make a point to it
2212 a = Name.rfind('.');
2213 if (a == Name.npos || a == 0)
2214 return StringRef();
2215 Dylib = Name.slice(a, Name.npos);
2216 if (Dylib != ".dylib")
2217 goto guess_qtx;
2218
2219 // First pull off the version letter for the form Foo.A.dylib if any.
2220 if (a >= 3) {
2221 Dot = Name.slice(a-2, a-1);
2222 if (Dot == ".")
2223 a = a - 2;
2224 }
2225
2226 b = Name.rfind('/', a);
2227 if (b == Name.npos)
2228 b = 0;
2229 else
2230 b = b+1;
2231 // ignore any suffix after an underbar like Foo_profile.A.dylib
2232 Idx = Name.find('_', b);
2233 if (Idx != Name.npos && Idx != b) {
2234 Lib = Name.slice(b, Idx);
2235 Suffix = Name.slice(Idx, a);
2236 }
2237 else
2238 Lib = Name.slice(b, a);
2239 // There are incorrect library names of the form:
2240 // libATS.A_profile.dylib so check for these.
2241 if (Lib.size() >= 3) {
2242 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2243 if (Dot == ".")
2244 Lib = Lib.slice(0, Lib.size()-2);
2245 }
2246 return Lib;
2247
2248guess_qtx:
2249 Qtx = Name.slice(a, Name.npos);
2250 if (Qtx != ".qtx")
2251 return StringRef();
2252 b = Name.rfind('/', a);
2253 if (b == Name.npos)
2254 Lib = Name.slice(0, a);
2255 else
2256 Lib = Name.slice(b+1, a);
2257 // There are library names of the form: QT.A.qtx so check for these.
2258 if (Lib.size() >= 3) {
2259 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2260 if (Dot == ".")
2261 Lib = Lib.slice(0, Lib.size()-2);
2262 }
2263 return Lib;
2264}
2265
2266// getLibraryShortNameByIndex() is used to get the short name of the library
2267// for an undefined symbol in a linked Mach-O binary that was linked with the
2268// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2269// It is passed the index (0 - based) of the library as translated from
2270// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00002271std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00002272 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00002273 if (Index >= Libraries.size())
2274 return object_error::parse_failed;
2275
Kevin Enderby980b2582014-06-05 21:21:57 +00002276 // If the cache of LibrariesShortNames is not built up do that first for
2277 // all the Libraries.
2278 if (LibrariesShortNames.size() == 0) {
2279 for (unsigned i = 0; i < Libraries.size(); i++) {
2280 MachO::dylib_command D =
Lang Hames697e7cd2016-12-04 01:56:10 +00002281 getStruct<MachO::dylib_command>(*this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00002282 if (D.dylib.name >= D.cmdsize)
2283 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00002284 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00002285 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00002286 if (D.dylib.name+Name.size() >= D.cmdsize)
2287 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00002288 StringRef Suffix;
2289 bool isFramework;
2290 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00002291 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00002292 LibrariesShortNames.push_back(Name);
2293 else
2294 LibrariesShortNames.push_back(shortName);
2295 }
2296 }
2297
2298 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00002299 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00002300}
2301
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00002302uint32_t MachOObjectFile::getLibraryCount() const {
2303 return Libraries.size();
2304}
2305
Rafael Espindola76ad2322015-07-06 14:55:37 +00002306section_iterator
2307MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2308 DataRefImpl Sec;
2309 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2310 return section_iterator(SectionRef(Sec, this));
2311}
2312
Peter Collingbourne435890a2016-11-22 03:38:40 +00002313basic_symbol_iterator MachOObjectFile::symbol_begin() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00002314 DataRefImpl DRI;
2315 MachO::symtab_command Symtab = getSymtabLoadCommand();
2316 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2317 return basic_symbol_iterator(SymbolRef(DRI, this));
2318
Lang Hames36072da2014-05-12 21:39:59 +00002319 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002320}
2321
Peter Collingbourne435890a2016-11-22 03:38:40 +00002322basic_symbol_iterator MachOObjectFile::symbol_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002323 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00002324 MachO::symtab_command Symtab = getSymtabLoadCommand();
2325 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002326 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00002327
Rafael Espindola75c30362013-04-24 19:47:55 +00002328 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002329 sizeof(MachO::nlist_64) :
2330 sizeof(MachO::nlist);
2331 unsigned Offset = Symtab.symoff +
2332 Symtab.nsyms * SymbolTableEntrySize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002333 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002334 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002335}
2336
Lang Hames36072da2014-05-12 21:39:59 +00002337basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00002338 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00002339 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002340 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00002341 unsigned SymbolTableEntrySize =
2342 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00002343 DataRefImpl DRI;
Lang Hames697e7cd2016-12-04 01:56:10 +00002344 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Lang Hames36072da2014-05-12 21:39:59 +00002345 DRI.p += Index * SymbolTableEntrySize;
2346 return basic_symbol_iterator(SymbolRef(DRI, this));
2347}
2348
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002349uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2350 MachO::symtab_command Symtab = getSymtabLoadCommand();
2351 if (!SymtabLoadCmd)
2352 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2353 unsigned SymbolTableEntrySize =
2354 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2355 DataRefImpl DRIstart;
Lang Hames697e7cd2016-12-04 01:56:10 +00002356 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002357 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2358 return Index;
2359}
2360
Rafael Espindolab5155a52014-02-10 20:24:04 +00002361section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002362 DataRefImpl DRI;
2363 return section_iterator(SectionRef(DRI, this));
2364}
2365
Rafael Espindolab5155a52014-02-10 20:24:04 +00002366section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002367 DataRefImpl DRI;
2368 DRI.d.a = Sections.size();
2369 return section_iterator(SectionRef(DRI, this));
2370}
2371
Rafael Espindola56f976f2013-04-18 18:08:55 +00002372uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00002373 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00002374}
2375
Rafael Espindola56f976f2013-04-18 18:08:55 +00002376StringRef MachOObjectFile::getFileFormatName() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002377 unsigned CPUType = getCPUType(*this);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002378 if (!is64Bit()) {
2379 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002380 case MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002381 return "Mach-O 32-bit i386";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002382 case MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002383 return "Mach-O arm";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002384 case MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002385 return "Mach-O 32-bit ppc";
2386 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002387 return "Mach-O 32-bit unknown";
2388 }
2389 }
2390
Rafael Espindola56f976f2013-04-18 18:08:55 +00002391 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002392 case MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002393 return "Mach-O 64-bit x86-64";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002394 case MachO::CPU_TYPE_ARM64:
Tim Northover00ed9962014-03-29 10:18:08 +00002395 return "Mach-O arm64";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002396 case MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002397 return "Mach-O 64-bit ppc64";
2398 default:
2399 return "Mach-O 64-bit unknown";
2400 }
2401}
2402
Alexey Samsonove6388e62013-06-18 15:03:28 +00002403Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2404 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002405 case MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002406 return Triple::x86;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002407 case MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002408 return Triple::x86_64;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002409 case MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002410 return Triple::arm;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002411 case MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00002412 return Triple::aarch64;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002413 case MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002414 return Triple::ppc;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002415 case MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002416 return Triple::ppc64;
2417 default:
2418 return Triple::UnknownArch;
2419 }
2420}
2421
Tim Northover9e8eb412016-04-22 23:21:13 +00002422Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
Kevin Enderby59343a92016-12-16 22:54:02 +00002423 const char **McpuDefault,
2424 const char **ArchFlag) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002425 if (McpuDefault)
2426 *McpuDefault = nullptr;
Kevin Enderby59343a92016-12-16 22:54:02 +00002427 if (ArchFlag)
2428 *ArchFlag = nullptr;
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002429
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002430 switch (CPUType) {
2431 case MachO::CPU_TYPE_I386:
2432 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2433 case MachO::CPU_SUBTYPE_I386_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002434 if (ArchFlag)
2435 *ArchFlag = "i386";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002436 return Triple("i386-apple-darwin");
2437 default:
2438 return Triple();
2439 }
2440 case MachO::CPU_TYPE_X86_64:
2441 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2442 case MachO::CPU_SUBTYPE_X86_64_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002443 if (ArchFlag)
2444 *ArchFlag = "x86_64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002445 return Triple("x86_64-apple-darwin");
2446 case MachO::CPU_SUBTYPE_X86_64_H:
Kevin Enderby59343a92016-12-16 22:54:02 +00002447 if (ArchFlag)
2448 *ArchFlag = "x86_64h";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002449 return Triple("x86_64h-apple-darwin");
2450 default:
2451 return Triple();
2452 }
2453 case MachO::CPU_TYPE_ARM:
2454 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2455 case MachO::CPU_SUBTYPE_ARM_V4T:
Kevin Enderby59343a92016-12-16 22:54:02 +00002456 if (ArchFlag)
2457 *ArchFlag = "armv4t";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002458 return Triple("armv4t-apple-darwin");
2459 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
Kevin Enderby59343a92016-12-16 22:54:02 +00002460 if (ArchFlag)
2461 *ArchFlag = "armv5e";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002462 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002463 case MachO::CPU_SUBTYPE_ARM_XSCALE:
Kevin Enderby59343a92016-12-16 22:54:02 +00002464 if (ArchFlag)
2465 *ArchFlag = "xscale";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002466 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002467 case MachO::CPU_SUBTYPE_ARM_V6:
Kevin Enderby59343a92016-12-16 22:54:02 +00002468 if (ArchFlag)
2469 *ArchFlag = "armv6";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002470 return Triple("armv6-apple-darwin");
2471 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002472 if (McpuDefault)
2473 *McpuDefault = "cortex-m0";
Kevin Enderby59343a92016-12-16 22:54:02 +00002474 if (ArchFlag)
2475 *ArchFlag = "armv6m";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002476 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002477 case MachO::CPU_SUBTYPE_ARM_V7:
Kevin Enderby59343a92016-12-16 22:54:02 +00002478 if (ArchFlag)
2479 *ArchFlag = "armv7";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002480 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002481 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002482 if (McpuDefault)
2483 *McpuDefault = "cortex-m4";
Kevin Enderby59343a92016-12-16 22:54:02 +00002484 if (ArchFlag)
2485 *ArchFlag = "armv7em";
Tim Northover9e8eb412016-04-22 23:21:13 +00002486 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002487 case MachO::CPU_SUBTYPE_ARM_V7K:
Kevin Enderby7a165752017-01-24 23:41:04 +00002488 if (McpuDefault)
2489 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002490 if (ArchFlag)
2491 *ArchFlag = "armv7k";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002492 return Triple("armv7k-apple-darwin");
2493 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002494 if (McpuDefault)
2495 *McpuDefault = "cortex-m3";
Kevin Enderby59343a92016-12-16 22:54:02 +00002496 if (ArchFlag)
2497 *ArchFlag = "armv7m";
Tim Northover9e8eb412016-04-22 23:21:13 +00002498 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002499 case MachO::CPU_SUBTYPE_ARM_V7S:
Kevin Enderby7a165752017-01-24 23:41:04 +00002500 if (McpuDefault)
2501 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002502 if (ArchFlag)
2503 *ArchFlag = "armv7s";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002504 return Triple("armv7s-apple-darwin");
2505 default:
2506 return Triple();
2507 }
2508 case MachO::CPU_TYPE_ARM64:
2509 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2510 case MachO::CPU_SUBTYPE_ARM64_ALL:
Kevin Enderbydc412cc2017-02-10 19:27:10 +00002511 if (McpuDefault)
2512 *McpuDefault = "cyclone";
Kevin Enderby59343a92016-12-16 22:54:02 +00002513 if (ArchFlag)
2514 *ArchFlag = "arm64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002515 return Triple("arm64-apple-darwin");
2516 default:
2517 return Triple();
2518 }
2519 case MachO::CPU_TYPE_POWERPC:
2520 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2521 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002522 if (ArchFlag)
2523 *ArchFlag = "ppc";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002524 return Triple("ppc-apple-darwin");
2525 default:
2526 return Triple();
2527 }
2528 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00002529 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002530 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002531 if (ArchFlag)
2532 *ArchFlag = "ppc64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002533 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002534 default:
2535 return Triple();
2536 }
2537 default:
2538 return Triple();
2539 }
2540}
2541
2542Triple MachOObjectFile::getHostArch() {
2543 return Triple(sys::getDefaultTargetTriple());
2544}
2545
Rafael Espindola72318b42014-08-08 16:30:17 +00002546bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2547 return StringSwitch<bool>(ArchFlag)
2548 .Case("i386", true)
2549 .Case("x86_64", true)
2550 .Case("x86_64h", true)
2551 .Case("armv4t", true)
2552 .Case("arm", true)
2553 .Case("armv5e", true)
2554 .Case("armv6", true)
2555 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00002556 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002557 .Case("armv7em", true)
2558 .Case("armv7k", true)
2559 .Case("armv7m", true)
2560 .Case("armv7s", true)
2561 .Case("arm64", true)
2562 .Case("ppc", true)
2563 .Case("ppc64", true)
2564 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002565}
2566
Alexey Samsonove6388e62013-06-18 15:03:28 +00002567unsigned MachOObjectFile::getArch() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002568 return getArch(getCPUType(*this));
Alexey Samsonove6388e62013-06-18 15:03:28 +00002569}
2570
Tim Northover9e8eb412016-04-22 23:21:13 +00002571Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2572 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002573}
2574
Rui Ueyamabc654b12013-09-27 21:47:05 +00002575relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002576 DataRefImpl DRI;
2577 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002578 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002579}
2580
Rui Ueyamabc654b12013-09-27 21:47:05 +00002581relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002582 DataRefImpl DRI;
2583 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002584 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002585}
2586
Kevin Enderby273ae012013-06-06 17:20:50 +00002587dice_iterator MachOObjectFile::begin_dices() const {
2588 DataRefImpl DRI;
2589 if (!DataInCodeLoadCmd)
2590 return dice_iterator(DiceRef(DRI, this));
2591
Charles Davis8bdfafd2013-09-01 04:28:48 +00002592 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
Lang Hames697e7cd2016-12-04 01:56:10 +00002593 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00002594 return dice_iterator(DiceRef(DRI, this));
2595}
2596
2597dice_iterator MachOObjectFile::end_dices() const {
2598 DataRefImpl DRI;
2599 if (!DataInCodeLoadCmd)
2600 return dice_iterator(DiceRef(DRI, this));
2601
Charles Davis8bdfafd2013-09-01 04:28:48 +00002602 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2603 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002604 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Kevin Enderby273ae012013-06-06 17:20:50 +00002605 return dice_iterator(DiceRef(DRI, this));
2606}
2607
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002608ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
2609 ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002610
2611void ExportEntry::moveToFirst() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002612 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002613 pushNode(0);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002614 if (*E)
2615 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002616 pushDownUntilBottom();
2617}
2618
2619void ExportEntry::moveToEnd() {
2620 Stack.clear();
2621 Done = true;
2622}
2623
2624bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002625 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002626 if (Done || Other.Done)
2627 return (Done == Other.Done);
2628 // Not equal if different stack sizes.
2629 if (Stack.size() != Other.Stack.size())
2630 return false;
2631 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00002632 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00002633 return false;
2634 // Equal if all nodes in both stacks match.
2635 for (unsigned i=0; i < Stack.size(); ++i) {
2636 if (Stack[i].Start != Other.Stack[i].Start)
2637 return false;
2638 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002639 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002640}
2641
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002642uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002643 unsigned Count;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002644 uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002645 Ptr += Count;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002646 if (Ptr > Trie.end())
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002647 Ptr = Trie.end();
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002648 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002649}
2650
2651StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00002652 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002653}
2654
2655uint64_t ExportEntry::flags() const {
2656 return Stack.back().Flags;
2657}
2658
2659uint64_t ExportEntry::address() const {
2660 return Stack.back().Address;
2661}
2662
2663uint64_t ExportEntry::other() const {
2664 return Stack.back().Other;
2665}
2666
2667StringRef ExportEntry::otherName() const {
2668 const char* ImportName = Stack.back().ImportName;
2669 if (ImportName)
2670 return StringRef(ImportName);
2671 return StringRef();
2672}
2673
2674uint32_t ExportEntry::nodeOffset() const {
2675 return Stack.back().Start - Trie.begin();
2676}
2677
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002678ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002679 : Start(Ptr), Current(Ptr) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002680
2681void ExportEntry::pushNode(uint64_t offset) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002682 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002683 const uint8_t *Ptr = Trie.begin() + offset;
2684 NodeState State(Ptr);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002685 const char *error;
2686 uint64_t ExportInfoSize = readULEB128(State.Current, &error);
2687 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002688 *E = malformedError("export info size " + Twine(error) +
2689 " in export trie data at node: 0x" +
2690 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002691 moveToEnd();
2692 return;
2693 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002694 State.IsExportNode = (ExportInfoSize != 0);
2695 const uint8_t* Children = State.Current + ExportInfoSize;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002696 if (Children > Trie.end()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002697 *E = malformedError(
2698 "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
2699 " in export trie data at node: 0x" + Twine::utohexstr(offset) +
2700 " too big and extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002701 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) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002708 *E = malformedError("flags " + Twine(error) +
2709 " in export trie data at node: 0x" +
2710 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002711 moveToEnd();
2712 return;
2713 }
2714 uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
2715 if (State.Flags != 0 &&
2716 (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
2717 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
2718 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002719 *E = malformedError(
2720 "unsupported exported symbol kind: " + Twine((int)Kind) +
2721 " in flags: 0x" + Twine::utohexstr(State.Flags) +
2722 " in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002723 moveToEnd();
2724 return;
2725 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002726 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2727 State.Address = 0;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002728 State.Other = readULEB128(State.Current, &error); // dylib ordinal
2729 if (error) {
2730 *E = malformedError("dylib ordinal of re-export " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002731 " in export trie data at node: 0x" +
2732 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002733 moveToEnd();
2734 return;
2735 }
2736 if (O != nullptr) {
2737 if (State.Other > O->getLibraryCount()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002738 *E = malformedError(
2739 "bad library ordinal: " + Twine((int)State.Other) + " (max " +
2740 Twine((int)O->getLibraryCount()) +
2741 ") in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002742 moveToEnd();
2743 return;
2744 }
2745 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002746 State.ImportName = reinterpret_cast<const char*>(State.Current);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002747 if (*State.ImportName == '\0') {
2748 State.Current++;
2749 } else {
2750 const uint8_t *End = State.Current + 1;
2751 if (End >= Trie.end()) {
2752 *E = malformedError("import name of re-export in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002753 "node: 0x" +
2754 Twine::utohexstr(offset) +
2755 " starts past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002756 moveToEnd();
2757 return;
2758 }
2759 while(*End != '\0' && End < Trie.end())
2760 End++;
2761 if (*End != '\0') {
2762 *E = malformedError("import name of re-export in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002763 "node: 0x" +
2764 Twine::utohexstr(offset) +
2765 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002766 moveToEnd();
2767 return;
2768 }
2769 State.Current = End + 1;
2770 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002771 } else {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002772 State.Address = readULEB128(State.Current, &error);
2773 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002774 *E = malformedError("address " + Twine(error) +
2775 " in export trie data at node: 0x" +
2776 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002777 moveToEnd();
2778 return;
2779 }
2780 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
2781 State.Other = readULEB128(State.Current, &error);
2782 if (error) {
2783 *E = malformedError("resolver of stub and resolver " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002784 " in export trie data at node: 0x" +
2785 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002786 moveToEnd();
2787 return;
2788 }
2789 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002790 }
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002791 if(ExportStart + ExportInfoSize != State.Current) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002792 *E = malformedError(
2793 "inconsistant export info size: 0x" +
2794 Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
2795 Twine::utohexstr(State.Current - ExportStart) +
2796 " in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002797 moveToEnd();
2798 return;
2799 }
2800 }
Kevin Enderby8100cde2017-07-24 20:33:41 +00002801 State.ChildCount = *Children;
2802 if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002803 *E = malformedError("byte for count of childern in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002804 "node: 0x" +
2805 Twine::utohexstr(offset) +
2806 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002807 moveToEnd();
2808 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002809 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002810 State.Current = Children + 1;
2811 State.NextChildIndex = 0;
2812 State.ParentStringLength = CumulativeString.size();
2813 Stack.push_back(State);
2814}
2815
2816void ExportEntry::pushDownUntilBottom() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002817 ErrorAsOutParameter ErrAsOutParam(E);
2818 const char *error;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002819 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2820 NodeState &Top = Stack.back();
2821 CumulativeString.resize(Top.ParentStringLength);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002822 for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002823 char C = *Top.Current;
2824 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002825 }
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002826 if (Top.Current >= Trie.end()) {
2827 *E = malformedError("edge sub-string in export trie data at node: 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002828 Twine::utohexstr(Top.Start - Trie.begin()) +
2829 " for child #" + Twine((int)Top.NextChildIndex) +
2830 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002831 moveToEnd();
2832 return;
2833 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002834 Top.Current += 1;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002835 uint64_t childNodeIndex = readULEB128(Top.Current, &error);
2836 if (error) {
2837 *E = malformedError("child node offset " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002838 " in export trie data at node: 0x" +
2839 Twine::utohexstr(Top.Start - Trie.begin()));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002840 moveToEnd();
2841 return;
2842 }
2843 for (const NodeState &node : nodes()) {
2844 if (node.Start == Trie.begin() + childNodeIndex){
2845 *E = malformedError("loop in childern in export trie data at node: 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002846 Twine::utohexstr(Top.Start - Trie.begin()) +
2847 " back to node: 0x" +
2848 Twine::utohexstr(childNodeIndex));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002849 moveToEnd();
2850 return;
2851 }
2852 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002853 Top.NextChildIndex += 1;
2854 pushNode(childNodeIndex);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002855 if (*E)
2856 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002857 }
2858 if (!Stack.back().IsExportNode) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002859 *E = malformedError("node is not an export node in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002860 "node: 0x" +
2861 Twine::utohexstr(Stack.back().Start - Trie.begin()));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002862 moveToEnd();
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002863 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002864 }
2865}
2866
2867// We have a trie data structure and need a way to walk it that is compatible
2868// with the C++ iterator model. The solution is a non-recursive depth first
2869// traversal where the iterator contains a stack of parent nodes along with a
2870// string that is the accumulation of all edge strings along the parent chain
2871// to this point.
2872//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00002873// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00002874// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002875// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002876//
2877// The algorithm for moveNext() is to keep moving down the leftmost unvisited
2878// child until hitting a node with no children (which is an export node or
2879// else the trie is malformed). On the way down, each node is pushed on the
2880// stack ivar. If there is no more ways down, it pops up one and tries to go
2881// down a sibling path until a childless node is reached.
2882void ExportEntry::moveNext() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002883 assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
2884 if (!Stack.back().IsExportNode) {
2885 *E = malformedError("node is not an export node in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002886 "node: 0x" +
2887 Twine::utohexstr(Stack.back().Start - Trie.begin()));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002888 moveToEnd();
2889 return;
2890 }
2891
2892 Stack.pop_back();
2893 while (!Stack.empty()) {
2894 NodeState &Top = Stack.back();
2895 if (Top.NextChildIndex < Top.ChildCount) {
2896 pushDownUntilBottom();
2897 // Now at the next export node.
2898 return;
2899 } else {
2900 if (Top.IsExportNode) {
2901 // This node has no children but is itself an export node.
2902 CumulativeString.resize(Top.ParentStringLength);
2903 return;
2904 }
2905 Stack.pop_back();
2906 }
2907 }
2908 Done = true;
2909}
2910
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002911iterator_range<export_iterator>
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002912MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
2913 const MachOObjectFile *O) {
2914 ExportEntry Start(&E, O, Trie);
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002915 if (Trie.empty())
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00002916 Start.moveToEnd();
2917 else
2918 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002919
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002920 ExportEntry Finish(&E, O, Trie);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002921 Finish.moveToEnd();
2922
Craig Topper15576e12015-12-06 05:08:07 +00002923 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002924}
2925
Alexander Shaposhnikove5740342017-07-29 00:30:45 +00002926iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
2927 return exports(Err, getDyldInfoExportsTrie(), this);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002928}
2929
Kevin Enderbya8d256c2017-03-20 19:46:55 +00002930MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
2931 ArrayRef<uint8_t> Bytes, bool is64Bit)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002932 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
2933 PointerSize(is64Bit ? 8 : 4) {}
Nick Kledzikac431442014-09-12 21:34:15 +00002934
2935void MachORebaseEntry::moveToFirst() {
2936 Ptr = Opcodes.begin();
2937 moveNext();
2938}
2939
2940void MachORebaseEntry::moveToEnd() {
2941 Ptr = Opcodes.end();
2942 RemainingLoopCount = 0;
2943 Done = true;
2944}
2945
2946void MachORebaseEntry::moveNext() {
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002947 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikac431442014-09-12 21:34:15 +00002948 // If in the middle of some loop, move to next rebasing in loop.
2949 SegmentOffset += AdvanceAmount;
2950 if (RemainingLoopCount) {
2951 --RemainingLoopCount;
2952 return;
2953 }
Juergen Ributzkacad12492017-03-30 19:56:50 +00002954 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
2955 // pointer size. Therefore it is possible to reach the end without ever having
2956 // seen REBASE_OPCODE_DONE.
2957 if (Ptr == Opcodes.end()) {
Nick Kledzikac431442014-09-12 21:34:15 +00002958 Done = true;
2959 return;
2960 }
2961 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002962 while (More) {
Nick Kledzikac431442014-09-12 21:34:15 +00002963 // Parse next opcode and set up next loop.
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002964 const uint8_t *OpcodeStart = Ptr;
Nick Kledzikac431442014-09-12 21:34:15 +00002965 uint8_t Byte = *Ptr++;
2966 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
2967 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002968 uint32_t Count, Skip;
2969 const char *error = nullptr;
Nick Kledzikac431442014-09-12 21:34:15 +00002970 switch (Opcode) {
2971 case MachO::REBASE_OPCODE_DONE:
2972 More = false;
2973 Done = true;
2974 moveToEnd();
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002975 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
Nick Kledzikac431442014-09-12 21:34:15 +00002976 break;
2977 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
2978 RebaseType = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002979 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002980 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
2981 Twine((int)RebaseType) + " for opcode at: 0x" +
2982 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
2983 moveToEnd();
2984 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002985 }
Nick Kledzikac431442014-09-12 21:34:15 +00002986 DEBUG_WITH_TYPE(
2987 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002988 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
2989 << "RebaseType=" << (int) RebaseType << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00002990 break;
2991 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2992 SegmentIndex = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002993 SegmentOffset = readULEB128(&error);
2994 if (error) {
2995 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002996 Twine(error) + " for opcode at: 0x" +
2997 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002998 moveToEnd();
2999 return;
3000 }
3001 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3002 true);
3003 if (error) {
3004 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003005 Twine(error) + " for opcode at: 0x" +
3006 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003007 moveToEnd();
3008 return;
3009 }
Nick Kledzikac431442014-09-12 21:34:15 +00003010 DEBUG_WITH_TYPE(
3011 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003012 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3013 << "SegmentIndex=" << SegmentIndex << ", "
3014 << format("SegmentOffset=0x%06X", SegmentOffset)
3015 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003016 break;
3017 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003018 SegmentOffset += readULEB128(&error);
3019 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003020 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3021 " for opcode at: 0x" +
3022 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003023 moveToEnd();
3024 return;
3025 }
3026 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3027 true);
3028 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003029 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3030 " for opcode at: 0x" +
3031 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003032 moveToEnd();
3033 return;
3034 }
Nick Kledzikac431442014-09-12 21:34:15 +00003035 DEBUG_WITH_TYPE("mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003036 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3037 << format("SegmentOffset=0x%06X",
3038 SegmentOffset) << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003039 break;
3040 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003041 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3042 true);
3043 if (error) {
3044 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003045 Twine(error) + " for opcode at: 0x" +
3046 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003047 moveToEnd();
3048 return;
3049 }
Nick Kledzikac431442014-09-12 21:34:15 +00003050 SegmentOffset += ImmValue * PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003051 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3052 false);
3053 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003054 *E =
3055 malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3056 " (after adding immediate times the pointer size) " +
3057 Twine(error) + " for opcode at: 0x" +
3058 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003059 moveToEnd();
3060 return;
3061 }
Nick Kledzikac431442014-09-12 21:34:15 +00003062 DEBUG_WITH_TYPE("mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003063 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3064 << format("SegmentOffset=0x%06X",
3065 SegmentOffset) << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003066 break;
3067 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003068 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3069 true);
3070 if (error) {
3071 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003072 Twine(error) + " for opcode at: 0x" +
3073 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003074 moveToEnd();
3075 return;
3076 }
Nick Kledzikac431442014-09-12 21:34:15 +00003077 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003078 Skip = 0;
3079 Count = ImmValue;
3080 if (ImmValue != 0)
3081 RemainingLoopCount = ImmValue - 1;
3082 else
3083 RemainingLoopCount = 0;
3084 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3085 SegmentIndex, SegmentOffset);
3086 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003087 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3088 Twine(error) + " for opcode at: 0x" +
3089 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003090 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003091 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003092 }
Nick Kledzikac431442014-09-12 21:34:15 +00003093 DEBUG_WITH_TYPE(
3094 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003095 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3096 << format("SegmentOffset=0x%06X", SegmentOffset)
3097 << ", AdvanceAmount=" << AdvanceAmount
3098 << ", RemainingLoopCount=" << RemainingLoopCount
3099 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003100 return;
3101 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003102 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3103 true);
3104 if (error) {
3105 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003106 Twine(error) + " for opcode at: 0x" +
3107 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003108 moveToEnd();
3109 return;
3110 }
Nick Kledzikac431442014-09-12 21:34:15 +00003111 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003112 Skip = 0;
3113 Count = readULEB128(&error);
3114 if (error) {
3115 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003116 Twine(error) + " for opcode at: 0x" +
3117 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003118 moveToEnd();
3119 return;
3120 }
3121 if (Count != 0)
3122 RemainingLoopCount = Count - 1;
3123 else
3124 RemainingLoopCount = 0;
3125 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3126 SegmentIndex, SegmentOffset);
3127 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003128 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3129 Twine(error) + " for opcode at: 0x" +
3130 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003131 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003132 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003133 }
Nick Kledzikac431442014-09-12 21:34:15 +00003134 DEBUG_WITH_TYPE(
3135 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003136 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3137 << format("SegmentOffset=0x%06X", SegmentOffset)
3138 << ", AdvanceAmount=" << AdvanceAmount
3139 << ", RemainingLoopCount=" << RemainingLoopCount
3140 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003141 return;
3142 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003143 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3144 true);
3145 if (error) {
3146 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003147 Twine(error) + " for opcode at: 0x" +
3148 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003149 moveToEnd();
3150 return;
3151 }
3152 Skip = readULEB128(&error);
3153 if (error) {
3154 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003155 Twine(error) + " for opcode at: 0x" +
3156 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003157 moveToEnd();
3158 return;
3159 }
3160 AdvanceAmount = Skip + PointerSize;
3161 Count = 1;
Nick Kledzikac431442014-09-12 21:34:15 +00003162 RemainingLoopCount = 0;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003163 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3164 SegmentIndex, SegmentOffset);
3165 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003166 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3167 Twine(error) + " for opcode at: 0x" +
3168 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003169 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003170 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003171 }
Nick Kledzikac431442014-09-12 21:34:15 +00003172 DEBUG_WITH_TYPE(
3173 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003174 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3175 << format("SegmentOffset=0x%06X", SegmentOffset)
3176 << ", AdvanceAmount=" << AdvanceAmount
3177 << ", RemainingLoopCount=" << RemainingLoopCount
3178 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003179 return;
3180 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003181 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3182 true);
3183 if (error) {
3184 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003185 "ULEB " +
3186 Twine(error) + " for opcode at: 0x" +
3187 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003188 moveToEnd();
3189 return;
3190 }
3191 Count = readULEB128(&error);
3192 if (error) {
3193 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003194 "ULEB " +
3195 Twine(error) + " for opcode at: 0x" +
3196 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003197 moveToEnd();
3198 return;
3199 }
3200 if (Count != 0)
3201 RemainingLoopCount = Count - 1;
3202 else
3203 RemainingLoopCount = 0;
3204 Skip = readULEB128(&error);
3205 if (error) {
3206 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003207 "ULEB " +
3208 Twine(error) + " for opcode at: 0x" +
3209 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003210 moveToEnd();
3211 return;
3212 }
3213 AdvanceAmount = Skip + PointerSize;
3214
3215 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3216 SegmentIndex, SegmentOffset);
3217 if (error) {
3218 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003219 "ULEB " +
3220 Twine(error) + " for opcode at: 0x" +
3221 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003222 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003223 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003224 }
Nick Kledzikac431442014-09-12 21:34:15 +00003225 DEBUG_WITH_TYPE(
3226 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003227 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3228 << format("SegmentOffset=0x%06X", SegmentOffset)
3229 << ", AdvanceAmount=" << AdvanceAmount
3230 << ", RemainingLoopCount=" << RemainingLoopCount
3231 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003232 return;
3233 default:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003234 *E = malformedError("bad rebase info (bad opcode value 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003235 Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3236 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003237 moveToEnd();
3238 return;
Nick Kledzikac431442014-09-12 21:34:15 +00003239 }
3240 }
3241}
3242
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003243uint64_t MachORebaseEntry::readULEB128(const char **error) {
Nick Kledzikac431442014-09-12 21:34:15 +00003244 unsigned Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003245 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzikac431442014-09-12 21:34:15 +00003246 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003247 if (Ptr > Opcodes.end())
Nick Kledzikac431442014-09-12 21:34:15 +00003248 Ptr = Opcodes.end();
Nick Kledzikac431442014-09-12 21:34:15 +00003249 return Result;
3250}
3251
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003252int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzikac431442014-09-12 21:34:15 +00003253
3254uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3255
3256StringRef MachORebaseEntry::typeName() const {
3257 switch (RebaseType) {
3258 case MachO::REBASE_TYPE_POINTER:
3259 return "pointer";
3260 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3261 return "text abs32";
3262 case MachO::REBASE_TYPE_TEXT_PCREL32:
3263 return "text rel32";
3264 }
3265 return "unknown";
3266}
3267
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003268// For use with the SegIndex of a checked Mach-O Rebase entry
3269// to get the segment name.
3270StringRef MachORebaseEntry::segmentName() const {
3271 return O->BindRebaseSegmentName(SegmentIndex);
3272}
3273
3274// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3275// to get the section name.
3276StringRef MachORebaseEntry::sectionName() const {
3277 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3278}
3279
3280// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3281// to get the address.
3282uint64_t MachORebaseEntry::address() const {
3283 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3284}
3285
Nick Kledzikac431442014-09-12 21:34:15 +00003286bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003287#ifdef EXPENSIVE_CHECKS
Nick Kledzikac431442014-09-12 21:34:15 +00003288 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003289#else
3290 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3291#endif
Nick Kledzikac431442014-09-12 21:34:15 +00003292 return (Ptr == Other.Ptr) &&
3293 (RemainingLoopCount == Other.RemainingLoopCount) &&
3294 (Done == Other.Done);
3295}
3296
3297iterator_range<rebase_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003298MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3299 ArrayRef<uint8_t> Opcodes, bool is64) {
3300 if (O->BindRebaseSectionTable == nullptr)
3301 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3302 MachORebaseEntry Start(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003303 Start.moveToFirst();
3304
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003305 MachORebaseEntry Finish(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003306 Finish.moveToEnd();
3307
Craig Topper15576e12015-12-06 05:08:07 +00003308 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00003309}
3310
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003311iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3312 return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
Nick Kledzikac431442014-09-12 21:34:15 +00003313}
3314
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003315MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3316 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003317 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3318 PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
Nick Kledzik56ebef42014-09-16 01:41:51 +00003319
3320void MachOBindEntry::moveToFirst() {
3321 Ptr = Opcodes.begin();
3322 moveNext();
3323}
3324
3325void MachOBindEntry::moveToEnd() {
3326 Ptr = Opcodes.end();
3327 RemainingLoopCount = 0;
3328 Done = true;
3329}
3330
3331void MachOBindEntry::moveNext() {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003332 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003333 // If in the middle of some loop, move to next binding in loop.
3334 SegmentOffset += AdvanceAmount;
3335 if (RemainingLoopCount) {
3336 --RemainingLoopCount;
3337 return;
3338 }
Juergen Ributzkacad12492017-03-30 19:56:50 +00003339 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3340 // pointer size. Therefore it is possible to reach the end without ever having
3341 // seen BIND_OPCODE_DONE.
3342 if (Ptr == Opcodes.end()) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003343 Done = true;
3344 return;
3345 }
3346 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003347 while (More) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003348 // Parse next opcode and set up next loop.
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003349 const uint8_t *OpcodeStart = Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003350 uint8_t Byte = *Ptr++;
3351 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3352 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3353 int8_t SignExtended;
3354 const uint8_t *SymStart;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003355 uint32_t Count, Skip;
3356 const char *error = nullptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003357 switch (Opcode) {
3358 case MachO::BIND_OPCODE_DONE:
3359 if (TableKind == Kind::Lazy) {
3360 // Lazying bindings have a DONE opcode between entries. Need to ignore
3361 // it to advance to next entry. But need not if this is last entry.
3362 bool NotLastEntry = false;
3363 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3364 if (*P) {
3365 NotLastEntry = true;
3366 }
3367 }
3368 if (NotLastEntry)
3369 break;
3370 }
3371 More = false;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003372 moveToEnd();
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003373 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003374 break;
3375 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003376 if (TableKind == Kind::Weak) {
3377 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003378 "weak bind table for opcode at: 0x" +
3379 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003380 moveToEnd();
3381 return;
3382 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003383 Ordinal = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003384 LibraryOrdinalSet = true;
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003385 if (ImmValue > O->getLibraryCount()) {
3386 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003387 "library ordinal: " +
3388 Twine((int)ImmValue) + " (max " +
3389 Twine((int)O->getLibraryCount()) +
3390 ") for opcode at: 0x" +
3391 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003392 moveToEnd();
3393 return;
3394 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003395 DEBUG_WITH_TYPE(
3396 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003397 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3398 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003399 break;
3400 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003401 if (TableKind == Kind::Weak) {
3402 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003403 "weak bind table for opcode at: 0x" +
3404 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003405 moveToEnd();
3406 return;
3407 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003408 Ordinal = readULEB128(&error);
3409 LibraryOrdinalSet = true;
3410 if (error) {
3411 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003412 Twine(error) + " for opcode at: 0x" +
3413 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003414 moveToEnd();
3415 return;
3416 }
3417 if (Ordinal > (int)O->getLibraryCount()) {
3418 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003419 "library ordinal: " +
3420 Twine((int)Ordinal) + " (max " +
3421 Twine((int)O->getLibraryCount()) +
3422 ") for opcode at: 0x" +
3423 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003424 moveToEnd();
3425 return;
3426 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003427 DEBUG_WITH_TYPE(
3428 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003429 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3430 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003431 break;
3432 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003433 if (TableKind == Kind::Weak) {
3434 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003435 "weak bind table for opcode at: 0x" +
3436 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003437 moveToEnd();
3438 return;
3439 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003440 if (ImmValue) {
3441 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3442 Ordinal = SignExtended;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003443 if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3444 *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003445 "special ordinal: " +
3446 Twine((int)Ordinal) + " for opcode at: 0x" +
3447 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003448 moveToEnd();
3449 return;
3450 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003451 } else
3452 Ordinal = 0;
Steven Wu97e2cf82017-05-31 22:17:43 +00003453 LibraryOrdinalSet = true;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003454 DEBUG_WITH_TYPE(
3455 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003456 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3457 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003458 break;
3459 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3460 Flags = ImmValue;
3461 SymStart = Ptr;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003462 while (*Ptr && (Ptr < Opcodes.end())) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003463 ++Ptr;
3464 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003465 if (Ptr == Opcodes.end()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003466 *E = malformedError(
3467 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3468 "symbol name extends past opcodes for opcode at: 0x" +
3469 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3470 moveToEnd();
3471 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003472 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003473 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3474 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00003475 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003476 DEBUG_WITH_TYPE(
3477 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003478 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3479 << "SymbolName=" << SymbolName << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003480 if (TableKind == Kind::Weak) {
3481 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3482 return;
3483 }
3484 break;
3485 case MachO::BIND_OPCODE_SET_TYPE_IMM:
3486 BindType = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003487 if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003488 *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3489 Twine((int)ImmValue) + " for opcode at: 0x" +
3490 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3491 moveToEnd();
3492 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003493 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003494 DEBUG_WITH_TYPE(
3495 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003496 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3497 << "BindType=" << (int)BindType << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003498 break;
3499 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003500 Addend = readSLEB128(&error);
3501 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003502 *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
3503 " for opcode at: 0x" +
3504 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003505 moveToEnd();
3506 return;
3507 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003508 DEBUG_WITH_TYPE(
3509 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003510 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3511 << "Addend=" << Addend << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003512 break;
3513 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3514 SegmentIndex = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003515 SegmentOffset = readULEB128(&error);
3516 if (error) {
3517 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003518 Twine(error) + " for opcode at: 0x" +
3519 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003520 moveToEnd();
3521 return;
3522 }
3523 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3524 if (error) {
3525 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003526 Twine(error) + " for opcode at: 0x" +
3527 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003528 moveToEnd();
3529 return;
3530 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003531 DEBUG_WITH_TYPE(
3532 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003533 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3534 << "SegmentIndex=" << SegmentIndex << ", "
3535 << format("SegmentOffset=0x%06X", SegmentOffset)
3536 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003537 break;
3538 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003539 SegmentOffset += readULEB128(&error);
3540 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003541 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3542 " for opcode at: 0x" +
3543 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003544 moveToEnd();
3545 return;
3546 }
3547 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3548 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003549 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3550 " for opcode at: 0x" +
3551 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003552 moveToEnd();
3553 return;
3554 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003555 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003556 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3557 << format("SegmentOffset=0x%06X",
3558 SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003559 break;
3560 case MachO::BIND_OPCODE_DO_BIND:
3561 AdvanceAmount = PointerSize;
3562 RemainingLoopCount = 0;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003563 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3564 if (error) {
3565 *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003566 " for opcode at: 0x" +
3567 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003568 moveToEnd();
3569 return;
3570 }
3571 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003572 *E = malformedError(
3573 "for BIND_OPCODE_DO_BIND missing preceding "
3574 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3575 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003576 moveToEnd();
3577 return;
3578 }
3579 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003580 *E =
3581 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3582 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3583 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003584 moveToEnd();
3585 return;
3586 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003587 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003588 dbgs() << "BIND_OPCODE_DO_BIND: "
3589 << format("SegmentOffset=0x%06X",
3590 SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003591 return;
3592 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003593 if (TableKind == Kind::Lazy) {
3594 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003595 "lazy bind table for opcode at: 0x" +
3596 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003597 moveToEnd();
3598 return;
3599 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003600 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3601 if (error) {
3602 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003603 Twine(error) + " for opcode at: 0x" +
3604 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003605 moveToEnd();
3606 return;
3607 }
3608 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003609 *E = malformedError(
3610 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3611 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3612 "at: 0x" +
3613 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003614 moveToEnd();
3615 return;
3616 }
3617 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003618 *E = malformedError(
3619 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3620 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3621 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003622 moveToEnd();
3623 return;
3624 }
3625 AdvanceAmount = readULEB128(&error) + PointerSize;
3626 if (error) {
3627 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003628 Twine(error) + " for opcode at: 0x" +
3629 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003630 moveToEnd();
3631 return;
3632 }
3633 // Note, this is not really an error until the next bind but make no sense
3634 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3635 // bind operation.
3636 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3637 AdvanceAmount, false);
3638 if (error) {
3639 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003640 "ULEB) " +
3641 Twine(error) + " for opcode at: 0x" +
3642 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003643 moveToEnd();
3644 return;
3645 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003646 RemainingLoopCount = 0;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003647 DEBUG_WITH_TYPE(
3648 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003649 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3650 << format("SegmentOffset=0x%06X", SegmentOffset)
3651 << ", AdvanceAmount=" << AdvanceAmount
3652 << ", RemainingLoopCount=" << RemainingLoopCount
3653 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003654 return;
3655 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003656 if (TableKind == Kind::Lazy) {
3657 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003658 "allowed in lazy bind table for opcode at: 0x" +
3659 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003660 moveToEnd();
3661 return;
3662 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003663 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3664 if (error) {
3665 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003666 Twine(error) + " for opcode at: 0x" +
3667 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003668 moveToEnd();
3669 return;
3670 }
3671 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003672 *E = malformedError(
3673 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3674 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3675 "opcode at: 0x" +
3676 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003677 moveToEnd();
3678 return;
3679 }
3680 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003681 *E = malformedError(
3682 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3683 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3684 "at: 0x" +
3685 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003686 moveToEnd();
3687 return;
3688 }
Nick Kledzik3b2aa052014-10-18 01:21:02 +00003689 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003690 RemainingLoopCount = 0;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003691 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3692 AdvanceAmount, false);
3693 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003694 *E =
3695 malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3696 " (after adding immediate times the pointer size) " +
3697 Twine(error) + " for opcode at: 0x" +
3698 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003699 moveToEnd();
3700 return;
3701 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003702 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003703 dbgs()
Nick Kledzik56ebef42014-09-16 01:41:51 +00003704 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003705 << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003706 return;
3707 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003708 if (TableKind == Kind::Lazy) {
3709 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003710 "allowed in lazy bind table for opcode at: 0x" +
3711 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003712 moveToEnd();
3713 return;
3714 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003715 Count = readULEB128(&error);
3716 if (Count != 0)
3717 RemainingLoopCount = Count - 1;
3718 else
3719 RemainingLoopCount = 0;
3720 if (error) {
3721 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003722 " (count value) " +
3723 Twine(error) + " for opcode at: 0x" +
3724 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003725 moveToEnd();
3726 return;
3727 }
3728 Skip = readULEB128(&error);
3729 AdvanceAmount = Skip + PointerSize;
3730 if (error) {
3731 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003732 " (skip value) " +
3733 Twine(error) + " for opcode at: 0x" +
3734 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003735 moveToEnd();
3736 return;
3737 }
3738 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3739 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003740 *E =
3741 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3742 Twine(error) + " for opcode at: 0x" +
3743 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003744 moveToEnd();
3745 return;
3746 }
3747 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003748 *E = malformedError(
3749 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3750 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3751 "opcode at: 0x" +
3752 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003753 moveToEnd();
3754 return;
3755 }
3756 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003757 *E = malformedError(
3758 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3759 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3760 "at: 0x" +
3761 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003762 moveToEnd();
3763 return;
3764 }
3765 error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
3766 SegmentIndex, SegmentOffset);
3767 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003768 *E =
3769 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3770 Twine(error) + " for opcode at: 0x" +
3771 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003772 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003773 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003774 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003775 DEBUG_WITH_TYPE(
3776 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003777 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3778 << format("SegmentOffset=0x%06X", SegmentOffset)
3779 << ", AdvanceAmount=" << AdvanceAmount
3780 << ", RemainingLoopCount=" << RemainingLoopCount
3781 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003782 return;
3783 default:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003784 *E = malformedError("bad bind info (bad opcode value 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003785 Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3786 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003787 moveToEnd();
3788 return;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003789 }
3790 }
3791}
3792
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003793uint64_t MachOBindEntry::readULEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003794 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003795 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003796 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003797 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003798 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003799 return Result;
3800}
3801
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003802int64_t MachOBindEntry::readSLEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003803 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003804 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003805 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003806 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003807 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003808 return Result;
3809}
3810
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003811int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003812
3813uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3814
3815StringRef MachOBindEntry::typeName() const {
3816 switch (BindType) {
3817 case MachO::BIND_TYPE_POINTER:
3818 return "pointer";
3819 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3820 return "text abs32";
3821 case MachO::BIND_TYPE_TEXT_PCREL32:
3822 return "text rel32";
3823 }
3824 return "unknown";
3825}
3826
3827StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3828
3829int64_t MachOBindEntry::addend() const { return Addend; }
3830
3831uint32_t MachOBindEntry::flags() const { return Flags; }
3832
3833int MachOBindEntry::ordinal() const { return Ordinal; }
3834
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003835// For use with the SegIndex of a checked Mach-O Bind entry
3836// to get the segment name.
3837StringRef MachOBindEntry::segmentName() const {
3838 return O->BindRebaseSegmentName(SegmentIndex);
3839}
3840
3841// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3842// to get the section name.
3843StringRef MachOBindEntry::sectionName() const {
3844 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3845}
3846
3847// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3848// to get the address.
3849uint64_t MachOBindEntry::address() const {
3850 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3851}
3852
Nick Kledzik56ebef42014-09-16 01:41:51 +00003853bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003854#ifdef EXPENSIVE_CHECKS
Nick Kledzik56ebef42014-09-16 01:41:51 +00003855 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003856#else
3857 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3858#endif
Nick Kledzik56ebef42014-09-16 01:41:51 +00003859 return (Ptr == Other.Ptr) &&
3860 (RemainingLoopCount == Other.RemainingLoopCount) &&
3861 (Done == Other.Done);
3862}
3863
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003864// Build table of sections so SegIndex/SegOffset pairs can be translated.
3865BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
3866 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
3867 StringRef CurSegName;
3868 uint64_t CurSegAddress;
3869 for (const SectionRef &Section : Obj->sections()) {
3870 SectionInfo Info;
3871 Section.getName(Info.SectionName);
3872 Info.Address = Section.getAddress();
3873 Info.Size = Section.getSize();
3874 Info.SegmentName =
3875 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
3876 if (!Info.SegmentName.equals(CurSegName)) {
3877 ++CurSegIndex;
3878 CurSegName = Info.SegmentName;
3879 CurSegAddress = Info.Address;
3880 }
3881 Info.SegmentIndex = CurSegIndex - 1;
3882 Info.OffsetInSegment = Info.Address - CurSegAddress;
3883 Info.SegmentStartAddress = CurSegAddress;
3884 Sections.push_back(Info);
3885 }
3886 MaxSegIndex = CurSegIndex;
3887}
3888
3889// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003890// validate a MachOBindEntry or MachORebaseEntry.
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003891const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
3892 uint64_t SegOffset,
3893 bool endInvalid) {
3894 if (SegIndex == -1)
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003895 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003896 if (SegIndex >= MaxSegIndex)
3897 return "bad segIndex (too large)";
3898 for (const SectionInfo &SI : Sections) {
3899 if (SI.SegmentIndex != SegIndex)
3900 continue;
3901 if (SI.OffsetInSegment > SegOffset)
3902 continue;
3903 if (SegOffset > (SI.OffsetInSegment + SI.Size))
3904 continue;
3905 if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
3906 continue;
3907 return nullptr;
3908 }
3909 return "bad segOffset, too large";
3910}
3911
3912// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003913// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
3914// MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
3915// REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
3916// been already checked.
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003917const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
3918 uint8_t PointerSize,
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003919 int32_t SegIndex,
3920 uint64_t SegOffset) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003921 const SectionInfo &SI = findSection(SegIndex, SegOffset);
3922 uint64_t addr = SI.SegmentStartAddress + SegOffset;
3923 if (addr >= SI.Address + SI.Size)
3924 return "bad segOffset, too large";
3925 uint64_t i = 0;
3926 if (Count > 1)
3927 i = (Skip + PointerSize) * (Count - 1);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003928 else if (Count == 1)
3929 i = Skip + PointerSize;
3930 if (addr + i >= SI.Address + SI.Size) {
3931 // For rebase opcodes they can step from one section to another.
3932 uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
3933 const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
3934 if (error)
3935 return "bad count and skip, too large";
3936 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003937 return nullptr;
3938}
3939
3940// For use with the SegIndex of a checked Mach-O Bind or Rebase entry
3941// to get the segment name.
3942StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
3943 for (const SectionInfo &SI : Sections) {
3944 if (SI.SegmentIndex == SegIndex)
3945 return SI.SegmentName;
3946 }
3947 llvm_unreachable("invalid SegIndex");
3948}
3949
3950// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3951// to get the SectionInfo.
3952const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
3953 int32_t SegIndex, uint64_t SegOffset) {
3954 for (const SectionInfo &SI : Sections) {
3955 if (SI.SegmentIndex != SegIndex)
3956 continue;
3957 if (SI.OffsetInSegment > SegOffset)
3958 continue;
3959 if (SegOffset >= (SI.OffsetInSegment + SI.Size))
3960 continue;
3961 return SI;
3962 }
3963 llvm_unreachable("SegIndex and SegOffset not in any section");
3964}
3965
3966// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3967// entry to get the section name.
3968StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
3969 uint64_t SegOffset) {
3970 return findSection(SegIndex, SegOffset).SectionName;
3971}
3972
3973// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3974// entry to get the address.
3975uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
3976 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
3977 return SI.SegmentStartAddress + OffsetInSeg;
3978}
3979
Nick Kledzik56ebef42014-09-16 01:41:51 +00003980iterator_range<bind_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003981MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003982 ArrayRef<uint8_t> Opcodes, bool is64,
Nick Kledzik56ebef42014-09-16 01:41:51 +00003983 MachOBindEntry::Kind BKind) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003984 if (O->BindRebaseSectionTable == nullptr)
3985 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003986 MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003987 Start.moveToFirst();
3988
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003989 MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003990 Finish.moveToEnd();
3991
Craig Topper15576e12015-12-06 05:08:07 +00003992 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00003993}
3994
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003995iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003996 return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00003997 MachOBindEntry::Kind::Regular);
3998}
3999
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004000iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004001 return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004002 MachOBindEntry::Kind::Lazy);
4003}
4004
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004005iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004006 return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004007 MachOBindEntry::Kind::Weak);
4008}
4009
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00004010MachOObjectFile::load_command_iterator
4011MachOObjectFile::begin_load_commands() const {
4012 return LoadCommands.begin();
4013}
4014
4015MachOObjectFile::load_command_iterator
4016MachOObjectFile::end_load_commands() const {
4017 return LoadCommands.end();
4018}
4019
4020iterator_range<MachOObjectFile::load_command_iterator>
4021MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00004022 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00004023}
4024
Rafael Espindola56f976f2013-04-18 18:08:55 +00004025StringRef
4026MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
4027 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
4028 return parseSegmentOrSectionName(Raw.data());
4029}
4030
4031ArrayRef<char>
4032MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00004033 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00004034 const section_base *Base =
4035 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00004036 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004037}
4038
4039ArrayRef<char>
4040MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00004041 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00004042 const section_base *Base =
4043 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00004044 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004045}
4046
4047bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00004048MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00004049 const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004050 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00004051 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00004052 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004053}
4054
Eric Christopher1d62c252013-07-22 22:25:07 +00004055unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004056 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004057 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00004058 return RE.r_word1 & 0xffffff;
4059 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004060}
4061
Eric Christopher1d62c252013-07-22 22:25:07 +00004062bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004063 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004064 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00004065 return (RE.r_word1 >> 27) & 1;
4066 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004067}
4068
Eric Christopher1d62c252013-07-22 22:25:07 +00004069bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004070 const MachO::any_relocation_info &RE) const {
4071 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004072}
4073
Eric Christopher1d62c252013-07-22 22:25:07 +00004074uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004075 const MachO::any_relocation_info &RE) const {
4076 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004077}
4078
Kevin Enderby9907d0a2014-11-04 00:43:16 +00004079uint32_t MachOObjectFile::getScatteredRelocationType(
4080 const MachO::any_relocation_info &RE) const {
4081 return (RE.r_word0 >> 24) & 0xf;
4082}
4083
Eric Christopher1d62c252013-07-22 22:25:07 +00004084unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004085 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004086 if (isRelocationScattered(RE))
4087 return getScatteredRelocationAddress(RE);
4088 return getPlainRelocationAddress(RE);
4089}
4090
Charles Davis8bdfafd2013-09-01 04:28:48 +00004091unsigned MachOObjectFile::getAnyRelocationPCRel(
4092 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004093 if (isRelocationScattered(RE))
Lang Hames697e7cd2016-12-04 01:56:10 +00004094 return getScatteredRelocationPCRel(RE);
4095 return getPlainRelocationPCRel(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004096}
4097
Eric Christopher1d62c252013-07-22 22:25:07 +00004098unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004099 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004100 if (isRelocationScattered(RE))
4101 return getScatteredRelocationLength(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00004102 return getPlainRelocationLength(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004103}
4104
4105unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00004106MachOObjectFile::getAnyRelocationType(
4107 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004108 if (isRelocationScattered(RE))
4109 return getScatteredRelocationType(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00004110 return getPlainRelocationType(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004111}
4112
Rafael Espindola52501032013-04-30 15:40:54 +00004113SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00004114MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004115 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00004116 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00004117 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00004118 unsigned SecNum = getPlainRelocationSymbolNum(RE);
4119 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
4120 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00004121 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00004122 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00004123 return SectionRef(DRI, this);
4124}
4125
Charles Davis8bdfafd2013-09-01 04:28:48 +00004126MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00004127 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00004128 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004129}
4130
Charles Davis8bdfafd2013-09-01 04:28:48 +00004131MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00004132 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00004133 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004134}
4135
Charles Davis8bdfafd2013-09-01 04:28:48 +00004136MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00004137 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004138 const char *Sec = getSectionPtr(*this, L, Index);
4139 return getStruct<MachO::section>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004140}
4141
Charles Davis8bdfafd2013-09-01 04:28:48 +00004142MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4143 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004144 const char *Sec = getSectionPtr(*this, L, Index);
4145 return getStruct<MachO::section_64>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004146}
4147
Charles Davis8bdfafd2013-09-01 04:28:48 +00004148MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00004149MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00004150 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004151 return getStruct<MachO::nlist>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004152}
4153
Charles Davis8bdfafd2013-09-01 04:28:48 +00004154MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00004155MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00004156 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004157 return getStruct<MachO::nlist_64>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004158}
4159
Charles Davis8bdfafd2013-09-01 04:28:48 +00004160MachO::linkedit_data_command
4161MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004162 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004163}
4164
Charles Davis8bdfafd2013-09-01 04:28:48 +00004165MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00004166MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004167 return getStruct<MachO::segment_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004168}
4169
Charles Davis8bdfafd2013-09-01 04:28:48 +00004170MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00004171MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004172 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004173}
4174
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00004175MachO::linker_option_command
4176MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004177 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004178}
4179
Jim Grosbach448334a2014-03-18 22:09:05 +00004180MachO::version_min_command
4181MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004182 return getStruct<MachO::version_min_command>(*this, L.Ptr);
Jim Grosbach448334a2014-03-18 22:09:05 +00004183}
4184
Kevin Enderbya4579c42017-01-19 17:36:31 +00004185MachO::note_command
4186MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
4187 return getStruct<MachO::note_command>(*this, L.Ptr);
4188}
4189
Steven Wu5b54a422017-01-23 20:07:55 +00004190MachO::build_version_command
4191MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
4192 return getStruct<MachO::build_version_command>(*this, L.Ptr);
4193}
4194
4195MachO::build_tool_version
4196MachOObjectFile::getBuildToolVersion(unsigned index) const {
4197 return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
4198}
4199
Tim Northover8f9590b2014-06-30 14:40:57 +00004200MachO::dylib_command
4201MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004202 return getStruct<MachO::dylib_command>(*this, L.Ptr);
Tim Northover8f9590b2014-06-30 14:40:57 +00004203}
4204
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004205MachO::dyld_info_command
4206MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004207 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004208}
4209
4210MachO::dylinker_command
4211MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004212 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004213}
4214
4215MachO::uuid_command
4216MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004217 return getStruct<MachO::uuid_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004218}
4219
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004220MachO::rpath_command
4221MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004222 return getStruct<MachO::rpath_command>(*this, L.Ptr);
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004223}
4224
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004225MachO::source_version_command
4226MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004227 return getStruct<MachO::source_version_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004228}
4229
4230MachO::entry_point_command
4231MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004232 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004233}
4234
Kevin Enderby0804f4672014-12-16 23:25:52 +00004235MachO::encryption_info_command
4236MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004237 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
Kevin Enderby0804f4672014-12-16 23:25:52 +00004238}
4239
Kevin Enderby57538292014-12-17 01:01:30 +00004240MachO::encryption_info_command_64
4241MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004242 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
Kevin Enderby57538292014-12-17 01:01:30 +00004243}
4244
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004245MachO::sub_framework_command
4246MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004247 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004248}
Tim Northover8f9590b2014-06-30 14:40:57 +00004249
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004250MachO::sub_umbrella_command
4251MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004252 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004253}
4254
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004255MachO::sub_library_command
4256MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004257 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004258}
4259
Kevin Enderby186eac32014-12-19 21:06:24 +00004260MachO::sub_client_command
4261MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004262 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
Kevin Enderby186eac32014-12-19 21:06:24 +00004263}
4264
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004265MachO::routines_command
4266MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004267 return getStruct<MachO::routines_command>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004268}
4269
4270MachO::routines_command_64
4271MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004272 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004273}
4274
Kevin Enderby48ef5342014-12-23 22:56:39 +00004275MachO::thread_command
4276MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004277 return getStruct<MachO::thread_command>(*this, L.Ptr);
Kevin Enderby48ef5342014-12-23 22:56:39 +00004278}
4279
Charles Davis8bdfafd2013-09-01 04:28:48 +00004280MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00004281MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00004282 uint32_t Offset;
Kevin Enderbyabf10f22017-06-22 17:41:22 +00004283 if (getHeader().filetype == MachO::MH_OBJECT) {
4284 DataRefImpl Sec;
4285 Sec.d.a = Rel.d.a;
4286 if (is64Bit()) {
4287 MachO::section_64 Sect = getSection64(Sec);
4288 Offset = Sect.reloff;
4289 } else {
4290 MachO::section Sect = getSection(Sec);
4291 Offset = Sect.reloff;
4292 }
Rafael Espindola128b8112014-04-03 23:51:28 +00004293 } else {
Kevin Enderbyabf10f22017-06-22 17:41:22 +00004294 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
4295 Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
Rafael Espindola128b8112014-04-03 23:51:28 +00004296 }
4297
4298 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004299 getPtr(*this, Offset)) + Rel.d.b;
Rafael Espindola128b8112014-04-03 23:51:28 +00004300 return getStruct<MachO::any_relocation_info>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004301 *this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00004302}
4303
Charles Davis8bdfafd2013-09-01 04:28:48 +00004304MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00004305MachOObjectFile::getDice(DataRefImpl Rel) const {
4306 const char *P = reinterpret_cast<const char *>(Rel.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004307 return getStruct<MachO::data_in_code_entry>(*this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00004308}
4309
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004310const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00004311 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004312}
4313
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004314const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4315 assert(is64Bit());
4316 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004317}
4318
Charles Davis8bdfafd2013-09-01 04:28:48 +00004319uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4320 const MachO::dysymtab_command &DLC,
4321 unsigned Index) const {
4322 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
Lang Hames697e7cd2016-12-04 01:56:10 +00004323 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004324}
4325
Charles Davis8bdfafd2013-09-01 04:28:48 +00004326MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00004327MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4328 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004329 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
Lang Hames697e7cd2016-12-04 01:56:10 +00004330 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004331}
4332
Charles Davis8bdfafd2013-09-01 04:28:48 +00004333MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004334 if (SymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004335 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004336
4337 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4338 MachO::symtab_command Cmd;
4339 Cmd.cmd = MachO::LC_SYMTAB;
4340 Cmd.cmdsize = sizeof(MachO::symtab_command);
4341 Cmd.symoff = 0;
4342 Cmd.nsyms = 0;
4343 Cmd.stroff = 0;
4344 Cmd.strsize = 0;
4345 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004346}
4347
Charles Davis8bdfafd2013-09-01 04:28:48 +00004348MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004349 if (DysymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004350 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004351
4352 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4353 MachO::dysymtab_command Cmd;
4354 Cmd.cmd = MachO::LC_DYSYMTAB;
4355 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4356 Cmd.ilocalsym = 0;
4357 Cmd.nlocalsym = 0;
4358 Cmd.iextdefsym = 0;
4359 Cmd.nextdefsym = 0;
4360 Cmd.iundefsym = 0;
4361 Cmd.nundefsym = 0;
4362 Cmd.tocoff = 0;
4363 Cmd.ntoc = 0;
4364 Cmd.modtaboff = 0;
4365 Cmd.nmodtab = 0;
4366 Cmd.extrefsymoff = 0;
4367 Cmd.nextrefsyms = 0;
4368 Cmd.indirectsymoff = 0;
4369 Cmd.nindirectsyms = 0;
4370 Cmd.extreloff = 0;
4371 Cmd.nextrel = 0;
4372 Cmd.locreloff = 0;
4373 Cmd.nlocrel = 0;
4374 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004375}
4376
Charles Davis8bdfafd2013-09-01 04:28:48 +00004377MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00004378MachOObjectFile::getDataInCodeLoadCommand() const {
4379 if (DataInCodeLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004380 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00004381
4382 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00004383 MachO::linkedit_data_command Cmd;
4384 Cmd.cmd = MachO::LC_DATA_IN_CODE;
4385 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4386 Cmd.dataoff = 0;
4387 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00004388 return Cmd;
4389}
4390
Kevin Enderby9a509442015-01-27 21:28:24 +00004391MachO::linkedit_data_command
4392MachOObjectFile::getLinkOptHintsLoadCommand() const {
4393 if (LinkOptHintsLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004394 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
Kevin Enderby9a509442015-01-27 21:28:24 +00004395
4396 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4397 // fields.
4398 MachO::linkedit_data_command Cmd;
4399 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4400 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4401 Cmd.dataoff = 0;
4402 Cmd.datasize = 0;
4403 return Cmd;
4404}
4405
Nick Kledzikd04bc352014-08-30 00:20:14 +00004406ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004407 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004408 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004409
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004410 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004411 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004412 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004413 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00004414 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004415}
4416
4417ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004418 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004419 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004420
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004421 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004422 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004423 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004424 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004425 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004426}
4427
4428ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004429 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004430 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004431
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004432 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004433 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004434 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004435 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004436 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004437}
4438
4439ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004440 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004441 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004442
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004443 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004444 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004445 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004446 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004447 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004448}
4449
4450ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004451 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004452 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004453
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004454 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004455 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004456 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004457 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00004458 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004459}
4460
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004461ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
4462 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004463 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00004464 // Returning a pointer is fine as uuid doesn't need endian swapping.
4465 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00004466 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004467}
Nick Kledzikd04bc352014-08-30 00:20:14 +00004468
Rafael Espindola6e040c02013-04-26 20:07:33 +00004469StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004470 MachO::symtab_command S = getSymtabLoadCommand();
4471 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004472}
4473
Rafael Espindola56f976f2013-04-18 18:08:55 +00004474bool MachOObjectFile::is64Bit() const {
4475 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00004476 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004477}
4478
4479void MachOObjectFile::ReadULEB128s(uint64_t Index,
4480 SmallVectorImpl<uint64_t> &Out) const {
4481 DataExtractor extractor(ObjectFile::getData(), true, 0);
4482
4483 uint32_t offset = Index;
4484 uint64_t data = 0;
4485 while (uint64_t delta = extractor.getULEB128(&offset)) {
4486 data += delta;
4487 Out.push_back(data);
4488 }
4489}
4490
Rafael Espindolac66d7612014-08-17 19:09:37 +00004491bool MachOObjectFile::isRelocatableObject() const {
4492 return getHeader().filetype == MachO::MH_OBJECT;
4493}
4494
Lang Hamesff044b12016-03-25 23:11:52 +00004495Expected<std::unique_ptr<MachOObjectFile>>
Kevin Enderby79d6c632016-10-24 21:15:11 +00004496ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4497 uint32_t UniversalCputype,
4498 uint32_t UniversalIndex) {
Rafael Espindola48af1c22014-08-19 18:44:46 +00004499 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00004500 if (Magic == "\xFE\xED\xFA\xCE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004501 return MachOObjectFile::create(Buffer, false, false,
4502 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004503 if (Magic == "\xCE\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004504 return MachOObjectFile::create(Buffer, true, false,
4505 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004506 if (Magic == "\xFE\xED\xFA\xCF")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004507 return MachOObjectFile::create(Buffer, false, true,
4508 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004509 if (Magic == "\xCF\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004510 return MachOObjectFile::create(Buffer, true, true,
4511 UniversalCputype, UniversalIndex);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00004512 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00004513 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004514}
Wolfgang Pieb77d3e932017-06-06 01:22:34 +00004515
4516StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
4517 return StringSwitch<StringRef>(Name)
4518 .Case("debug_str_offs", "debug_str_offsets")
4519 .Default(Name);
4520}