blob: 731ff4e01fd541ebdfac8548bf8dc3bdec973241 [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) {
Sam Clegg675a5172018-06-04 17:01:20 +0000110 assert(Offset <= O.getData().size());
Sam Clegga81fb842018-05-30 03:37:26 +0000111 return O.getData().data() + Offset;
Rafael Espindola60689982013-04-07 19:05:30 +0000112}
113
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000114static MachO::nlist_base
Lang Hames697e7cd2016-12-04 01:56:10 +0000115getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +0000116 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000117 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +0000118}
119
Rafael Espindola56f976f2013-04-18 18:08:55 +0000120static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000121 if (P[15] == 0)
122 // Null terminated.
123 return P;
124 // Not null terminated, so this is a 16 char string.
125 return StringRef(P, 16);
126}
127
Lang Hames697e7cd2016-12-04 01:56:10 +0000128static unsigned getCPUType(const MachOObjectFile &O) {
129 return O.getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000130}
131
Charles Davis8bdfafd2013-09-01 04:28:48 +0000132static uint32_t
133getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
134 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000135}
136
137static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000138getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
139 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000140}
141
Lang Hames697e7cd2016-12-04 01:56:10 +0000142static bool getPlainRelocationPCRel(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000143 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000144 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000145 return (RE.r_word1 >> 24) & 1;
146 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000147}
148
149static bool
Lang Hames697e7cd2016-12-04 01:56:10 +0000150getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000151 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152}
153
Lang Hames697e7cd2016-12-04 01:56:10 +0000154static unsigned getPlainRelocationLength(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000155 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000156 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000157 return (RE.r_word1 >> 25) & 3;
158 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000159}
160
161static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000162getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
163 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000164}
165
Lang Hames697e7cd2016-12-04 01:56:10 +0000166static unsigned getPlainRelocationType(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000167 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000168 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000169 return RE.r_word1 >> 28;
170 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000171}
172
Lang Hames697e7cd2016-12-04 01:56:10 +0000173static uint32_t getSectionFlags(const MachOObjectFile &O,
Rafael Espindola56f976f2013-04-18 18:08:55 +0000174 DataRefImpl Sec) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000175 if (O.is64Bit()) {
176 MachO::section_64 Sect = O.getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000177 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000178 }
Lang Hames697e7cd2016-12-04 01:56:10 +0000179 MachO::section Sect = O.getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000180 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000181}
182
Lang Hames9e964f32016-03-25 17:25:34 +0000183static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000184getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000185 uint32_t LoadCommandIndex) {
Lang Hames9e964f32016-03-25 17:25:34 +0000186 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
Jonas Devlieghere81f5abe2017-09-13 13:43:01 +0000187 if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
188 return malformedError("load command " + Twine(LoadCommandIndex) +
189 " extends past end of file");
Lang Hames9e964f32016-03-25 17:25:34 +0000190 if (CmdOrErr->cmdsize < 8)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000191 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000192 " with size less than 8 bytes");
Lang Hames9e964f32016-03-25 17:25:34 +0000193 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
194 } else
195 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000196}
197
Lang Hames9e964f32016-03-25 17:25:34 +0000198static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000199getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
200 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
201 : sizeof(MachO::mach_header);
202 if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000203 return malformedError("load command 0 extends past the end all load "
Kevin Enderby89134962016-05-05 23:41:05 +0000204 "commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000205 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000206}
207
Lang Hames9e964f32016-03-25 17:25:34 +0000208static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000209getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000210 const MachOObjectFile::LoadCommandInfo &L) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000211 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
212 : sizeof(MachO::mach_header);
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000213 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
Lang Hames697e7cd2016-12-04 01:56:10 +0000214 Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000215 return malformedError("load command " + Twine(LoadCommandIndex + 1) +
Kevin Enderby89134962016-05-05 23:41:05 +0000216 " extends past the end all load commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000217 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000218}
219
Alexey Samsonov9f336632015-06-04 19:45:22 +0000220template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +0000221static void parseHeader(const MachOObjectFile &Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000222 Error &Err) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000223 if (sizeof(T) > Obj.getData().size()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000224 Err = malformedError("the mach header extends past the end of the "
Kevin Enderby89134962016-05-05 23:41:05 +0000225 "file");
Kevin Enderby87025742016-04-13 21:17:58 +0000226 return;
227 }
Lang Hames9e964f32016-03-25 17:25:34 +0000228 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
229 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000230 else
Lang Hames9e964f32016-03-25 17:25:34 +0000231 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000232}
233
Kevin Enderbyd5039402016-10-31 20:29:48 +0000234// This is used to check for overlapping of Mach-O elements.
235struct MachOElement {
236 uint64_t Offset;
237 uint64_t Size;
238 const char *Name;
239};
240
241static Error checkOverlappingElement(std::list<MachOElement> &Elements,
242 uint64_t Offset, uint64_t Size,
243 const char *Name) {
244 if (Size == 0)
245 return Error::success();
246
247 for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
248 auto E = *it;
249 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
250 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
251 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
252 return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
253 " with a size of " + Twine(Size) + ", overlaps " +
254 E.Name + " at offset " + Twine(E.Offset) + " with "
255 "a size of " + Twine(E.Size));
256 auto nt = it;
257 nt++;
258 if (nt != Elements.end()) {
259 auto N = *nt;
260 if (Offset + Size <= N.Offset) {
261 Elements.insert(nt, {Offset, Size, Name});
262 return Error::success();
263 }
264 }
265 }
266 Elements.push_back({Offset, Size, Name});
267 return Error::success();
268}
269
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000270// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
271// sections to \param Sections, and optionally sets
272// \param IsPageZeroSegment to true.
Kevin Enderbyc614d282016-08-12 20:10:25 +0000273template <typename Segment, typename Section>
Lang Hames9e964f32016-03-25 17:25:34 +0000274static Error parseSegmentLoadCommand(
Lang Hames697e7cd2016-12-04 01:56:10 +0000275 const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000276 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000277 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
278 std::list<MachOElement> &Elements) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000279 const unsigned SegmentLoadSize = sizeof(Segment);
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000280 if (Load.C.cmdsize < SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000281 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000282 " " + CmdName + " cmdsize too small");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000283 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
284 Segment S = SegOrErr.get();
285 const unsigned SectionSize = sizeof(Section);
Lang Hames697e7cd2016-12-04 01:56:10 +0000286 uint64_t FileSize = Obj.getData().size();
Lang Hames9e964f32016-03-25 17:25:34 +0000287 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
288 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000289 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000290 " inconsistent cmdsize in " + CmdName +
Kevin Enderby89134962016-05-05 23:41:05 +0000291 " for the number of sections");
Lang Hames9e964f32016-03-25 17:25:34 +0000292 for (unsigned J = 0; J < S.nsects; ++J) {
293 const char *Sec = getSectionPtr(Obj, Load, J);
294 Sections.push_back(Sec);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000295 Section s = getStruct<Section>(Obj, Sec);
Lang Hames697e7cd2016-12-04 01:56:10 +0000296 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
297 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000298 s.flags != MachO::S_ZEROFILL &&
299 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
300 s.offset > FileSize)
301 return malformedError("offset field of section " + Twine(J) + " in " +
302 CmdName + " command " + Twine(LoadCommandIndex) +
303 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000304 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
305 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000306 s.flags != MachO::S_ZEROFILL &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000307 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
308 s.offset < SizeOfHeaders && s.size != 0)
Kevin Enderbyc614d282016-08-12 20:10:25 +0000309 return malformedError("offset field of section " + Twine(J) + " in " +
310 CmdName + " command " + Twine(LoadCommandIndex) +
311 " not past the headers of the file");
312 uint64_t BigSize = s.offset;
313 BigSize += s.size;
Lang Hames697e7cd2016-12-04 01:56:10 +0000314 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
315 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000316 s.flags != MachO::S_ZEROFILL &&
317 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
318 BigSize > FileSize)
319 return malformedError("offset field plus size field of section " +
320 Twine(J) + " in " + CmdName + " command " +
321 Twine(LoadCommandIndex) +
322 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000323 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
324 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000325 s.flags != MachO::S_ZEROFILL &&
326 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
327 s.size > S.filesize)
328 return malformedError("size field of section " +
329 Twine(J) + " in " + CmdName + " command " +
330 Twine(LoadCommandIndex) +
331 " greater than the segment");
Lang Hames697e7cd2016-12-04 01:56:10 +0000332 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
333 Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000334 s.addr < S.vmaddr)
335 return malformedError("addr field of section " + Twine(J) + " in " +
336 CmdName + " command " + Twine(LoadCommandIndex) +
337 " less than the segment's vmaddr");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000338 BigSize = s.addr;
339 BigSize += s.size;
340 uint64_t BigEnd = S.vmaddr;
341 BigEnd += S.vmsize;
342 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000343 return malformedError("addr field plus size of section " + Twine(J) +
344 " in " + CmdName + " command " +
345 Twine(LoadCommandIndex) +
346 " greater than than "
Kevin Enderbyc614d282016-08-12 20:10:25 +0000347 "the segment's vmaddr plus vmsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000348 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
349 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000350 s.flags != MachO::S_ZEROFILL &&
351 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
352 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
353 "section contents"))
354 return Err;
Kevin Enderbyc614d282016-08-12 20:10:25 +0000355 if (s.reloff > FileSize)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000356 return malformedError("reloff field of section " + Twine(J) + " in " +
357 CmdName + " command " + Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000358 " extends past the end of the file");
359 BigSize = s.nreloc;
360 BigSize *= sizeof(struct MachO::relocation_info);
361 BigSize += s.reloff;
362 if (BigSize > FileSize)
363 return malformedError("reloff field plus nreloc field times sizeof("
364 "struct relocation_info) of section " +
365 Twine(J) + " in " + CmdName + " command " +
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000366 Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000367 " extends past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000368 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
369 sizeof(struct
370 MachO::relocation_info),
371 "section relocation entries"))
372 return Err;
Lang Hames9e964f32016-03-25 17:25:34 +0000373 }
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000374 if (S.fileoff > FileSize)
375 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000376 " fileoff field in " + CmdName +
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000377 " extends past the end of the file");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000378 uint64_t BigSize = S.fileoff;
379 BigSize += S.filesize;
380 if (BigSize > FileSize)
381 return malformedError("load command " + Twine(LoadCommandIndex) +
382 " fileoff field plus filesize field in " +
383 CmdName + " extends past the end of the file");
384 if (S.vmsize != 0 && S.filesize > S.vmsize)
385 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby86d8bd12017-02-07 21:20:44 +0000386 " filesize field in " + CmdName +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000387 " greater than vmsize field");
Lang Hames9e964f32016-03-25 17:25:34 +0000388 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
389 } else
390 return SegOrErr.takeError();
391
392 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000393}
394
Lang Hames697e7cd2016-12-04 01:56:10 +0000395static Error checkSymtabCommand(const MachOObjectFile &Obj,
Kevin Enderby0e52c922016-08-26 19:34:07 +0000396 const MachOObjectFile::LoadCommandInfo &Load,
397 uint32_t LoadCommandIndex,
Kevin Enderbyd5039402016-10-31 20:29:48 +0000398 const char **SymtabLoadCmd,
399 std::list<MachOElement> &Elements) {
Kevin Enderby0e52c922016-08-26 19:34:07 +0000400 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
401 return malformedError("load command " + Twine(LoadCommandIndex) +
402 " LC_SYMTAB cmdsize too small");
403 if (*SymtabLoadCmd != nullptr)
404 return malformedError("more than one LC_SYMTAB command");
405 MachO::symtab_command Symtab =
406 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
407 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
408 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
409 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000410 uint64_t FileSize = Obj.getData().size();
Kevin Enderby0e52c922016-08-26 19:34:07 +0000411 if (Symtab.symoff > FileSize)
412 return malformedError("symoff field of LC_SYMTAB command " +
413 Twine(LoadCommandIndex) + " extends past the end "
414 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000415 uint64_t SymtabSize = Symtab.nsyms;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000416 const char *struct_nlist_name;
Lang Hames697e7cd2016-12-04 01:56:10 +0000417 if (Obj.is64Bit()) {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000418 SymtabSize *= sizeof(MachO::nlist_64);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000419 struct_nlist_name = "struct nlist_64";
420 } else {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000421 SymtabSize *= sizeof(MachO::nlist);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000422 struct_nlist_name = "struct nlist";
423 }
Kevin Enderbyd5039402016-10-31 20:29:48 +0000424 uint64_t BigSize = SymtabSize;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000425 BigSize += Symtab.symoff;
426 if (BigSize > FileSize)
427 return malformedError("symoff field plus nsyms field times sizeof(" +
428 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
429 Twine(LoadCommandIndex) + " extends past the end "
430 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000431 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
432 "symbol table"))
433 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000434 if (Symtab.stroff > FileSize)
435 return malformedError("stroff field of LC_SYMTAB command " +
436 Twine(LoadCommandIndex) + " extends past the end "
437 "of the file");
438 BigSize = Symtab.stroff;
439 BigSize += Symtab.strsize;
440 if (BigSize > FileSize)
441 return malformedError("stroff field plus strsize field of LC_SYMTAB "
442 "command " + Twine(LoadCommandIndex) + " extends "
443 "past the end of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000444 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
445 Symtab.strsize, "string table"))
446 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000447 *SymtabLoadCmd = Load.Ptr;
448 return Error::success();
449}
450
Lang Hames697e7cd2016-12-04 01:56:10 +0000451static Error checkDysymtabCommand(const MachOObjectFile &Obj,
452 const MachOObjectFile::LoadCommandInfo &Load,
453 uint32_t LoadCommandIndex,
454 const char **DysymtabLoadCmd,
455 std::list<MachOElement> &Elements) {
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000456 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
457 return malformedError("load command " + Twine(LoadCommandIndex) +
458 " LC_DYSYMTAB cmdsize too small");
459 if (*DysymtabLoadCmd != nullptr)
460 return malformedError("more than one LC_DYSYMTAB command");
461 MachO::dysymtab_command Dysymtab =
462 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
463 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
464 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
465 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000466 uint64_t FileSize = Obj.getData().size();
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000467 if (Dysymtab.tocoff > FileSize)
468 return malformedError("tocoff field of LC_DYSYMTAB command " +
469 Twine(LoadCommandIndex) + " extends past the end of "
470 "the file");
471 uint64_t BigSize = Dysymtab.ntoc;
472 BigSize *= sizeof(MachO::dylib_table_of_contents);
473 BigSize += Dysymtab.tocoff;
474 if (BigSize > FileSize)
475 return malformedError("tocoff field plus ntoc field times sizeof(struct "
476 "dylib_table_of_contents) of LC_DYSYMTAB command " +
477 Twine(LoadCommandIndex) + " extends past the end of "
478 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000479 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
480 Dysymtab.ntoc * sizeof(struct
NAKAMURA Takumi6f43bd42017-10-18 13:31:28 +0000481 MachO::dylib_table_of_contents),
482 "table of contents"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000483 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000484 if (Dysymtab.modtaboff > FileSize)
485 return malformedError("modtaboff field of LC_DYSYMTAB command " +
486 Twine(LoadCommandIndex) + " extends past the end of "
487 "the file");
488 BigSize = Dysymtab.nmodtab;
489 const char *struct_dylib_module_name;
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000490 uint64_t sizeof_modtab;
Lang Hames697e7cd2016-12-04 01:56:10 +0000491 if (Obj.is64Bit()) {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000492 sizeof_modtab = sizeof(MachO::dylib_module_64);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000493 struct_dylib_module_name = "struct dylib_module_64";
494 } else {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000495 sizeof_modtab = sizeof(MachO::dylib_module);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000496 struct_dylib_module_name = "struct dylib_module";
497 }
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000498 BigSize *= sizeof_modtab;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000499 BigSize += Dysymtab.modtaboff;
500 if (BigSize > FileSize)
501 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
502 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
503 "command " + Twine(LoadCommandIndex) + " extends "
504 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000505 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
506 Dysymtab.nmodtab * sizeof_modtab,
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000507 "module table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000508 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000509 if (Dysymtab.extrefsymoff > FileSize)
510 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
511 Twine(LoadCommandIndex) + " extends past the end of "
512 "the file");
513 BigSize = Dysymtab.nextrefsyms;
514 BigSize *= sizeof(MachO::dylib_reference);
515 BigSize += Dysymtab.extrefsymoff;
516 if (BigSize > FileSize)
517 return malformedError("extrefsymoff field plus nextrefsyms field times "
518 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
519 "command " + Twine(LoadCommandIndex) + " extends "
520 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000521 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
522 Dysymtab.nextrefsyms *
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000523 sizeof(MachO::dylib_reference),
524 "reference table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000525 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000526 if (Dysymtab.indirectsymoff > FileSize)
527 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
528 Twine(LoadCommandIndex) + " extends past the end of "
529 "the file");
530 BigSize = Dysymtab.nindirectsyms;
531 BigSize *= sizeof(uint32_t);
532 BigSize += Dysymtab.indirectsymoff;
533 if (BigSize > FileSize)
534 return malformedError("indirectsymoff field plus nindirectsyms field times "
535 "sizeof(uint32_t) of LC_DYSYMTAB command " +
536 Twine(LoadCommandIndex) + " extends past the end of "
537 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000538 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
539 Dysymtab.nindirectsyms *
540 sizeof(uint32_t),
NAKAMURA Takumi6f43bd42017-10-18 13:31:28 +0000541 "indirect table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000542 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000543 if (Dysymtab.extreloff > FileSize)
544 return malformedError("extreloff field of LC_DYSYMTAB command " +
545 Twine(LoadCommandIndex) + " extends past the end of "
546 "the file");
547 BigSize = Dysymtab.nextrel;
548 BigSize *= sizeof(MachO::relocation_info);
549 BigSize += Dysymtab.extreloff;
550 if (BigSize > FileSize)
551 return malformedError("extreloff field plus nextrel field times sizeof"
552 "(struct relocation_info) of LC_DYSYMTAB command " +
553 Twine(LoadCommandIndex) + " extends past the end of "
554 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000555 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
556 Dysymtab.nextrel *
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000557 sizeof(MachO::relocation_info),
558 "external relocation table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000559 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000560 if (Dysymtab.locreloff > FileSize)
561 return malformedError("locreloff field of LC_DYSYMTAB command " +
562 Twine(LoadCommandIndex) + " extends past the end of "
563 "the file");
564 BigSize = Dysymtab.nlocrel;
565 BigSize *= sizeof(MachO::relocation_info);
566 BigSize += Dysymtab.locreloff;
567 if (BigSize > FileSize)
568 return malformedError("locreloff field plus nlocrel field times sizeof"
569 "(struct relocation_info) of LC_DYSYMTAB command " +
570 Twine(LoadCommandIndex) + " extends past the end of "
571 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000572 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
573 Dysymtab.nlocrel *
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000574 sizeof(MachO::relocation_info),
575 "local relocation table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000576 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000577 *DysymtabLoadCmd = Load.Ptr;
578 return Error::success();
579}
580
Lang Hames697e7cd2016-12-04 01:56:10 +0000581static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000582 const MachOObjectFile::LoadCommandInfo &Load,
583 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000584 const char **LoadCmd, const char *CmdName,
585 std::list<MachOElement> &Elements,
586 const char *ElementName) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000587 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
588 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
589 CmdName + " cmdsize too small");
590 if (*LoadCmd != nullptr)
591 return malformedError("more than one " + Twine(CmdName) + " command");
592 MachO::linkedit_data_command LinkData =
593 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
594 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
595 return malformedError(Twine(CmdName) + " command " +
596 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000597 uint64_t FileSize = Obj.getData().size();
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000598 if (LinkData.dataoff > FileSize)
599 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
600 Twine(LoadCommandIndex) + " extends past the end of "
601 "the file");
602 uint64_t BigSize = LinkData.dataoff;
603 BigSize += LinkData.datasize;
604 if (BigSize > FileSize)
605 return malformedError("dataoff field plus datasize field of " +
606 Twine(CmdName) + " command " +
607 Twine(LoadCommandIndex) + " extends past the end of "
608 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000609 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
610 LinkData.datasize, ElementName))
611 return Err;
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000612 *LoadCmd = Load.Ptr;
613 return Error::success();
614}
615
Lang Hames697e7cd2016-12-04 01:56:10 +0000616static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000617 const MachOObjectFile::LoadCommandInfo &Load,
618 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000619 const char **LoadCmd, const char *CmdName,
620 std::list<MachOElement> &Elements) {
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000621 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
622 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
623 CmdName + " cmdsize too small");
624 if (*LoadCmd != nullptr)
625 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
626 "command");
627 MachO::dyld_info_command DyldInfo =
628 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
629 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
630 return malformedError(Twine(CmdName) + " command " +
631 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000632 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000633 if (DyldInfo.rebase_off > FileSize)
634 return malformedError("rebase_off field of " + Twine(CmdName) +
635 " command " + Twine(LoadCommandIndex) + " extends "
636 "past the end of the file");
637 uint64_t BigSize = DyldInfo.rebase_off;
638 BigSize += DyldInfo.rebase_size;
639 if (BigSize > FileSize)
640 return malformedError("rebase_off field plus rebase_size field of " +
641 Twine(CmdName) + " command " +
642 Twine(LoadCommandIndex) + " extends past the end of "
643 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000644 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
645 DyldInfo.rebase_size,
646 "dyld rebase info"))
647 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000648 if (DyldInfo.bind_off > FileSize)
649 return malformedError("bind_off field of " + Twine(CmdName) +
650 " command " + Twine(LoadCommandIndex) + " extends "
651 "past the end of the file");
652 BigSize = DyldInfo.bind_off;
653 BigSize += DyldInfo.bind_size;
654 if (BigSize > FileSize)
655 return malformedError("bind_off field plus bind_size field of " +
656 Twine(CmdName) + " command " +
657 Twine(LoadCommandIndex) + " extends past the end of "
658 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000659 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
660 DyldInfo.bind_size,
661 "dyld bind info"))
662 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000663 if (DyldInfo.weak_bind_off > FileSize)
664 return malformedError("weak_bind_off field of " + Twine(CmdName) +
665 " command " + Twine(LoadCommandIndex) + " extends "
666 "past the end of the file");
667 BigSize = DyldInfo.weak_bind_off;
668 BigSize += DyldInfo.weak_bind_size;
669 if (BigSize > FileSize)
670 return malformedError("weak_bind_off field plus weak_bind_size field of " +
671 Twine(CmdName) + " command " +
672 Twine(LoadCommandIndex) + " extends past the end of "
673 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000674 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
675 DyldInfo.weak_bind_size,
676 "dyld weak bind info"))
677 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000678 if (DyldInfo.lazy_bind_off > FileSize)
679 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
680 " command " + Twine(LoadCommandIndex) + " extends "
681 "past the end of the file");
682 BigSize = DyldInfo.lazy_bind_off;
683 BigSize += DyldInfo.lazy_bind_size;
684 if (BigSize > FileSize)
685 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
686 Twine(CmdName) + " command " +
687 Twine(LoadCommandIndex) + " extends past the end of "
688 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000689 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
690 DyldInfo.lazy_bind_size,
691 "dyld lazy bind info"))
692 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000693 if (DyldInfo.export_off > FileSize)
694 return malformedError("export_off field of " + Twine(CmdName) +
695 " command " + Twine(LoadCommandIndex) + " extends "
696 "past the end of the file");
697 BigSize = DyldInfo.export_off;
698 BigSize += DyldInfo.export_size;
699 if (BigSize > FileSize)
700 return malformedError("export_off field plus export_size field of " +
701 Twine(CmdName) + " command " +
702 Twine(LoadCommandIndex) + " extends past the end of "
703 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000704 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
705 DyldInfo.export_size,
706 "dyld export info"))
707 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000708 *LoadCmd = Load.Ptr;
709 return Error::success();
710}
711
Lang Hames697e7cd2016-12-04 01:56:10 +0000712static Error checkDylibCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000713 const MachOObjectFile::LoadCommandInfo &Load,
714 uint32_t LoadCommandIndex, const char *CmdName) {
715 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
716 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
717 CmdName + " cmdsize too small");
718 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
719 if (D.dylib.name < sizeof(MachO::dylib_command))
720 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
721 CmdName + " name.offset field too small, not past "
722 "the end of the dylib_command struct");
723 if (D.dylib.name >= D.cmdsize)
724 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
725 CmdName + " name.offset field extends past the end "
726 "of the load command");
727 // Make sure there is a null between the starting offset of the name and
728 // the end of the load command.
729 uint32_t i;
730 const char *P = (const char *)Load.Ptr;
731 for (i = D.dylib.name; i < D.cmdsize; i++)
732 if (P[i] == '\0')
733 break;
734 if (i >= D.cmdsize)
735 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
736 CmdName + " library name extends past the end of the "
737 "load command");
738 return Error::success();
739}
740
Lang Hames697e7cd2016-12-04 01:56:10 +0000741static Error checkDylibIdCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000742 const MachOObjectFile::LoadCommandInfo &Load,
743 uint32_t LoadCommandIndex,
744 const char **LoadCmd) {
745 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
746 "LC_ID_DYLIB"))
747 return Err;
748 if (*LoadCmd != nullptr)
749 return malformedError("more than one LC_ID_DYLIB command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000750 if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
751 Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000752 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
753 "file type");
754 *LoadCmd = Load.Ptr;
755 return Error::success();
756}
757
Lang Hames697e7cd2016-12-04 01:56:10 +0000758static Error checkDyldCommand(const MachOObjectFile &Obj,
Kevin Enderby3e490ef2016-09-27 23:24:13 +0000759 const MachOObjectFile::LoadCommandInfo &Load,
760 uint32_t LoadCommandIndex, const char *CmdName) {
761 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
762 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
763 CmdName + " cmdsize too small");
764 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
765 if (D.name < sizeof(MachO::dylinker_command))
766 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
767 CmdName + " name.offset field too small, not past "
768 "the end of the dylinker_command struct");
769 if (D.name >= D.cmdsize)
770 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
771 CmdName + " name.offset field extends past the end "
772 "of the load command");
773 // Make sure there is a null between the starting offset of the name and
774 // the end of the load command.
775 uint32_t i;
776 const char *P = (const char *)Load.Ptr;
777 for (i = D.name; i < D.cmdsize; i++)
778 if (P[i] == '\0')
779 break;
780 if (i >= D.cmdsize)
781 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
782 CmdName + " dyld name extends past the end of the "
783 "load command");
784 return Error::success();
785}
786
Lang Hames697e7cd2016-12-04 01:56:10 +0000787static Error checkVersCommand(const MachOObjectFile &Obj,
Kevin Enderby32359db2016-09-28 21:20:45 +0000788 const MachOObjectFile::LoadCommandInfo &Load,
789 uint32_t LoadCommandIndex,
790 const char **LoadCmd, const char *CmdName) {
791 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
792 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
793 CmdName + " has incorrect cmdsize");
794 if (*LoadCmd != nullptr)
795 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
796 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
797 "LC_VERSION_MIN_WATCHOS command");
798 *LoadCmd = Load.Ptr;
799 return Error::success();
800}
801
Kevin Enderbya4579c42017-01-19 17:36:31 +0000802static Error checkNoteCommand(const MachOObjectFile &Obj,
803 const MachOObjectFile::LoadCommandInfo &Load,
804 uint32_t LoadCommandIndex,
805 std::list<MachOElement> &Elements) {
806 if (Load.C.cmdsize != sizeof(MachO::note_command))
Jonas Devlieghere81f5abe2017-09-13 13:43:01 +0000807 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderbya4579c42017-01-19 17:36:31 +0000808 " LC_NOTE has incorrect cmdsize");
809 MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
810 uint64_t FileSize = Obj.getData().size();
811 if (Nt.offset > FileSize)
812 return malformedError("offset field of LC_NOTE command " +
813 Twine(LoadCommandIndex) + " extends "
814 "past the end of the file");
815 uint64_t BigSize = Nt.offset;
816 BigSize += Nt.size;
817 if (BigSize > FileSize)
818 return malformedError("size field plus offset field of LC_NOTE command " +
819 Twine(LoadCommandIndex) + " extends past the end of "
820 "the file");
821 if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
822 "LC_NOTE data"))
823 return Err;
824 return Error::success();
825}
826
Steven Wu5b54a422017-01-23 20:07:55 +0000827static Error
828parseBuildVersionCommand(const MachOObjectFile &Obj,
829 const MachOObjectFile::LoadCommandInfo &Load,
830 SmallVectorImpl<const char*> &BuildTools,
831 uint32_t LoadCommandIndex) {
832 MachO::build_version_command BVC =
833 getStruct<MachO::build_version_command>(Obj, Load.Ptr);
834 if (Load.C.cmdsize !=
835 sizeof(MachO::build_version_command) +
836 BVC.ntools * sizeof(MachO::build_tool_version))
837 return malformedError("load command " + Twine(LoadCommandIndex) +
838 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
839
840 auto Start = Load.Ptr + sizeof(MachO::build_version_command);
841 BuildTools.resize(BVC.ntools);
842 for (unsigned i = 0; i < BVC.ntools; ++i)
843 BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
844
845 return Error::success();
846}
847
Lang Hames697e7cd2016-12-04 01:56:10 +0000848static Error checkRpathCommand(const MachOObjectFile &Obj,
Kevin Enderby76966bf2016-09-28 23:16:01 +0000849 const MachOObjectFile::LoadCommandInfo &Load,
850 uint32_t LoadCommandIndex) {
851 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
852 return malformedError("load command " + Twine(LoadCommandIndex) +
853 " LC_RPATH cmdsize too small");
854 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
855 if (R.path < sizeof(MachO::rpath_command))
856 return malformedError("load command " + Twine(LoadCommandIndex) +
857 " LC_RPATH path.offset field too small, not past "
858 "the end of the rpath_command struct");
859 if (R.path >= R.cmdsize)
860 return malformedError("load command " + Twine(LoadCommandIndex) +
861 " LC_RPATH path.offset field extends past the end "
862 "of the load command");
863 // Make sure there is a null between the starting offset of the path and
864 // the end of the load command.
865 uint32_t i;
866 const char *P = (const char *)Load.Ptr;
867 for (i = R.path; i < R.cmdsize; i++)
868 if (P[i] == '\0')
869 break;
870 if (i >= R.cmdsize)
871 return malformedError("load command " + Twine(LoadCommandIndex) +
872 " LC_RPATH library name extends past the end of the "
873 "load command");
874 return Error::success();
875}
876
Lang Hames697e7cd2016-12-04 01:56:10 +0000877static Error checkEncryptCommand(const MachOObjectFile &Obj,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000878 const MachOObjectFile::LoadCommandInfo &Load,
879 uint32_t LoadCommandIndex,
880 uint64_t cryptoff, uint64_t cryptsize,
881 const char **LoadCmd, const char *CmdName) {
882 if (*LoadCmd != nullptr)
883 return malformedError("more than one LC_ENCRYPTION_INFO and or "
884 "LC_ENCRYPTION_INFO_64 command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000885 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000886 if (cryptoff > FileSize)
887 return malformedError("cryptoff field of " + Twine(CmdName) +
888 " command " + Twine(LoadCommandIndex) + " extends "
889 "past the end of the file");
890 uint64_t BigSize = cryptoff;
891 BigSize += cryptsize;
892 if (BigSize > FileSize)
893 return malformedError("cryptoff field plus cryptsize field of " +
894 Twine(CmdName) + " command " +
895 Twine(LoadCommandIndex) + " extends past the end of "
896 "the file");
897 *LoadCmd = Load.Ptr;
898 return Error::success();
899}
900
Lang Hames697e7cd2016-12-04 01:56:10 +0000901static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
Kevin Enderby68fffa82016-10-11 21:04:39 +0000902 const MachOObjectFile::LoadCommandInfo &Load,
903 uint32_t LoadCommandIndex) {
904 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
905 return malformedError("load command " + Twine(LoadCommandIndex) +
906 " LC_LINKER_OPTION cmdsize too small");
907 MachO::linker_option_command L =
908 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
909 // Make sure the count of strings is correct.
910 const char *string = (const char *)Load.Ptr +
911 sizeof(struct MachO::linker_option_command);
912 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
913 uint32_t i = 0;
914 while (left > 0) {
915 while (*string == '\0' && left > 0) {
916 string++;
917 left--;
918 }
919 if (left > 0) {
920 i++;
921 uint32_t NullPos = StringRef(string, left).find('\0');
922 uint32_t len = std::min(NullPos, left) + 1;
923 string += len;
924 left -= len;
925 }
926 }
927 if (L.count != i)
928 return malformedError("load command " + Twine(LoadCommandIndex) +
929 " LC_LINKER_OPTION string count " + Twine(L.count) +
930 " does not match number of strings");
931 return Error::success();
932}
933
Lang Hames697e7cd2016-12-04 01:56:10 +0000934static Error checkSubCommand(const MachOObjectFile &Obj,
Kevin Enderby2490de02016-10-17 22:09:25 +0000935 const MachOObjectFile::LoadCommandInfo &Load,
936 uint32_t LoadCommandIndex, const char *CmdName,
937 size_t SizeOfCmd, const char *CmdStructName,
938 uint32_t PathOffset, const char *PathFieldName) {
939 if (PathOffset < SizeOfCmd)
940 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
941 CmdName + " " + PathFieldName + ".offset field too "
942 "small, not past the end of the " + CmdStructName);
943 if (PathOffset >= Load.C.cmdsize)
944 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
945 CmdName + " " + PathFieldName + ".offset field "
946 "extends past the end of the load command");
947 // Make sure there is a null between the starting offset of the path and
948 // the end of the load command.
949 uint32_t i;
950 const char *P = (const char *)Load.Ptr;
951 for (i = PathOffset; i < Load.C.cmdsize; i++)
952 if (P[i] == '\0')
953 break;
954 if (i >= Load.C.cmdsize)
955 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
956 CmdName + " " + PathFieldName + " name extends past "
957 "the end of the load command");
958 return Error::success();
959}
960
Lang Hames697e7cd2016-12-04 01:56:10 +0000961static Error checkThreadCommand(const MachOObjectFile &Obj,
Kevin Enderby210030b2016-10-19 23:44:34 +0000962 const MachOObjectFile::LoadCommandInfo &Load,
963 uint32_t LoadCommandIndex,
964 const char *CmdName) {
965 if (Load.C.cmdsize < sizeof(MachO::thread_command))
966 return malformedError("load command " + Twine(LoadCommandIndex) +
967 CmdName + " cmdsize too small");
968 MachO::thread_command T =
969 getStruct<MachO::thread_command>(Obj, Load.Ptr);
970 const char *state = Load.Ptr + sizeof(MachO::thread_command);
971 const char *end = Load.Ptr + T.cmdsize;
972 uint32_t nflavor = 0;
973 uint32_t cputype = getCPUType(Obj);
974 while (state < end) {
975 if(state + sizeof(uint32_t) > end)
976 return malformedError("load command " + Twine(LoadCommandIndex) +
977 "flavor in " + CmdName + " extends past end of "
978 "command");
979 uint32_t flavor;
980 memcpy(&flavor, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000981 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000982 sys::swapByteOrder(flavor);
983 state += sizeof(uint32_t);
984
985 if(state + sizeof(uint32_t) > end)
986 return malformedError("load command " + Twine(LoadCommandIndex) +
987 " count in " + CmdName + " extends past end of "
988 "command");
989 uint32_t count;
990 memcpy(&count, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000991 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000992 sys::swapByteOrder(count);
993 state += sizeof(uint32_t);
994
Kevin Enderbyc3a035d2017-01-23 21:13:29 +0000995 if (cputype == MachO::CPU_TYPE_I386) {
996 if (flavor == MachO::x86_THREAD_STATE32) {
997 if (count != MachO::x86_THREAD_STATE32_COUNT)
998 return malformedError("load command " + Twine(LoadCommandIndex) +
999 " count not x86_THREAD_STATE32_COUNT for "
1000 "flavor number " + Twine(nflavor) + " which is "
1001 "a x86_THREAD_STATE32 flavor in " + CmdName +
1002 " command");
1003 if (state + sizeof(MachO::x86_thread_state32_t) > end)
1004 return malformedError("load command " + Twine(LoadCommandIndex) +
1005 " x86_THREAD_STATE32 extends past end of "
1006 "command in " + CmdName + " command");
1007 state += sizeof(MachO::x86_thread_state32_t);
1008 } else {
1009 return malformedError("load command " + Twine(LoadCommandIndex) +
1010 " unknown flavor (" + Twine(flavor) + ") for "
1011 "flavor number " + Twine(nflavor) + " in " +
1012 CmdName + " command");
1013 }
1014 } else if (cputype == MachO::CPU_TYPE_X86_64) {
Kevin Enderby299cd892018-03-08 23:10:38 +00001015 if (flavor == MachO::x86_THREAD_STATE) {
1016 if (count != MachO::x86_THREAD_STATE_COUNT)
1017 return malformedError("load command " + Twine(LoadCommandIndex) +
1018 " count not x86_THREAD_STATE_COUNT for "
1019 "flavor number " + Twine(nflavor) + " which is "
1020 "a x86_THREAD_STATE flavor in " + CmdName +
1021 " command");
1022 if (state + sizeof(MachO::x86_thread_state_t) > end)
1023 return malformedError("load command " + Twine(LoadCommandIndex) +
1024 " x86_THREAD_STATE extends past end of "
1025 "command in " + CmdName + " command");
1026 state += sizeof(MachO::x86_thread_state_t);
1027 } else if (flavor == MachO::x86_FLOAT_STATE) {
1028 if (count != MachO::x86_FLOAT_STATE_COUNT)
1029 return malformedError("load command " + Twine(LoadCommandIndex) +
1030 " count not x86_FLOAT_STATE_COUNT for "
1031 "flavor number " + Twine(nflavor) + " which is "
1032 "a x86_FLOAT_STATE flavor in " + CmdName +
1033 " command");
1034 if (state + sizeof(MachO::x86_float_state_t) > end)
1035 return malformedError("load command " + Twine(LoadCommandIndex) +
1036 " x86_FLOAT_STATE extends past end of "
1037 "command in " + CmdName + " command");
1038 state += sizeof(MachO::x86_float_state_t);
1039 } else if (flavor == MachO::x86_EXCEPTION_STATE) {
1040 if (count != MachO::x86_EXCEPTION_STATE_COUNT)
1041 return malformedError("load command " + Twine(LoadCommandIndex) +
1042 " count not x86_EXCEPTION_STATE_COUNT for "
1043 "flavor number " + Twine(nflavor) + " which is "
1044 "a x86_EXCEPTION_STATE flavor in " + CmdName +
1045 " command");
1046 if (state + sizeof(MachO::x86_exception_state_t) > end)
1047 return malformedError("load command " + Twine(LoadCommandIndex) +
1048 " x86_EXCEPTION_STATE extends past end of "
1049 "command in " + CmdName + " command");
1050 state += sizeof(MachO::x86_exception_state_t);
1051 } else if (flavor == MachO::x86_THREAD_STATE64) {
Kevin Enderby210030b2016-10-19 23:44:34 +00001052 if (count != MachO::x86_THREAD_STATE64_COUNT)
1053 return malformedError("load command " + Twine(LoadCommandIndex) +
1054 " count not x86_THREAD_STATE64_COUNT for "
1055 "flavor number " + Twine(nflavor) + " which is "
1056 "a x86_THREAD_STATE64 flavor in " + CmdName +
1057 " command");
1058 if (state + sizeof(MachO::x86_thread_state64_t) > end)
1059 return malformedError("load command " + Twine(LoadCommandIndex) +
1060 " x86_THREAD_STATE64 extends past end of "
1061 "command in " + CmdName + " command");
1062 state += sizeof(MachO::x86_thread_state64_t);
Kevin Enderby299cd892018-03-08 23:10:38 +00001063 } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
1064 if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
1065 return malformedError("load command " + Twine(LoadCommandIndex) +
1066 " count not x86_EXCEPTION_STATE64_COUNT for "
1067 "flavor number " + Twine(nflavor) + " which is "
1068 "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
1069 " command");
1070 if (state + sizeof(MachO::x86_exception_state64_t) > end)
1071 return malformedError("load command " + Twine(LoadCommandIndex) +
1072 " x86_EXCEPTION_STATE64 extends past end of "
1073 "command in " + CmdName + " command");
1074 state += sizeof(MachO::x86_exception_state64_t);
Kevin Enderby210030b2016-10-19 23:44:34 +00001075 } else {
1076 return malformedError("load command " + Twine(LoadCommandIndex) +
1077 " unknown flavor (" + Twine(flavor) + ") for "
1078 "flavor number " + Twine(nflavor) + " in " +
1079 CmdName + " command");
1080 }
1081 } else if (cputype == MachO::CPU_TYPE_ARM) {
1082 if (flavor == MachO::ARM_THREAD_STATE) {
1083 if (count != MachO::ARM_THREAD_STATE_COUNT)
1084 return malformedError("load command " + Twine(LoadCommandIndex) +
1085 " count not ARM_THREAD_STATE_COUNT for "
1086 "flavor number " + Twine(nflavor) + " which is "
1087 "a ARM_THREAD_STATE flavor in " + CmdName +
1088 " command");
1089 if (state + sizeof(MachO::arm_thread_state32_t) > end)
1090 return malformedError("load command " + Twine(LoadCommandIndex) +
1091 " ARM_THREAD_STATE extends past end of "
1092 "command in " + CmdName + " command");
1093 state += sizeof(MachO::arm_thread_state32_t);
1094 } else {
1095 return malformedError("load command " + Twine(LoadCommandIndex) +
1096 " unknown flavor (" + Twine(flavor) + ") for "
1097 "flavor number " + Twine(nflavor) + " in " +
1098 CmdName + " command");
1099 }
Kevin Enderby7747cb52016-11-03 20:51:28 +00001100 } else if (cputype == MachO::CPU_TYPE_ARM64) {
1101 if (flavor == MachO::ARM_THREAD_STATE64) {
1102 if (count != MachO::ARM_THREAD_STATE64_COUNT)
1103 return malformedError("load command " + Twine(LoadCommandIndex) +
1104 " count not ARM_THREAD_STATE64_COUNT for "
1105 "flavor number " + Twine(nflavor) + " which is "
1106 "a ARM_THREAD_STATE64 flavor in " + CmdName +
1107 " command");
1108 if (state + sizeof(MachO::arm_thread_state64_t) > end)
1109 return malformedError("load command " + Twine(LoadCommandIndex) +
1110 " ARM_THREAD_STATE64 extends past end of "
1111 "command in " + CmdName + " command");
1112 state += sizeof(MachO::arm_thread_state64_t);
1113 } else {
1114 return malformedError("load command " + Twine(LoadCommandIndex) +
1115 " unknown flavor (" + Twine(flavor) + ") for "
1116 "flavor number " + Twine(nflavor) + " in " +
1117 CmdName + " command");
1118 }
Kevin Enderby210030b2016-10-19 23:44:34 +00001119 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1120 if (flavor == MachO::PPC_THREAD_STATE) {
1121 if (count != MachO::PPC_THREAD_STATE_COUNT)
1122 return malformedError("load command " + Twine(LoadCommandIndex) +
1123 " count not PPC_THREAD_STATE_COUNT for "
1124 "flavor number " + Twine(nflavor) + " which is "
1125 "a PPC_THREAD_STATE flavor in " + CmdName +
1126 " command");
1127 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1128 return malformedError("load command " + Twine(LoadCommandIndex) +
1129 " PPC_THREAD_STATE extends past end of "
1130 "command in " + CmdName + " command");
1131 state += sizeof(MachO::ppc_thread_state32_t);
1132 } else {
1133 return malformedError("load command " + Twine(LoadCommandIndex) +
1134 " unknown flavor (" + Twine(flavor) + ") for "
1135 "flavor number " + Twine(nflavor) + " in " +
1136 CmdName + " command");
1137 }
1138 } else {
1139 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1140 "command " + Twine(LoadCommandIndex) + " for " +
1141 CmdName + " command can't be checked");
1142 }
1143 nflavor++;
1144 }
1145 return Error::success();
1146}
1147
Lang Hames697e7cd2016-12-04 01:56:10 +00001148static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001149 const MachOObjectFile::LoadCommandInfo
1150 &Load,
1151 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001152 const char **LoadCmd,
1153 std::list<MachOElement> &Elements) {
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001154 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1155 return malformedError("load command " + Twine(LoadCommandIndex) +
1156 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1157 if (*LoadCmd != nullptr)
1158 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1159 MachO::twolevel_hints_command Hints =
1160 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
Lang Hames697e7cd2016-12-04 01:56:10 +00001161 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001162 if (Hints.offset > FileSize)
1163 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1164 Twine(LoadCommandIndex) + " extends past the end of "
1165 "the file");
1166 uint64_t BigSize = Hints.nhints;
Jessica Paquette1a81dfb2017-10-17 20:43:33 +00001167 BigSize *= sizeof(MachO::twolevel_hint);
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001168 BigSize += Hints.offset;
1169 if (BigSize > FileSize)
1170 return malformedError("offset field plus nhints times sizeof(struct "
1171 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1172 Twine(LoadCommandIndex) + " extends past the end of "
1173 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001174 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1175 sizeof(MachO::twolevel_hint),
1176 "two level hints"))
1177 return Err;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001178 *LoadCmd = Load.Ptr;
1179 return Error::success();
1180}
1181
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001182// Returns true if the libObject code does not support the load command and its
1183// contents. The cmd value it is treated as an unknown load command but with
1184// an error message that says the cmd value is obsolete.
1185static bool isLoadCommandObsolete(uint32_t cmd) {
1186 if (cmd == MachO::LC_SYMSEG ||
1187 cmd == MachO::LC_LOADFVMLIB ||
1188 cmd == MachO::LC_IDFVMLIB ||
1189 cmd == MachO::LC_IDENT ||
1190 cmd == MachO::LC_FVMFILE ||
1191 cmd == MachO::LC_PREPAGE ||
1192 cmd == MachO::LC_PREBOUND_DYLIB ||
1193 cmd == MachO::LC_TWOLEVEL_HINTS ||
1194 cmd == MachO::LC_PREBIND_CKSUM)
1195 return true;
1196 return false;
1197}
1198
Lang Hames82627642016-03-25 21:59:14 +00001199Expected<std::unique_ptr<MachOObjectFile>>
1200MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001201 bool Is64Bits, uint32_t UniversalCputype,
1202 uint32_t UniversalIndex) {
Mehdi Amini41af4302016-11-11 04:28:40 +00001203 Error Err = Error::success();
Lang Hames82627642016-03-25 21:59:14 +00001204 std::unique_ptr<MachOObjectFile> Obj(
1205 new MachOObjectFile(std::move(Object), IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001206 Is64Bits, Err, UniversalCputype,
1207 UniversalIndex));
Lang Hames82627642016-03-25 21:59:14 +00001208 if (Err)
1209 return std::move(Err);
1210 return std::move(Obj);
1211}
1212
Rafael Espindola48af1c22014-08-19 18:44:46 +00001213MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001214 bool Is64bits, Error &Err,
1215 uint32_t UniversalCputype,
1216 uint32_t UniversalIndex)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00001217 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
Lang Hames5e51a2e2016-07-22 16:11:25 +00001218 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001219 uint64_t SizeOfHeaders;
Kevin Enderby79d6c632016-10-24 21:15:11 +00001220 uint32_t cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001221 if (is64Bit()) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001222 parseHeader(*this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001223 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001224 cputype = Header64.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001225 } else {
Lang Hames697e7cd2016-12-04 01:56:10 +00001226 parseHeader(*this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001227 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001228 cputype = Header.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001229 }
Lang Hames9e964f32016-03-25 17:25:34 +00001230 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +00001231 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +00001232 SizeOfHeaders += getHeader().sizeofcmds;
1233 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001234 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +00001235 return;
1236 }
Kevin Enderby79d6c632016-10-24 21:15:11 +00001237 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1238 Err = malformedError("universal header architecture: " +
1239 Twine(UniversalIndex) + "'s cputype does not match "
1240 "object file's mach header");
1241 return;
1242 }
Kevin Enderbyd5039402016-10-31 20:29:48 +00001243 std::list<MachOElement> Elements;
1244 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001245
1246 uint32_t LoadCommandCount = getHeader().ncmds;
Lang Hames9e964f32016-03-25 17:25:34 +00001247 LoadCommandInfo Load;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001248 if (LoadCommandCount != 0) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001249 if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001250 Load = *LoadOrErr;
1251 else {
1252 Err = LoadOrErr.takeError();
1253 return;
1254 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001255 }
Lang Hames9e964f32016-03-25 17:25:34 +00001256
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001257 const char *DyldIdLoadCmd = nullptr;
Kevin Enderby90986e62016-09-26 21:11:03 +00001258 const char *FuncStartsLoadCmd = nullptr;
1259 const char *SplitInfoLoadCmd = nullptr;
1260 const char *CodeSignDrsLoadCmd = nullptr;
Kevin Enderby89baf992016-10-18 20:24:12 +00001261 const char *CodeSignLoadCmd = nullptr;
Kevin Enderby32359db2016-09-28 21:20:45 +00001262 const char *VersLoadCmd = nullptr;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001263 const char *SourceLoadCmd = nullptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001264 const char *EntryPointLoadCmd = nullptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001265 const char *EncryptLoadCmd = nullptr;
Kevin Enderby6f695822016-10-18 17:54:17 +00001266 const char *RoutinesLoadCmd = nullptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001267 const char *UnixThreadLoadCmd = nullptr;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001268 const char *TwoLevelHintsLoadCmd = nullptr;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001269 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +00001270 if (is64Bit()) {
1271 if (Load.C.cmdsize % 8 != 0) {
1272 // We have a hack here to allow 64-bit Mach-O core files to have
1273 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1274 // allowed since the macOS kernel produces them.
1275 if (getHeader().filetype != MachO::MH_CORE ||
1276 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1277 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1278 "multiple of 8");
1279 return;
1280 }
1281 }
1282 } else {
1283 if (Load.C.cmdsize % 4 != 0) {
1284 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1285 "multiple of 4");
1286 return;
1287 }
1288 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001289 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001290 if (Load.C.cmd == MachO::LC_SYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001291 if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001292 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001293 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001294 if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001295 Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001296 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001297 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001298 if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001299 "LC_DATA_IN_CODE", Elements,
1300 "data in code info")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001301 return;
Kevin Enderby9a509442015-01-27 21:28:24 +00001302 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001303 if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001304 "LC_LINKER_OPTIMIZATION_HINT",
1305 Elements, "linker optimization "
1306 "hints")))
Kevin Enderby9a509442015-01-27 21:28:24 +00001307 return;
Kevin Enderby90986e62016-09-26 21:11:03 +00001308 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001309 if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001310 "LC_FUNCTION_STARTS", Elements,
1311 "function starts data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001312 return;
1313 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001314 if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001315 "LC_SEGMENT_SPLIT_INFO", Elements,
1316 "split info data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001317 return;
1318 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001319 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001320 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1321 "code signing RDs data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001322 return;
Kevin Enderby89baf992016-10-18 20:24:12 +00001323 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001324 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001325 "LC_CODE_SIGNATURE", Elements,
1326 "code signature data")))
Kevin Enderby89baf992016-10-18 20:24:12 +00001327 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001328 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001329 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001330 "LC_DYLD_INFO", Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001331 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001332 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001333 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001334 "LC_DYLD_INFO_ONLY", Elements)))
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001335 return;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001336 } else if (Load.C.cmd == MachO::LC_UUID) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001337 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1338 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1339 "cmdsize");
1340 return;
1341 }
David Majnemer73cc6ff2014-11-13 19:48:56 +00001342 if (UuidLoadCmd) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001343 Err = malformedError("more than one LC_UUID command");
David Majnemer73cc6ff2014-11-13 19:48:56 +00001344 return;
1345 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001346 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001347 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001348 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1349 MachO::section_64>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001350 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001351 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001352 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001353 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001354 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1355 MachO::section>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001356 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001357 "LC_SEGMENT", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001358 return;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001359 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001360 if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001361 return;
1362 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001363 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001364 return;
1365 Libraries.push_back(Load.Ptr);
1366 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001367 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001368 return;
1369 Libraries.push_back(Load.Ptr);
1370 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001371 if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001372 return;
1373 Libraries.push_back(Load.Ptr);
1374 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001375 if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001376 return;
1377 Libraries.push_back(Load.Ptr);
1378 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001379 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001380 return;
Kevin Enderby980b2582014-06-05 21:21:57 +00001381 Libraries.push_back(Load.Ptr);
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001382 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001383 if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001384 return;
1385 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001386 if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001387 return;
1388 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001389 if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001390 return;
Kevin Enderby32359db2016-09-28 21:20:45 +00001391 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001392 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001393 "LC_VERSION_MIN_MACOSX")))
1394 return;
1395 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001396 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001397 "LC_VERSION_MIN_IPHONEOS")))
1398 return;
1399 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001400 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001401 "LC_VERSION_MIN_TVOS")))
1402 return;
1403 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001404 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001405 "LC_VERSION_MIN_WATCHOS")))
1406 return;
Kevin Enderbya4579c42017-01-19 17:36:31 +00001407 } else if (Load.C.cmd == MachO::LC_NOTE) {
1408 if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1409 return;
Steven Wu5b54a422017-01-23 20:07:55 +00001410 } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1411 if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1412 return;
Kevin Enderby76966bf2016-09-28 23:16:01 +00001413 } else if (Load.C.cmd == MachO::LC_RPATH) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001414 if ((Err = checkRpathCommand(*this, Load, I)))
Kevin Enderby76966bf2016-09-28 23:16:01 +00001415 return;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001416 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1417 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1418 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1419 " has incorrect cmdsize");
1420 return;
1421 }
1422 if (SourceLoadCmd) {
1423 Err = malformedError("more than one LC_SOURCE_VERSION command");
1424 return;
1425 }
1426 SourceLoadCmd = Load.Ptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001427 } else if (Load.C.cmd == MachO::LC_MAIN) {
1428 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1429 Err = malformedError("LC_MAIN command " + Twine(I) +
1430 " has incorrect cmdsize");
1431 return;
1432 }
1433 if (EntryPointLoadCmd) {
1434 Err = malformedError("more than one LC_MAIN command");
1435 return;
1436 }
1437 EntryPointLoadCmd = Load.Ptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001438 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1439 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1440 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1441 " has incorrect cmdsize");
1442 return;
1443 }
1444 MachO::encryption_info_command E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001445 getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1446 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001447 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1448 return;
1449 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1450 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1451 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1452 " has incorrect cmdsize");
1453 return;
1454 }
1455 MachO::encryption_info_command_64 E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001456 getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1457 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001458 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1459 return;
Kevin Enderby68fffa82016-10-11 21:04:39 +00001460 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001461 if ((Err = checkLinkerOptCommand(*this, Load, I)))
Kevin Enderby68fffa82016-10-11 21:04:39 +00001462 return;
Kevin Enderby2490de02016-10-17 22:09:25 +00001463 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1464 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1465 Err = malformedError("load command " + Twine(I) +
1466 " LC_SUB_FRAMEWORK cmdsize too small");
1467 return;
1468 }
1469 MachO::sub_framework_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001470 getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1471 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
Kevin Enderby2490de02016-10-17 22:09:25 +00001472 sizeof(MachO::sub_framework_command),
1473 "sub_framework_command", S.umbrella,
1474 "umbrella")))
1475 return;
1476 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1477 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1478 Err = malformedError("load command " + Twine(I) +
1479 " LC_SUB_UMBRELLA cmdsize too small");
1480 return;
1481 }
1482 MachO::sub_umbrella_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001483 getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1484 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
Kevin Enderby2490de02016-10-17 22:09:25 +00001485 sizeof(MachO::sub_umbrella_command),
1486 "sub_umbrella_command", S.sub_umbrella,
1487 "sub_umbrella")))
1488 return;
1489 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1490 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1491 Err = malformedError("load command " + Twine(I) +
1492 " LC_SUB_LIBRARY cmdsize too small");
1493 return;
1494 }
1495 MachO::sub_library_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001496 getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1497 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
Kevin Enderby2490de02016-10-17 22:09:25 +00001498 sizeof(MachO::sub_library_command),
1499 "sub_library_command", S.sub_library,
1500 "sub_library")))
1501 return;
1502 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1503 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1504 Err = malformedError("load command " + Twine(I) +
1505 " LC_SUB_CLIENT cmdsize too small");
1506 return;
1507 }
1508 MachO::sub_client_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001509 getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1510 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
Kevin Enderby2490de02016-10-17 22:09:25 +00001511 sizeof(MachO::sub_client_command),
1512 "sub_client_command", S.client, "client")))
1513 return;
Kevin Enderby6f695822016-10-18 17:54:17 +00001514 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1515 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1516 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1517 " has incorrect cmdsize");
1518 return;
1519 }
1520 if (RoutinesLoadCmd) {
1521 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1522 "command");
1523 return;
1524 }
1525 RoutinesLoadCmd = Load.Ptr;
1526 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1527 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1528 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1529 " has incorrect cmdsize");
1530 return;
1531 }
1532 if (RoutinesLoadCmd) {
1533 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1534 "command");
1535 return;
1536 }
1537 RoutinesLoadCmd = Load.Ptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001538 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001539 if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001540 return;
1541 if (UnixThreadLoadCmd) {
1542 Err = malformedError("more than one LC_UNIXTHREAD command");
1543 return;
1544 }
1545 UnixThreadLoadCmd = Load.Ptr;
1546 } else if (Load.C.cmd == MachO::LC_THREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001547 if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001548 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001549 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001550 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001551 if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001552 &TwoLevelHintsLoadCmd, Elements)))
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001553 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001554 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1555 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1556 Twine(Load.C.cmd) + " is obsolete and not "
1557 "supported");
1558 return;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001559 }
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001560 // TODO: generate a error for unknown load commands by default. But still
1561 // need work out an approach to allow or not allow unknown values like this
1562 // as an option for some uses like lldb.
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001563 if (I < LoadCommandCount - 1) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001564 if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +00001565 Load = *LoadOrErr;
1566 else {
1567 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001568 return;
1569 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001570 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001571 }
Kevin Enderby1829c682016-01-22 22:49:55 +00001572 if (!SymtabLoadCmd) {
1573 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001574 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +00001575 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +00001576 return;
1577 }
1578 } else if (DysymtabLoadCmd) {
1579 MachO::symtab_command Symtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001580 getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001581 MachO::dysymtab_command Dysymtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001582 getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001583 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001584 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001585 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001586 return;
1587 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001588 uint64_t BigSize = Dysymtab.ilocalsym;
1589 BigSize += Dysymtab.nlocalsym;
1590 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001591 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001592 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001593 return;
1594 }
1595 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001596 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001597 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001598 return;
1599 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001600 BigSize = Dysymtab.iextdefsym;
1601 BigSize += Dysymtab.nextdefsym;
1602 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001603 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +00001604 "load command extends past the end of the symbol "
1605 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001606 return;
1607 }
1608 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001609 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001610 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001611 return;
1612 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001613 BigSize = Dysymtab.iundefsym;
1614 BigSize += Dysymtab.nundefsym;
1615 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001616 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001617 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001618 return;
1619 }
1620 }
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001621 if ((getHeader().filetype == MachO::MH_DYLIB ||
1622 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1623 DyldIdLoadCmd == nullptr) {
1624 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1625 "filetype");
1626 return;
1627 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001628 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +00001629
1630 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001631}
1632
Kevin Enderby22fc0072016-11-14 20:57:04 +00001633Error MachOObjectFile::checkSymbolTable() const {
1634 uint32_t Flags = 0;
1635 if (is64Bit()) {
1636 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1637 Flags = H_64.flags;
1638 } else {
1639 MachO::mach_header H = MachOObjectFile::getHeader();
1640 Flags = H.flags;
1641 }
1642 uint8_t NType = 0;
1643 uint8_t NSect = 0;
1644 uint16_t NDesc = 0;
1645 uint32_t NStrx = 0;
1646 uint64_t NValue = 0;
1647 uint32_t SymbolIndex = 0;
1648 MachO::symtab_command S = getSymtabLoadCommand();
1649 for (const SymbolRef &Symbol : symbols()) {
1650 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1651 if (is64Bit()) {
1652 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1653 NType = STE_64.n_type;
1654 NSect = STE_64.n_sect;
1655 NDesc = STE_64.n_desc;
1656 NStrx = STE_64.n_strx;
1657 NValue = STE_64.n_value;
1658 } else {
1659 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1660 NType = STE.n_type;
1661 NType = STE.n_type;
1662 NSect = STE.n_sect;
1663 NDesc = STE.n_desc;
1664 NStrx = STE.n_strx;
1665 NValue = STE.n_value;
1666 }
1667 if ((NType & MachO::N_STAB) == 0 &&
1668 (NType & MachO::N_TYPE) == MachO::N_SECT) {
1669 if (NSect == 0 || NSect > Sections.size())
1670 return malformedError("bad section index: " + Twine((int)NSect) +
1671 " for symbol at index " + Twine(SymbolIndex));
1672 }
1673 if ((NType & MachO::N_STAB) == 0 &&
1674 (NType & MachO::N_TYPE) == MachO::N_INDR) {
1675 if (NValue >= S.strsize)
1676 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1677 "the end of string table, for N_INDR symbol at "
1678 "index " + Twine(SymbolIndex));
1679 }
1680 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1681 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1682 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1683 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1684 if (LibraryOrdinal != 0 &&
1685 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1686 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1687 LibraryOrdinal - 1 >= Libraries.size() ) {
1688 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1689 " for symbol at index " + Twine(SymbolIndex));
1690 }
1691 }
1692 if (NStrx >= S.strsize)
1693 return malformedError("bad string table index: " + Twine((int)NStrx) +
1694 " past the end of string table, for symbol at "
1695 "index " + Twine(SymbolIndex));
1696 SymbolIndex++;
1697 }
1698 return Error::success();
1699}
1700
Rafael Espindola5e812af2014-01-30 02:49:50 +00001701void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001702 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001703 sizeof(MachO::nlist_64) :
1704 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +00001705 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001706}
1707
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001708Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001709 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001710 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Michael Trentca309022018-01-03 23:28:32 +00001711 if (Entry.n_strx == 0)
1712 // A n_strx value of 0 indicates that no name is associated with a
1713 // particular symbol table entry.
1714 return StringRef();
Charles Davis8bdfafd2013-09-01 04:28:48 +00001715 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001716 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001717 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +00001718 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001719 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00001720 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001721}
1722
Rafael Espindola0e77a942014-12-10 20:46:55 +00001723unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1724 DataRefImpl DRI = Sec.getRawDataRefImpl();
Lang Hames697e7cd2016-12-04 01:56:10 +00001725 uint32_t Flags = getSectionFlags(*this, DRI);
Rafael Espindola0e77a942014-12-10 20:46:55 +00001726 return Flags & MachO::SECTION_TYPE;
1727}
1728
Rafael Espindola59128922015-06-24 18:14:41 +00001729uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1730 if (is64Bit()) {
1731 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1732 return Entry.n_value;
1733 }
1734 MachO::nlist Entry = getSymbolTableEntry(Sym);
1735 return Entry.n_value;
1736}
1737
Kevin Enderby980b2582014-06-05 21:21:57 +00001738// getIndirectName() returns the name of the alias'ed symbol who's string table
1739// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +00001740std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1741 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001742 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001743 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Rafael Espindola59128922015-06-24 18:14:41 +00001744 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1745 return object_error::parse_failed;
1746 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +00001747 if (NValue >= StringTable.size())
1748 return object_error::parse_failed;
1749 const char *Start = &StringTable.data()[NValue];
1750 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +00001751 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001752}
1753
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +00001754uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +00001755 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +00001756}
1757
Kevin Enderby931cb652016-06-24 18:24:42 +00001758Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +00001759 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001760}
1761
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001762uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +00001763 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001764 if (flags & SymbolRef::SF_Common) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001765 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001766 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001767 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001768 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001769}
1770
Rafael Espindolad7a32ea2015-06-24 10:20:30 +00001771uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001772 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001773}
1774
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001775Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001776MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001777 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001778 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001779
Rafael Espindola56f976f2013-04-18 18:08:55 +00001780 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001781 if (n_type & MachO::N_STAB)
1782 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001783
Charles Davis74ec8b02013-08-27 05:00:13 +00001784 switch (n_type & MachO::N_TYPE) {
1785 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001786 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +00001787 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001788 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001789 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001790 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001791 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +00001792 if (Sec->isData() || Sec->isBSS())
1793 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001794 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001795 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001796 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001797}
1798
Rafael Espindola20122a42014-01-31 20:57:12 +00001799uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001800 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001801
Charles Davis8bdfafd2013-09-01 04:28:48 +00001802 uint8_t MachOType = Entry.n_type;
1803 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001804
Rafael Espindola20122a42014-01-31 20:57:12 +00001805 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001806
Tim Northovereaef0742014-05-30 13:22:59 +00001807 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1808 Result |= SymbolRef::SF_Indirect;
1809
Rafael Espindolaa1356322013-11-02 05:03:24 +00001810 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001811 Result |= SymbolRef::SF_FormatSpecific;
1812
Charles Davis74ec8b02013-08-27 05:00:13 +00001813 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001814 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +00001815 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001816 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001817 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +00001818 else
1819 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001820 }
Lang Hames7e0692b2015-01-15 22:33:30 +00001821
1822 if (!(MachOType & MachO::N_PEXT))
1823 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001824 }
1825
Charles Davis74ec8b02013-08-27 05:00:13 +00001826 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +00001827 Result |= SymbolRef::SF_Weak;
1828
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001829 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1830 Result |= SymbolRef::SF_Thumb;
1831
Charles Davis74ec8b02013-08-27 05:00:13 +00001832 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001833 Result |= SymbolRef::SF_Absolute;
1834
Rafael Espindola20122a42014-01-31 20:57:12 +00001835 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001836}
1837
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001838Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +00001839MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001840 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001841 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001842
Rafael Espindola8bab8892015-08-07 23:27:14 +00001843 if (index == 0)
1844 return section_end();
1845 DataRefImpl DRI;
1846 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001847 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001848 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +00001849 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001850 }
Rafael Espindola8bab8892015-08-07 23:27:14 +00001851 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001852}
1853
Rafael Espindola6bf32212015-06-24 19:57:32 +00001854unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1855 MachO::nlist_base Entry =
Lang Hames697e7cd2016-12-04 01:56:10 +00001856 getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
Rafael Espindola6bf32212015-06-24 19:57:32 +00001857 return Entry.n_sect - 1;
1858}
1859
Rafael Espindola5e812af2014-01-30 02:49:50 +00001860void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001861 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001862}
1863
Rafael Espindola3acea392014-06-12 21:46:39 +00001864std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1865 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001866 ArrayRef<char> Raw = getSectionRawName(Sec);
1867 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +00001868 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001869}
1870
Rafael Espindola80291272014-10-08 15:28:58 +00001871uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1872 if (is64Bit())
1873 return getSection64(Sec).addr;
1874 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001875}
1876
George Rimara25d3292017-05-27 18:10:23 +00001877uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1878 return Sec.d.a;
1879}
1880
Rafael Espindola80291272014-10-08 15:28:58 +00001881uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +00001882 // In the case if a malformed Mach-O file where the section offset is past
1883 // the end of the file or some part of the section size is past the end of
1884 // the file return a size of zero or a size that covers the rest of the file
1885 // but does not extend past the end of the file.
1886 uint32_t SectOffset, SectType;
1887 uint64_t SectSize;
1888
1889 if (is64Bit()) {
1890 MachO::section_64 Sect = getSection64(Sec);
1891 SectOffset = Sect.offset;
1892 SectSize = Sect.size;
1893 SectType = Sect.flags & MachO::SECTION_TYPE;
1894 } else {
1895 MachO::section Sect = getSection(Sec);
1896 SectOffset = Sect.offset;
1897 SectSize = Sect.size;
1898 SectType = Sect.flags & MachO::SECTION_TYPE;
1899 }
1900 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1901 return SectSize;
1902 uint64_t FileSize = getData().size();
1903 if (SectOffset > FileSize)
1904 return 0;
1905 if (FileSize - SectOffset < SectSize)
1906 return FileSize - SectOffset;
1907 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001908}
1909
Rafael Espindola3acea392014-06-12 21:46:39 +00001910std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1911 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001912 uint32_t Offset;
1913 uint64_t Size;
1914
1915 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001916 MachO::section_64 Sect = getSection64(Sec);
1917 Offset = Sect.offset;
1918 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001919 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001920 MachO::section Sect = getSection(Sec);
1921 Offset = Sect.offset;
1922 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001923 }
1924
1925 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +00001926 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001927}
1928
Rafael Espindola80291272014-10-08 15:28:58 +00001929uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001930 uint32_t Align;
1931 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001932 MachO::section_64 Sect = getSection64(Sec);
1933 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001934 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001935 MachO::section Sect = getSection(Sec);
1936 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001937 }
1938
Rafael Espindola80291272014-10-08 15:28:58 +00001939 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001940}
1941
George Rimar401e4e52016-05-24 12:48:46 +00001942bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1943 return false;
1944}
1945
Rafael Espindola80291272014-10-08 15:28:58 +00001946bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001947 uint32_t Flags = getSectionFlags(*this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +00001948 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001949}
1950
Rafael Espindola80291272014-10-08 15:28:58 +00001951bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001952 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001953 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001954 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1955 !(SectionType == MachO::S_ZEROFILL ||
1956 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +00001957}
1958
Rafael Espindola80291272014-10-08 15:28:58 +00001959bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001960 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001961 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001962 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1963 (SectionType == MachO::S_ZEROFILL ||
1964 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +00001965}
1966
Rafael Espindola6bf32212015-06-24 19:57:32 +00001967unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1968 return Sec.getRawDataRefImpl().d.a;
1969}
1970
Rafael Espindola80291272014-10-08 15:28:58 +00001971bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Francis Visoiu Mistrih18346822018-04-19 17:02:57 +00001972 uint32_t Flags = getSectionFlags(*this, Sec);
1973 unsigned SectionType = Flags & MachO::SECTION_TYPE;
1974 return SectionType == MachO::S_ZEROFILL ||
1975 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindolac2413f52013-04-09 14:49:08 +00001976}
1977
Steven Wuf2fe0142016-02-29 19:40:10 +00001978bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1979 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1980 StringRef SectName;
1981 if (!getSectionName(Sec, SectName))
1982 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1983 return false;
1984}
1985
Jonas Devlieghere8af23872017-09-26 14:22:35 +00001986bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
1987 if (is64Bit())
1988 return getSection64(Sec).offset == 0;
1989 return getSection(Sec).offset == 0;
1990}
1991
Rui Ueyamabc654b12013-09-27 21:47:05 +00001992relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001993 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001994 Ret.d.a = Sec.d.a;
1995 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +00001996 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +00001997}
Rafael Espindolac0406e12013-04-08 20:45:01 +00001998
Rafael Espindola56f976f2013-04-18 18:08:55 +00001999relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +00002000MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00002001 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002002 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002003 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002004 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002005 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002006 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002007 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002008 }
Eric Christopher7b015c72011-04-22 03:19:48 +00002009
Rafael Espindola56f976f2013-04-18 18:08:55 +00002010 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00002011 Ret.d.a = Sec.d.a;
2012 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002013 return relocation_iterator(RelocationRef(Ret, this));
2014}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00002015
Kevin Enderbyabf10f22017-06-22 17:41:22 +00002016relocation_iterator MachOObjectFile::extrel_begin() const {
2017 DataRefImpl Ret;
Michael Trenta1703b12017-12-15 17:57:40 +00002018 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
Kevin Enderbyabf10f22017-06-22 17:41:22 +00002019 Ret.d.a = 0; // Would normally be a section index.
2020 Ret.d.b = 0; // Index into the external relocations
2021 return relocation_iterator(RelocationRef(Ret, this));
2022}
2023
2024relocation_iterator MachOObjectFile::extrel_end() const {
2025 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2026 DataRefImpl Ret;
Michael Trenta1703b12017-12-15 17:57:40 +00002027 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
Kevin Enderbyabf10f22017-06-22 17:41:22 +00002028 Ret.d.a = 0; // Would normally be a section index.
2029 Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
2030 return relocation_iterator(RelocationRef(Ret, this));
2031}
2032
Michael Trenta1703b12017-12-15 17:57:40 +00002033relocation_iterator MachOObjectFile::locrel_begin() const {
2034 DataRefImpl Ret;
2035 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2036 Ret.d.a = 1; // Would normally be a section index.
2037 Ret.d.b = 0; // Index into the local relocations
2038 return relocation_iterator(RelocationRef(Ret, this));
2039}
2040
2041relocation_iterator MachOObjectFile::locrel_end() const {
2042 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2043 DataRefImpl Ret;
2044 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2045 Ret.d.a = 1; // Would normally be a section index.
2046 Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
2047 return relocation_iterator(RelocationRef(Ret, this));
2048}
2049
Rafael Espindola5e812af2014-01-30 02:49:50 +00002050void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002051 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00002052}
Owen Anderson171f4852011-10-24 23:20:07 +00002053
Rafael Espindola96d071c2015-06-29 23:29:12 +00002054uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Kevin Enderbyabf10f22017-06-22 17:41:22 +00002055 assert((getHeader().filetype == MachO::MH_OBJECT ||
2056 getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
2057 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002058 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +00002059 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +00002060}
2061
Rafael Espindola806f0062013-06-05 01:33:53 +00002062symbol_iterator
2063MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002064 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00002065 if (isRelocationScattered(RE))
2066 return symbol_end();
2067
Rafael Espindola56f976f2013-04-18 18:08:55 +00002068 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
2069 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00002070 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00002071 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00002072
Charles Davis8bdfafd2013-09-01 04:28:48 +00002073 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00002074 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002075 sizeof(MachO::nlist_64) :
2076 sizeof(MachO::nlist);
2077 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00002078 DataRefImpl Sym;
Lang Hames697e7cd2016-12-04 01:56:10 +00002079 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00002080 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002081}
2082
Keno Fischerc780e8e2015-05-21 21:24:32 +00002083section_iterator
2084MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2085 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2086}
2087
Rafael Espindola99c041b2015-06-30 01:53:01 +00002088uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002089 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00002090 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002091}
2092
Rafael Espindola41bb4322015-06-30 04:08:37 +00002093void MachOObjectFile::getRelocationTypeName(
2094 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002095 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00002096 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002097
2098 unsigned Arch = this->getArch();
2099
2100 switch (Arch) {
2101 case Triple::x86: {
2102 static const char *const Table[] = {
2103 "GENERIC_RELOC_VANILLA",
2104 "GENERIC_RELOC_PAIR",
2105 "GENERIC_RELOC_SECTDIFF",
2106 "GENERIC_RELOC_PB_LA_PTR",
2107 "GENERIC_RELOC_LOCAL_SECTDIFF",
2108 "GENERIC_RELOC_TLV" };
2109
Eric Christopher13250cb2013-12-06 02:33:38 +00002110 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002111 res = "Unknown";
2112 else
2113 res = Table[RType];
2114 break;
2115 }
2116 case Triple::x86_64: {
2117 static const char *const Table[] = {
2118 "X86_64_RELOC_UNSIGNED",
2119 "X86_64_RELOC_SIGNED",
2120 "X86_64_RELOC_BRANCH",
2121 "X86_64_RELOC_GOT_LOAD",
2122 "X86_64_RELOC_GOT",
2123 "X86_64_RELOC_SUBTRACTOR",
2124 "X86_64_RELOC_SIGNED_1",
2125 "X86_64_RELOC_SIGNED_2",
2126 "X86_64_RELOC_SIGNED_4",
2127 "X86_64_RELOC_TLV" };
2128
2129 if (RType > 9)
2130 res = "Unknown";
2131 else
2132 res = Table[RType];
2133 break;
2134 }
2135 case Triple::arm: {
2136 static const char *const Table[] = {
2137 "ARM_RELOC_VANILLA",
2138 "ARM_RELOC_PAIR",
2139 "ARM_RELOC_SECTDIFF",
2140 "ARM_RELOC_LOCAL_SECTDIFF",
2141 "ARM_RELOC_PB_LA_PTR",
2142 "ARM_RELOC_BR24",
2143 "ARM_THUMB_RELOC_BR22",
2144 "ARM_THUMB_32BIT_BRANCH",
2145 "ARM_RELOC_HALF",
2146 "ARM_RELOC_HALF_SECTDIFF" };
2147
2148 if (RType > 9)
2149 res = "Unknown";
2150 else
2151 res = Table[RType];
2152 break;
2153 }
Tim Northover00ed9962014-03-29 10:18:08 +00002154 case Triple::aarch64: {
2155 static const char *const Table[] = {
2156 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2157 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2158 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2159 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2160 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2161 "ARM64_RELOC_ADDEND"
2162 };
2163
2164 if (RType >= array_lengthof(Table))
2165 res = "Unknown";
2166 else
2167 res = Table[RType];
2168 break;
2169 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00002170 case Triple::ppc: {
2171 static const char *const Table[] = {
2172 "PPC_RELOC_VANILLA",
2173 "PPC_RELOC_PAIR",
2174 "PPC_RELOC_BR14",
2175 "PPC_RELOC_BR24",
2176 "PPC_RELOC_HI16",
2177 "PPC_RELOC_LO16",
2178 "PPC_RELOC_HA16",
2179 "PPC_RELOC_LO14",
2180 "PPC_RELOC_SECTDIFF",
2181 "PPC_RELOC_PB_LA_PTR",
2182 "PPC_RELOC_HI16_SECTDIFF",
2183 "PPC_RELOC_LO16_SECTDIFF",
2184 "PPC_RELOC_HA16_SECTDIFF",
2185 "PPC_RELOC_JBSR",
2186 "PPC_RELOC_LO14_SECTDIFF",
2187 "PPC_RELOC_LOCAL_SECTDIFF" };
2188
Eric Christopher13250cb2013-12-06 02:33:38 +00002189 if (RType > 15)
2190 res = "Unknown";
2191 else
2192 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00002193 break;
2194 }
2195 case Triple::UnknownArch:
2196 res = "Unknown";
2197 break;
2198 }
2199 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00002200}
2201
Keno Fischer281b6942015-05-30 19:44:53 +00002202uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2203 MachO::any_relocation_info RE = getRelocation(Rel);
2204 return getAnyRelocationLength(RE);
2205}
2206
Kevin Enderby980b2582014-06-05 21:21:57 +00002207//
2208// guessLibraryShortName() is passed a name of a dynamic library and returns a
2209// guess on what the short name is. Then name is returned as a substring of the
2210// StringRef Name passed in. The name of the dynamic library is recognized as
2211// a framework if it has one of the two following forms:
2212// Foo.framework/Versions/A/Foo
2213// Foo.framework/Foo
2214// Where A and Foo can be any string. And may contain a trailing suffix
2215// starting with an underbar. If the Name is recognized as a framework then
2216// isFramework is set to true else it is set to false. If the Name has a
2217// suffix then Suffix is set to the substring in Name that contains the suffix
2218// else it is set to a NULL StringRef.
2219//
2220// The Name of the dynamic library is recognized as a library name if it has
2221// one of the two following forms:
2222// libFoo.A.dylib
2223// libFoo.dylib
2224// The library may have a suffix trailing the name Foo of the form:
2225// libFoo_profile.A.dylib
2226// libFoo_profile.dylib
2227//
2228// The Name of the dynamic library is also recognized as a library name if it
2229// has the following form:
2230// Foo.qtx
2231//
2232// If the Name of the dynamic library is none of the forms above then a NULL
2233// StringRef is returned.
2234//
2235StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2236 bool &isFramework,
2237 StringRef &Suffix) {
2238 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2239 size_t a, b, c, d, Idx;
2240
2241 isFramework = false;
2242 Suffix = StringRef();
2243
2244 // Pull off the last component and make Foo point to it
2245 a = Name.rfind('/');
2246 if (a == Name.npos || a == 0)
2247 goto guess_library;
2248 Foo = Name.slice(a+1, Name.npos);
2249
2250 // Look for a suffix starting with a '_'
2251 Idx = Foo.rfind('_');
2252 if (Idx != Foo.npos && Foo.size() >= 2) {
2253 Suffix = Foo.slice(Idx, Foo.npos);
2254 Foo = Foo.slice(0, Idx);
2255 }
2256
2257 // First look for the form Foo.framework/Foo
2258 b = Name.rfind('/', a);
2259 if (b == Name.npos)
2260 Idx = 0;
2261 else
2262 Idx = b+1;
2263 F = Name.slice(Idx, Idx + Foo.size());
2264 DotFramework = Name.slice(Idx + Foo.size(),
2265 Idx + Foo.size() + sizeof(".framework/")-1);
2266 if (F == Foo && DotFramework == ".framework/") {
2267 isFramework = true;
2268 return Foo;
2269 }
2270
2271 // Next look for the form Foo.framework/Versions/A/Foo
2272 if (b == Name.npos)
2273 goto guess_library;
2274 c = Name.rfind('/', b);
2275 if (c == Name.npos || c == 0)
2276 goto guess_library;
2277 V = Name.slice(c+1, Name.npos);
2278 if (!V.startswith("Versions/"))
2279 goto guess_library;
2280 d = Name.rfind('/', c);
2281 if (d == Name.npos)
2282 Idx = 0;
2283 else
2284 Idx = d+1;
2285 F = Name.slice(Idx, Idx + Foo.size());
2286 DotFramework = Name.slice(Idx + Foo.size(),
2287 Idx + Foo.size() + sizeof(".framework/")-1);
2288 if (F == Foo && DotFramework == ".framework/") {
2289 isFramework = true;
2290 return Foo;
2291 }
2292
2293guess_library:
2294 // pull off the suffix after the "." and make a point to it
2295 a = Name.rfind('.');
2296 if (a == Name.npos || a == 0)
2297 return StringRef();
2298 Dylib = Name.slice(a, Name.npos);
2299 if (Dylib != ".dylib")
2300 goto guess_qtx;
2301
2302 // First pull off the version letter for the form Foo.A.dylib if any.
2303 if (a >= 3) {
2304 Dot = Name.slice(a-2, a-1);
2305 if (Dot == ".")
2306 a = a - 2;
2307 }
2308
2309 b = Name.rfind('/', a);
2310 if (b == Name.npos)
2311 b = 0;
2312 else
2313 b = b+1;
2314 // ignore any suffix after an underbar like Foo_profile.A.dylib
2315 Idx = Name.find('_', b);
2316 if (Idx != Name.npos && Idx != b) {
2317 Lib = Name.slice(b, Idx);
2318 Suffix = Name.slice(Idx, a);
2319 }
2320 else
2321 Lib = Name.slice(b, a);
2322 // There are incorrect library names of the form:
2323 // libATS.A_profile.dylib so check for these.
2324 if (Lib.size() >= 3) {
2325 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2326 if (Dot == ".")
2327 Lib = Lib.slice(0, Lib.size()-2);
2328 }
2329 return Lib;
2330
2331guess_qtx:
2332 Qtx = Name.slice(a, Name.npos);
2333 if (Qtx != ".qtx")
2334 return StringRef();
2335 b = Name.rfind('/', a);
2336 if (b == Name.npos)
2337 Lib = Name.slice(0, a);
2338 else
2339 Lib = Name.slice(b+1, a);
2340 // There are library names of the form: QT.A.qtx so check for these.
2341 if (Lib.size() >= 3) {
2342 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2343 if (Dot == ".")
2344 Lib = Lib.slice(0, Lib.size()-2);
2345 }
2346 return Lib;
2347}
2348
2349// getLibraryShortNameByIndex() is used to get the short name of the library
2350// for an undefined symbol in a linked Mach-O binary that was linked with the
2351// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2352// It is passed the index (0 - based) of the library as translated from
2353// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00002354std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00002355 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00002356 if (Index >= Libraries.size())
2357 return object_error::parse_failed;
2358
Kevin Enderby980b2582014-06-05 21:21:57 +00002359 // If the cache of LibrariesShortNames is not built up do that first for
2360 // all the Libraries.
2361 if (LibrariesShortNames.size() == 0) {
2362 for (unsigned i = 0; i < Libraries.size(); i++) {
2363 MachO::dylib_command D =
Lang Hames697e7cd2016-12-04 01:56:10 +00002364 getStruct<MachO::dylib_command>(*this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00002365 if (D.dylib.name >= D.cmdsize)
2366 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00002367 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00002368 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00002369 if (D.dylib.name+Name.size() >= D.cmdsize)
2370 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00002371 StringRef Suffix;
2372 bool isFramework;
2373 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00002374 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00002375 LibrariesShortNames.push_back(Name);
2376 else
2377 LibrariesShortNames.push_back(shortName);
2378 }
2379 }
2380
2381 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00002382 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00002383}
2384
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00002385uint32_t MachOObjectFile::getLibraryCount() const {
2386 return Libraries.size();
2387}
2388
Rafael Espindola76ad2322015-07-06 14:55:37 +00002389section_iterator
2390MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2391 DataRefImpl Sec;
2392 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2393 return section_iterator(SectionRef(Sec, this));
2394}
2395
Peter Collingbourne435890a2016-11-22 03:38:40 +00002396basic_symbol_iterator MachOObjectFile::symbol_begin() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00002397 DataRefImpl DRI;
2398 MachO::symtab_command Symtab = getSymtabLoadCommand();
2399 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2400 return basic_symbol_iterator(SymbolRef(DRI, this));
2401
Lang Hames36072da2014-05-12 21:39:59 +00002402 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002403}
2404
Peter Collingbourne435890a2016-11-22 03:38:40 +00002405basic_symbol_iterator MachOObjectFile::symbol_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002406 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00002407 MachO::symtab_command Symtab = getSymtabLoadCommand();
2408 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002409 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00002410
Rafael Espindola75c30362013-04-24 19:47:55 +00002411 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002412 sizeof(MachO::nlist_64) :
2413 sizeof(MachO::nlist);
2414 unsigned Offset = Symtab.symoff +
2415 Symtab.nsyms * SymbolTableEntrySize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002416 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002417 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002418}
2419
Lang Hames36072da2014-05-12 21:39:59 +00002420basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00002421 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00002422 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002423 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00002424 unsigned SymbolTableEntrySize =
2425 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00002426 DataRefImpl DRI;
Lang Hames697e7cd2016-12-04 01:56:10 +00002427 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Lang Hames36072da2014-05-12 21:39:59 +00002428 DRI.p += Index * SymbolTableEntrySize;
2429 return basic_symbol_iterator(SymbolRef(DRI, this));
2430}
2431
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002432uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2433 MachO::symtab_command Symtab = getSymtabLoadCommand();
2434 if (!SymtabLoadCmd)
2435 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2436 unsigned SymbolTableEntrySize =
2437 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2438 DataRefImpl DRIstart;
Lang Hames697e7cd2016-12-04 01:56:10 +00002439 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002440 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2441 return Index;
2442}
2443
Rafael Espindolab5155a52014-02-10 20:24:04 +00002444section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002445 DataRefImpl DRI;
2446 return section_iterator(SectionRef(DRI, this));
2447}
2448
Rafael Espindolab5155a52014-02-10 20:24:04 +00002449section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002450 DataRefImpl DRI;
2451 DRI.d.a = Sections.size();
2452 return section_iterator(SectionRef(DRI, this));
2453}
2454
Rafael Espindola56f976f2013-04-18 18:08:55 +00002455uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00002456 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00002457}
2458
Rafael Espindola56f976f2013-04-18 18:08:55 +00002459StringRef MachOObjectFile::getFileFormatName() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002460 unsigned CPUType = getCPUType(*this);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002461 if (!is64Bit()) {
2462 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002463 case MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002464 return "Mach-O 32-bit i386";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002465 case MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002466 return "Mach-O arm";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002467 case MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002468 return "Mach-O 32-bit ppc";
2469 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002470 return "Mach-O 32-bit unknown";
2471 }
2472 }
2473
Rafael Espindola56f976f2013-04-18 18:08:55 +00002474 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002475 case MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002476 return "Mach-O 64-bit x86-64";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002477 case MachO::CPU_TYPE_ARM64:
Tim Northover00ed9962014-03-29 10:18:08 +00002478 return "Mach-O arm64";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002479 case MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002480 return "Mach-O 64-bit ppc64";
2481 default:
2482 return "Mach-O 64-bit unknown";
2483 }
2484}
2485
Alexey Samsonove6388e62013-06-18 15:03:28 +00002486Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2487 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002488 case MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002489 return Triple::x86;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002490 case MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002491 return Triple::x86_64;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002492 case MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002493 return Triple::arm;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002494 case MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00002495 return Triple::aarch64;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002496 case MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002497 return Triple::ppc;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002498 case MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002499 return Triple::ppc64;
2500 default:
2501 return Triple::UnknownArch;
2502 }
2503}
2504
Tim Northover9e8eb412016-04-22 23:21:13 +00002505Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
Kevin Enderby59343a92016-12-16 22:54:02 +00002506 const char **McpuDefault,
2507 const char **ArchFlag) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002508 if (McpuDefault)
2509 *McpuDefault = nullptr;
Kevin Enderby59343a92016-12-16 22:54:02 +00002510 if (ArchFlag)
2511 *ArchFlag = nullptr;
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002512
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002513 switch (CPUType) {
2514 case MachO::CPU_TYPE_I386:
2515 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2516 case MachO::CPU_SUBTYPE_I386_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002517 if (ArchFlag)
2518 *ArchFlag = "i386";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002519 return Triple("i386-apple-darwin");
2520 default:
2521 return Triple();
2522 }
2523 case MachO::CPU_TYPE_X86_64:
2524 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2525 case MachO::CPU_SUBTYPE_X86_64_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002526 if (ArchFlag)
2527 *ArchFlag = "x86_64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002528 return Triple("x86_64-apple-darwin");
2529 case MachO::CPU_SUBTYPE_X86_64_H:
Kevin Enderby59343a92016-12-16 22:54:02 +00002530 if (ArchFlag)
2531 *ArchFlag = "x86_64h";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002532 return Triple("x86_64h-apple-darwin");
2533 default:
2534 return Triple();
2535 }
2536 case MachO::CPU_TYPE_ARM:
2537 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2538 case MachO::CPU_SUBTYPE_ARM_V4T:
Kevin Enderby59343a92016-12-16 22:54:02 +00002539 if (ArchFlag)
2540 *ArchFlag = "armv4t";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002541 return Triple("armv4t-apple-darwin");
2542 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
Kevin Enderby59343a92016-12-16 22:54:02 +00002543 if (ArchFlag)
2544 *ArchFlag = "armv5e";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002545 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002546 case MachO::CPU_SUBTYPE_ARM_XSCALE:
Kevin Enderby59343a92016-12-16 22:54:02 +00002547 if (ArchFlag)
2548 *ArchFlag = "xscale";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002549 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002550 case MachO::CPU_SUBTYPE_ARM_V6:
Kevin Enderby59343a92016-12-16 22:54:02 +00002551 if (ArchFlag)
2552 *ArchFlag = "armv6";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002553 return Triple("armv6-apple-darwin");
2554 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002555 if (McpuDefault)
2556 *McpuDefault = "cortex-m0";
Kevin Enderby59343a92016-12-16 22:54:02 +00002557 if (ArchFlag)
2558 *ArchFlag = "armv6m";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002559 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002560 case MachO::CPU_SUBTYPE_ARM_V7:
Kevin Enderby59343a92016-12-16 22:54:02 +00002561 if (ArchFlag)
2562 *ArchFlag = "armv7";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002563 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002564 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002565 if (McpuDefault)
2566 *McpuDefault = "cortex-m4";
Kevin Enderby59343a92016-12-16 22:54:02 +00002567 if (ArchFlag)
2568 *ArchFlag = "armv7em";
Tim Northover9e8eb412016-04-22 23:21:13 +00002569 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002570 case MachO::CPU_SUBTYPE_ARM_V7K:
Kevin Enderby7a165752017-01-24 23:41:04 +00002571 if (McpuDefault)
2572 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002573 if (ArchFlag)
2574 *ArchFlag = "armv7k";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002575 return Triple("armv7k-apple-darwin");
2576 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002577 if (McpuDefault)
2578 *McpuDefault = "cortex-m3";
Kevin Enderby59343a92016-12-16 22:54:02 +00002579 if (ArchFlag)
2580 *ArchFlag = "armv7m";
Tim Northover9e8eb412016-04-22 23:21:13 +00002581 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002582 case MachO::CPU_SUBTYPE_ARM_V7S:
Kevin Enderby7a165752017-01-24 23:41:04 +00002583 if (McpuDefault)
2584 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002585 if (ArchFlag)
2586 *ArchFlag = "armv7s";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002587 return Triple("armv7s-apple-darwin");
2588 default:
2589 return Triple();
2590 }
2591 case MachO::CPU_TYPE_ARM64:
2592 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2593 case MachO::CPU_SUBTYPE_ARM64_ALL:
Kevin Enderbydc412cc2017-02-10 19:27:10 +00002594 if (McpuDefault)
2595 *McpuDefault = "cyclone";
Kevin Enderby59343a92016-12-16 22:54:02 +00002596 if (ArchFlag)
2597 *ArchFlag = "arm64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002598 return Triple("arm64-apple-darwin");
2599 default:
2600 return Triple();
2601 }
2602 case MachO::CPU_TYPE_POWERPC:
2603 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2604 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002605 if (ArchFlag)
2606 *ArchFlag = "ppc";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002607 return Triple("ppc-apple-darwin");
2608 default:
2609 return Triple();
2610 }
2611 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00002612 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002613 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002614 if (ArchFlag)
2615 *ArchFlag = "ppc64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002616 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002617 default:
2618 return Triple();
2619 }
2620 default:
2621 return Triple();
2622 }
2623}
2624
2625Triple MachOObjectFile::getHostArch() {
2626 return Triple(sys::getDefaultTargetTriple());
2627}
2628
Rafael Espindola72318b42014-08-08 16:30:17 +00002629bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2630 return StringSwitch<bool>(ArchFlag)
2631 .Case("i386", true)
2632 .Case("x86_64", true)
2633 .Case("x86_64h", true)
2634 .Case("armv4t", true)
2635 .Case("arm", true)
2636 .Case("armv5e", true)
2637 .Case("armv6", true)
2638 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00002639 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002640 .Case("armv7em", true)
2641 .Case("armv7k", true)
2642 .Case("armv7m", true)
2643 .Case("armv7s", true)
2644 .Case("arm64", true)
2645 .Case("ppc", true)
2646 .Case("ppc64", true)
2647 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002648}
2649
Zachary Turner260fe3e2017-12-14 22:07:03 +00002650Triple::ArchType MachOObjectFile::getArch() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002651 return getArch(getCPUType(*this));
Alexey Samsonove6388e62013-06-18 15:03:28 +00002652}
2653
Tim Northover9e8eb412016-04-22 23:21:13 +00002654Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2655 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002656}
2657
Rui Ueyamabc654b12013-09-27 21:47:05 +00002658relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002659 DataRefImpl DRI;
2660 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002661 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002662}
2663
Rui Ueyamabc654b12013-09-27 21:47:05 +00002664relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002665 DataRefImpl DRI;
2666 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002667 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002668}
2669
Kevin Enderby273ae012013-06-06 17:20:50 +00002670dice_iterator MachOObjectFile::begin_dices() const {
2671 DataRefImpl DRI;
2672 if (!DataInCodeLoadCmd)
2673 return dice_iterator(DiceRef(DRI, this));
2674
Charles Davis8bdfafd2013-09-01 04:28:48 +00002675 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
Lang Hames697e7cd2016-12-04 01:56:10 +00002676 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00002677 return dice_iterator(DiceRef(DRI, this));
2678}
2679
2680dice_iterator MachOObjectFile::end_dices() const {
2681 DataRefImpl DRI;
2682 if (!DataInCodeLoadCmd)
2683 return dice_iterator(DiceRef(DRI, this));
2684
Charles Davis8bdfafd2013-09-01 04:28:48 +00002685 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2686 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002687 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Kevin Enderby273ae012013-06-06 17:20:50 +00002688 return dice_iterator(DiceRef(DRI, this));
2689}
2690
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002691ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
2692 ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002693
2694void ExportEntry::moveToFirst() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002695 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002696 pushNode(0);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002697 if (*E)
2698 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002699 pushDownUntilBottom();
2700}
2701
2702void ExportEntry::moveToEnd() {
2703 Stack.clear();
2704 Done = true;
2705}
2706
2707bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002708 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002709 if (Done || Other.Done)
2710 return (Done == Other.Done);
2711 // Not equal if different stack sizes.
2712 if (Stack.size() != Other.Stack.size())
2713 return false;
2714 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00002715 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00002716 return false;
2717 // Equal if all nodes in both stacks match.
2718 for (unsigned i=0; i < Stack.size(); ++i) {
2719 if (Stack[i].Start != Other.Stack[i].Start)
2720 return false;
2721 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002722 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002723}
2724
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002725uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002726 unsigned Count;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002727 uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002728 Ptr += Count;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002729 if (Ptr > Trie.end())
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002730 Ptr = Trie.end();
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002731 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002732}
2733
2734StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00002735 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002736}
2737
2738uint64_t ExportEntry::flags() const {
2739 return Stack.back().Flags;
2740}
2741
2742uint64_t ExportEntry::address() const {
2743 return Stack.back().Address;
2744}
2745
2746uint64_t ExportEntry::other() const {
2747 return Stack.back().Other;
2748}
2749
2750StringRef ExportEntry::otherName() const {
2751 const char* ImportName = Stack.back().ImportName;
2752 if (ImportName)
2753 return StringRef(ImportName);
2754 return StringRef();
2755}
2756
2757uint32_t ExportEntry::nodeOffset() const {
2758 return Stack.back().Start - Trie.begin();
2759}
2760
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002761ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002762 : Start(Ptr), Current(Ptr) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002763
2764void ExportEntry::pushNode(uint64_t offset) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002765 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002766 const uint8_t *Ptr = Trie.begin() + offset;
2767 NodeState State(Ptr);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002768 const char *error;
2769 uint64_t ExportInfoSize = readULEB128(State.Current, &error);
2770 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002771 *E = malformedError("export info size " + Twine(error) +
2772 " in export trie data at node: 0x" +
2773 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002774 moveToEnd();
2775 return;
2776 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002777 State.IsExportNode = (ExportInfoSize != 0);
2778 const uint8_t* Children = State.Current + ExportInfoSize;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002779 if (Children > Trie.end()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002780 *E = malformedError(
2781 "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
2782 " in export trie data at node: 0x" + Twine::utohexstr(offset) +
2783 " too big and extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002784 moveToEnd();
2785 return;
2786 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002787 if (State.IsExportNode) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002788 const uint8_t *ExportStart = State.Current;
2789 State.Flags = readULEB128(State.Current, &error);
2790 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002791 *E = malformedError("flags " + Twine(error) +
2792 " in export trie data at node: 0x" +
2793 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002794 moveToEnd();
2795 return;
2796 }
2797 uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
2798 if (State.Flags != 0 &&
2799 (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
2800 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
2801 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002802 *E = malformedError(
2803 "unsupported exported symbol kind: " + Twine((int)Kind) +
2804 " in flags: 0x" + Twine::utohexstr(State.Flags) +
2805 " in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002806 moveToEnd();
2807 return;
2808 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002809 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2810 State.Address = 0;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002811 State.Other = readULEB128(State.Current, &error); // dylib ordinal
2812 if (error) {
2813 *E = malformedError("dylib ordinal of re-export " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002814 " in export trie data at node: 0x" +
2815 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002816 moveToEnd();
2817 return;
2818 }
2819 if (O != nullptr) {
2820 if (State.Other > O->getLibraryCount()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002821 *E = malformedError(
2822 "bad library ordinal: " + Twine((int)State.Other) + " (max " +
2823 Twine((int)O->getLibraryCount()) +
2824 ") in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002825 moveToEnd();
2826 return;
2827 }
2828 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002829 State.ImportName = reinterpret_cast<const char*>(State.Current);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002830 if (*State.ImportName == '\0') {
2831 State.Current++;
2832 } else {
2833 const uint8_t *End = State.Current + 1;
2834 if (End >= Trie.end()) {
2835 *E = malformedError("import name of re-export in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002836 "node: 0x" +
2837 Twine::utohexstr(offset) +
2838 " starts past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002839 moveToEnd();
2840 return;
2841 }
2842 while(*End != '\0' && End < Trie.end())
2843 End++;
2844 if (*End != '\0') {
2845 *E = malformedError("import name of re-export in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002846 "node: 0x" +
2847 Twine::utohexstr(offset) +
2848 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002849 moveToEnd();
2850 return;
2851 }
2852 State.Current = End + 1;
2853 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002854 } else {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002855 State.Address = readULEB128(State.Current, &error);
2856 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002857 *E = malformedError("address " + Twine(error) +
2858 " in export trie data at node: 0x" +
2859 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002860 moveToEnd();
2861 return;
2862 }
2863 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
2864 State.Other = readULEB128(State.Current, &error);
2865 if (error) {
2866 *E = malformedError("resolver of stub and resolver " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002867 " in export trie data at node: 0x" +
2868 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002869 moveToEnd();
2870 return;
2871 }
2872 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002873 }
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002874 if(ExportStart + ExportInfoSize != State.Current) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002875 *E = malformedError(
2876 "inconsistant export info size: 0x" +
2877 Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
2878 Twine::utohexstr(State.Current - ExportStart) +
2879 " in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002880 moveToEnd();
2881 return;
2882 }
2883 }
Kevin Enderby8100cde2017-07-24 20:33:41 +00002884 State.ChildCount = *Children;
2885 if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002886 *E = malformedError("byte for count of childern in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002887 "node: 0x" +
2888 Twine::utohexstr(offset) +
2889 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002890 moveToEnd();
2891 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002892 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002893 State.Current = Children + 1;
2894 State.NextChildIndex = 0;
2895 State.ParentStringLength = CumulativeString.size();
2896 Stack.push_back(State);
2897}
2898
2899void ExportEntry::pushDownUntilBottom() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002900 ErrorAsOutParameter ErrAsOutParam(E);
2901 const char *error;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002902 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2903 NodeState &Top = Stack.back();
2904 CumulativeString.resize(Top.ParentStringLength);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002905 for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002906 char C = *Top.Current;
2907 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002908 }
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002909 if (Top.Current >= Trie.end()) {
2910 *E = malformedError("edge sub-string in export trie data at node: 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002911 Twine::utohexstr(Top.Start - Trie.begin()) +
2912 " for child #" + Twine((int)Top.NextChildIndex) +
2913 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002914 moveToEnd();
2915 return;
2916 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002917 Top.Current += 1;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002918 uint64_t childNodeIndex = readULEB128(Top.Current, &error);
2919 if (error) {
2920 *E = malformedError("child node offset " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002921 " in export trie data at node: 0x" +
2922 Twine::utohexstr(Top.Start - Trie.begin()));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002923 moveToEnd();
2924 return;
2925 }
2926 for (const NodeState &node : nodes()) {
2927 if (node.Start == Trie.begin() + childNodeIndex){
2928 *E = malformedError("loop in childern in export trie data at node: 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002929 Twine::utohexstr(Top.Start - Trie.begin()) +
2930 " back to node: 0x" +
2931 Twine::utohexstr(childNodeIndex));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002932 moveToEnd();
2933 return;
2934 }
2935 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002936 Top.NextChildIndex += 1;
2937 pushNode(childNodeIndex);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002938 if (*E)
2939 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002940 }
2941 if (!Stack.back().IsExportNode) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002942 *E = malformedError("node is not an export node in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002943 "node: 0x" +
2944 Twine::utohexstr(Stack.back().Start - Trie.begin()));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002945 moveToEnd();
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002946 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002947 }
2948}
2949
2950// We have a trie data structure and need a way to walk it that is compatible
2951// with the C++ iterator model. The solution is a non-recursive depth first
2952// traversal where the iterator contains a stack of parent nodes along with a
2953// string that is the accumulation of all edge strings along the parent chain
2954// to this point.
2955//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00002956// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00002957// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002958// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002959//
2960// The algorithm for moveNext() is to keep moving down the leftmost unvisited
2961// child until hitting a node with no children (which is an export node or
2962// else the trie is malformed). On the way down, each node is pushed on the
2963// stack ivar. If there is no more ways down, it pops up one and tries to go
2964// down a sibling path until a childless node is reached.
2965void ExportEntry::moveNext() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002966 assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
2967 if (!Stack.back().IsExportNode) {
2968 *E = malformedError("node is not an export node in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002969 "node: 0x" +
2970 Twine::utohexstr(Stack.back().Start - Trie.begin()));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002971 moveToEnd();
2972 return;
2973 }
2974
2975 Stack.pop_back();
2976 while (!Stack.empty()) {
2977 NodeState &Top = Stack.back();
2978 if (Top.NextChildIndex < Top.ChildCount) {
2979 pushDownUntilBottom();
2980 // Now at the next export node.
2981 return;
2982 } else {
2983 if (Top.IsExportNode) {
2984 // This node has no children but is itself an export node.
2985 CumulativeString.resize(Top.ParentStringLength);
2986 return;
2987 }
2988 Stack.pop_back();
2989 }
2990 }
2991 Done = true;
2992}
2993
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002994iterator_range<export_iterator>
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002995MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
2996 const MachOObjectFile *O) {
2997 ExportEntry Start(&E, O, Trie);
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002998 if (Trie.empty())
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00002999 Start.moveToEnd();
3000 else
3001 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00003002
Kevin Enderby3e95bd22017-07-20 23:08:41 +00003003 ExportEntry Finish(&E, O, Trie);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003004 Finish.moveToEnd();
3005
Craig Topper15576e12015-12-06 05:08:07 +00003006 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00003007}
3008
Alexander Shaposhnikove5740342017-07-29 00:30:45 +00003009iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
3010 return exports(Err, getDyldInfoExportsTrie(), this);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003011}
3012
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003013MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
3014 ArrayRef<uint8_t> Bytes, bool is64Bit)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003015 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3016 PointerSize(is64Bit ? 8 : 4) {}
Nick Kledzikac431442014-09-12 21:34:15 +00003017
3018void MachORebaseEntry::moveToFirst() {
3019 Ptr = Opcodes.begin();
3020 moveNext();
3021}
3022
3023void MachORebaseEntry::moveToEnd() {
3024 Ptr = Opcodes.end();
3025 RemainingLoopCount = 0;
3026 Done = true;
3027}
3028
3029void MachORebaseEntry::moveNext() {
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003030 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikac431442014-09-12 21:34:15 +00003031 // If in the middle of some loop, move to next rebasing in loop.
3032 SegmentOffset += AdvanceAmount;
3033 if (RemainingLoopCount) {
3034 --RemainingLoopCount;
3035 return;
3036 }
Juergen Ributzkacad12492017-03-30 19:56:50 +00003037 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3038 // pointer size. Therefore it is possible to reach the end without ever having
3039 // seen REBASE_OPCODE_DONE.
3040 if (Ptr == Opcodes.end()) {
Nick Kledzikac431442014-09-12 21:34:15 +00003041 Done = true;
3042 return;
3043 }
3044 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003045 while (More) {
Nick Kledzikac431442014-09-12 21:34:15 +00003046 // Parse next opcode and set up next loop.
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003047 const uint8_t *OpcodeStart = Ptr;
Nick Kledzikac431442014-09-12 21:34:15 +00003048 uint8_t Byte = *Ptr++;
3049 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
3050 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003051 uint32_t Count, Skip;
3052 const char *error = nullptr;
Nick Kledzikac431442014-09-12 21:34:15 +00003053 switch (Opcode) {
3054 case MachO::REBASE_OPCODE_DONE:
3055 More = false;
3056 Done = true;
3057 moveToEnd();
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003058 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003059 break;
3060 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
3061 RebaseType = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003062 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003063 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3064 Twine((int)RebaseType) + " for opcode at: 0x" +
3065 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3066 moveToEnd();
3067 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003068 }
Nick Kledzikac431442014-09-12 21:34:15 +00003069 DEBUG_WITH_TYPE(
3070 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003071 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3072 << "RebaseType=" << (int) RebaseType << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003073 break;
3074 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3075 SegmentIndex = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003076 SegmentOffset = readULEB128(&error);
3077 if (error) {
3078 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003079 Twine(error) + " for opcode at: 0x" +
3080 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003081 moveToEnd();
3082 return;
3083 }
3084 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3085 true);
3086 if (error) {
3087 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003088 Twine(error) + " for opcode at: 0x" +
3089 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003090 moveToEnd();
3091 return;
3092 }
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_SET_SEGMENT_AND_OFFSET_ULEB: "
3096 << "SegmentIndex=" << SegmentIndex << ", "
3097 << format("SegmentOffset=0x%06X", SegmentOffset)
3098 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003099 break;
3100 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003101 SegmentOffset += readULEB128(&error);
3102 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003103 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3104 " for opcode at: 0x" +
3105 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003106 moveToEnd();
3107 return;
3108 }
3109 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3110 true);
3111 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003112 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3113 " for opcode at: 0x" +
3114 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003115 moveToEnd();
3116 return;
3117 }
Nick Kledzikac431442014-09-12 21:34:15 +00003118 DEBUG_WITH_TYPE("mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003119 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3120 << format("SegmentOffset=0x%06X",
3121 SegmentOffset) << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003122 break;
3123 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003124 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3125 true);
3126 if (error) {
3127 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003128 Twine(error) + " for opcode at: 0x" +
3129 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003130 moveToEnd();
3131 return;
3132 }
Nick Kledzikac431442014-09-12 21:34:15 +00003133 SegmentOffset += ImmValue * PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003134 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3135 false);
3136 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003137 *E =
3138 malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3139 " (after adding immediate times the pointer size) " +
3140 Twine(error) + " for opcode at: 0x" +
3141 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003142 moveToEnd();
3143 return;
3144 }
Nick Kledzikac431442014-09-12 21:34:15 +00003145 DEBUG_WITH_TYPE("mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003146 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3147 << format("SegmentOffset=0x%06X",
3148 SegmentOffset) << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003149 break;
3150 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003151 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3152 true);
3153 if (error) {
3154 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
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 }
Nick Kledzikac431442014-09-12 21:34:15 +00003160 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003161 Skip = 0;
3162 Count = ImmValue;
3163 if (ImmValue != 0)
3164 RemainingLoopCount = ImmValue - 1;
3165 else
3166 RemainingLoopCount = 0;
3167 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3168 SegmentIndex, SegmentOffset);
3169 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003170 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3171 Twine(error) + " for opcode at: 0x" +
3172 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003173 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003174 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003175 }
Nick Kledzikac431442014-09-12 21:34:15 +00003176 DEBUG_WITH_TYPE(
3177 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003178 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3179 << format("SegmentOffset=0x%06X", SegmentOffset)
3180 << ", AdvanceAmount=" << AdvanceAmount
3181 << ", RemainingLoopCount=" << RemainingLoopCount
3182 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003183 return;
3184 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003185 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3186 true);
3187 if (error) {
3188 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003189 Twine(error) + " for opcode at: 0x" +
3190 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003191 moveToEnd();
3192 return;
3193 }
Nick Kledzikac431442014-09-12 21:34:15 +00003194 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003195 Skip = 0;
3196 Count = readULEB128(&error);
3197 if (error) {
3198 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003199 Twine(error) + " for opcode at: 0x" +
3200 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003201 moveToEnd();
3202 return;
3203 }
3204 if (Count != 0)
3205 RemainingLoopCount = Count - 1;
3206 else
3207 RemainingLoopCount = 0;
3208 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3209 SegmentIndex, SegmentOffset);
3210 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003211 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3212 Twine(error) + " for opcode at: 0x" +
3213 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003214 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003215 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003216 }
Nick Kledzikac431442014-09-12 21:34:15 +00003217 DEBUG_WITH_TYPE(
3218 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003219 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3220 << format("SegmentOffset=0x%06X", SegmentOffset)
3221 << ", AdvanceAmount=" << AdvanceAmount
3222 << ", RemainingLoopCount=" << RemainingLoopCount
3223 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003224 return;
3225 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003226 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3227 true);
3228 if (error) {
3229 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003230 Twine(error) + " for opcode at: 0x" +
3231 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003232 moveToEnd();
3233 return;
3234 }
3235 Skip = readULEB128(&error);
3236 if (error) {
3237 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003238 Twine(error) + " for opcode at: 0x" +
3239 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003240 moveToEnd();
3241 return;
3242 }
3243 AdvanceAmount = Skip + PointerSize;
3244 Count = 1;
Nick Kledzikac431442014-09-12 21:34:15 +00003245 RemainingLoopCount = 0;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003246 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3247 SegmentIndex, SegmentOffset);
3248 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003249 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3250 Twine(error) + " for opcode at: 0x" +
3251 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003252 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003253 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003254 }
Nick Kledzikac431442014-09-12 21:34:15 +00003255 DEBUG_WITH_TYPE(
3256 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003257 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3258 << format("SegmentOffset=0x%06X", SegmentOffset)
3259 << ", AdvanceAmount=" << AdvanceAmount
3260 << ", RemainingLoopCount=" << RemainingLoopCount
3261 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003262 return;
3263 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003264 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3265 true);
3266 if (error) {
3267 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003268 "ULEB " +
3269 Twine(error) + " for opcode at: 0x" +
3270 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003271 moveToEnd();
3272 return;
3273 }
3274 Count = readULEB128(&error);
3275 if (error) {
3276 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003277 "ULEB " +
3278 Twine(error) + " for opcode at: 0x" +
3279 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003280 moveToEnd();
3281 return;
3282 }
3283 if (Count != 0)
3284 RemainingLoopCount = Count - 1;
3285 else
3286 RemainingLoopCount = 0;
3287 Skip = readULEB128(&error);
3288 if (error) {
3289 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003290 "ULEB " +
3291 Twine(error) + " for opcode at: 0x" +
3292 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003293 moveToEnd();
3294 return;
3295 }
3296 AdvanceAmount = Skip + PointerSize;
3297
3298 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3299 SegmentIndex, SegmentOffset);
3300 if (error) {
3301 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003302 "ULEB " +
3303 Twine(error) + " for opcode at: 0x" +
3304 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003305 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003306 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003307 }
Nick Kledzikac431442014-09-12 21:34:15 +00003308 DEBUG_WITH_TYPE(
3309 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003310 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3311 << format("SegmentOffset=0x%06X", SegmentOffset)
3312 << ", AdvanceAmount=" << AdvanceAmount
3313 << ", RemainingLoopCount=" << RemainingLoopCount
3314 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003315 return;
3316 default:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003317 *E = malformedError("bad rebase info (bad opcode value 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003318 Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3319 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003320 moveToEnd();
3321 return;
Nick Kledzikac431442014-09-12 21:34:15 +00003322 }
3323 }
3324}
3325
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003326uint64_t MachORebaseEntry::readULEB128(const char **error) {
Nick Kledzikac431442014-09-12 21:34:15 +00003327 unsigned Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003328 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzikac431442014-09-12 21:34:15 +00003329 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003330 if (Ptr > Opcodes.end())
Nick Kledzikac431442014-09-12 21:34:15 +00003331 Ptr = Opcodes.end();
Nick Kledzikac431442014-09-12 21:34:15 +00003332 return Result;
3333}
3334
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003335int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzikac431442014-09-12 21:34:15 +00003336
3337uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3338
3339StringRef MachORebaseEntry::typeName() const {
3340 switch (RebaseType) {
3341 case MachO::REBASE_TYPE_POINTER:
3342 return "pointer";
3343 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3344 return "text abs32";
3345 case MachO::REBASE_TYPE_TEXT_PCREL32:
3346 return "text rel32";
3347 }
3348 return "unknown";
3349}
3350
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003351// For use with the SegIndex of a checked Mach-O Rebase entry
3352// to get the segment name.
3353StringRef MachORebaseEntry::segmentName() const {
3354 return O->BindRebaseSegmentName(SegmentIndex);
3355}
3356
3357// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3358// to get the section name.
3359StringRef MachORebaseEntry::sectionName() const {
3360 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3361}
3362
3363// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3364// to get the address.
3365uint64_t MachORebaseEntry::address() const {
3366 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3367}
3368
Nick Kledzikac431442014-09-12 21:34:15 +00003369bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003370#ifdef EXPENSIVE_CHECKS
Nick Kledzikac431442014-09-12 21:34:15 +00003371 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003372#else
3373 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3374#endif
Nick Kledzikac431442014-09-12 21:34:15 +00003375 return (Ptr == Other.Ptr) &&
3376 (RemainingLoopCount == Other.RemainingLoopCount) &&
3377 (Done == Other.Done);
3378}
3379
3380iterator_range<rebase_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003381MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3382 ArrayRef<uint8_t> Opcodes, bool is64) {
3383 if (O->BindRebaseSectionTable == nullptr)
3384 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3385 MachORebaseEntry Start(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003386 Start.moveToFirst();
3387
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003388 MachORebaseEntry Finish(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003389 Finish.moveToEnd();
3390
Craig Topper15576e12015-12-06 05:08:07 +00003391 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00003392}
3393
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003394iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3395 return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
Nick Kledzikac431442014-09-12 21:34:15 +00003396}
3397
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003398MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3399 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003400 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3401 PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
Nick Kledzik56ebef42014-09-16 01:41:51 +00003402
3403void MachOBindEntry::moveToFirst() {
3404 Ptr = Opcodes.begin();
3405 moveNext();
3406}
3407
3408void MachOBindEntry::moveToEnd() {
3409 Ptr = Opcodes.end();
3410 RemainingLoopCount = 0;
3411 Done = true;
3412}
3413
3414void MachOBindEntry::moveNext() {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003415 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003416 // If in the middle of some loop, move to next binding in loop.
3417 SegmentOffset += AdvanceAmount;
3418 if (RemainingLoopCount) {
3419 --RemainingLoopCount;
3420 return;
3421 }
Juergen Ributzkacad12492017-03-30 19:56:50 +00003422 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3423 // pointer size. Therefore it is possible to reach the end without ever having
3424 // seen BIND_OPCODE_DONE.
3425 if (Ptr == Opcodes.end()) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003426 Done = true;
3427 return;
3428 }
3429 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003430 while (More) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003431 // Parse next opcode and set up next loop.
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003432 const uint8_t *OpcodeStart = Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003433 uint8_t Byte = *Ptr++;
3434 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3435 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3436 int8_t SignExtended;
3437 const uint8_t *SymStart;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003438 uint32_t Count, Skip;
3439 const char *error = nullptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003440 switch (Opcode) {
3441 case MachO::BIND_OPCODE_DONE:
3442 if (TableKind == Kind::Lazy) {
3443 // Lazying bindings have a DONE opcode between entries. Need to ignore
3444 // it to advance to next entry. But need not if this is last entry.
3445 bool NotLastEntry = false;
3446 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3447 if (*P) {
3448 NotLastEntry = true;
3449 }
3450 }
3451 if (NotLastEntry)
3452 break;
3453 }
3454 More = false;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003455 moveToEnd();
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003456 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003457 break;
3458 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003459 if (TableKind == Kind::Weak) {
3460 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003461 "weak bind table for opcode at: 0x" +
3462 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003463 moveToEnd();
3464 return;
3465 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003466 Ordinal = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003467 LibraryOrdinalSet = true;
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003468 if (ImmValue > O->getLibraryCount()) {
3469 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003470 "library ordinal: " +
3471 Twine((int)ImmValue) + " (max " +
3472 Twine((int)O->getLibraryCount()) +
3473 ") for opcode at: 0x" +
3474 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003475 moveToEnd();
3476 return;
3477 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003478 DEBUG_WITH_TYPE(
3479 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003480 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3481 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003482 break;
3483 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003484 if (TableKind == Kind::Weak) {
3485 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003486 "weak bind table for opcode at: 0x" +
3487 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003488 moveToEnd();
3489 return;
3490 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003491 Ordinal = readULEB128(&error);
3492 LibraryOrdinalSet = true;
3493 if (error) {
3494 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003495 Twine(error) + " for opcode at: 0x" +
3496 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003497 moveToEnd();
3498 return;
3499 }
3500 if (Ordinal > (int)O->getLibraryCount()) {
3501 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003502 "library ordinal: " +
3503 Twine((int)Ordinal) + " (max " +
3504 Twine((int)O->getLibraryCount()) +
3505 ") for opcode at: 0x" +
3506 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003507 moveToEnd();
3508 return;
3509 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003510 DEBUG_WITH_TYPE(
3511 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003512 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3513 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003514 break;
3515 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003516 if (TableKind == Kind::Weak) {
3517 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003518 "weak bind table for opcode at: 0x" +
3519 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003520 moveToEnd();
3521 return;
3522 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003523 if (ImmValue) {
3524 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3525 Ordinal = SignExtended;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003526 if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3527 *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003528 "special ordinal: " +
3529 Twine((int)Ordinal) + " for opcode at: 0x" +
3530 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003531 moveToEnd();
3532 return;
3533 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003534 } else
3535 Ordinal = 0;
Steven Wu97e2cf82017-05-31 22:17:43 +00003536 LibraryOrdinalSet = true;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003537 DEBUG_WITH_TYPE(
3538 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003539 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3540 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003541 break;
3542 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3543 Flags = ImmValue;
3544 SymStart = Ptr;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003545 while (*Ptr && (Ptr < Opcodes.end())) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003546 ++Ptr;
3547 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003548 if (Ptr == Opcodes.end()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003549 *E = malformedError(
3550 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3551 "symbol name extends past opcodes for opcode at: 0x" +
3552 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3553 moveToEnd();
3554 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003555 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003556 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3557 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00003558 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003559 DEBUG_WITH_TYPE(
3560 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003561 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3562 << "SymbolName=" << SymbolName << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003563 if (TableKind == Kind::Weak) {
3564 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3565 return;
3566 }
3567 break;
3568 case MachO::BIND_OPCODE_SET_TYPE_IMM:
3569 BindType = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003570 if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003571 *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3572 Twine((int)ImmValue) + " for opcode at: 0x" +
3573 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3574 moveToEnd();
3575 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003576 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003577 DEBUG_WITH_TYPE(
3578 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003579 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3580 << "BindType=" << (int)BindType << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003581 break;
3582 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003583 Addend = readSLEB128(&error);
3584 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003585 *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
3586 " for opcode at: 0x" +
3587 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003588 moveToEnd();
3589 return;
3590 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003591 DEBUG_WITH_TYPE(
3592 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003593 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3594 << "Addend=" << Addend << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003595 break;
3596 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3597 SegmentIndex = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003598 SegmentOffset = readULEB128(&error);
3599 if (error) {
3600 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003601 Twine(error) + " for opcode at: 0x" +
3602 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003603 moveToEnd();
3604 return;
3605 }
3606 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3607 if (error) {
3608 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003609 Twine(error) + " for opcode at: 0x" +
3610 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003611 moveToEnd();
3612 return;
3613 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003614 DEBUG_WITH_TYPE(
3615 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003616 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3617 << "SegmentIndex=" << SegmentIndex << ", "
3618 << format("SegmentOffset=0x%06X", SegmentOffset)
3619 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003620 break;
3621 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003622 SegmentOffset += readULEB128(&error);
3623 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003624 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3625 " for opcode at: 0x" +
3626 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003627 moveToEnd();
3628 return;
3629 }
3630 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3631 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003632 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3633 " for opcode at: 0x" +
3634 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003635 moveToEnd();
3636 return;
3637 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003638 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003639 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3640 << format("SegmentOffset=0x%06X",
3641 SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003642 break;
3643 case MachO::BIND_OPCODE_DO_BIND:
3644 AdvanceAmount = PointerSize;
3645 RemainingLoopCount = 0;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003646 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3647 if (error) {
3648 *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003649 " for opcode at: 0x" +
3650 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003651 moveToEnd();
3652 return;
3653 }
3654 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003655 *E = malformedError(
3656 "for BIND_OPCODE_DO_BIND missing preceding "
3657 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3658 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003659 moveToEnd();
3660 return;
3661 }
3662 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003663 *E =
3664 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3665 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3666 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003667 moveToEnd();
3668 return;
3669 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003670 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003671 dbgs() << "BIND_OPCODE_DO_BIND: "
3672 << format("SegmentOffset=0x%06X",
3673 SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003674 return;
3675 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003676 if (TableKind == Kind::Lazy) {
3677 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003678 "lazy bind table for opcode at: 0x" +
3679 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003680 moveToEnd();
3681 return;
3682 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003683 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3684 if (error) {
3685 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003686 Twine(error) + " for opcode at: 0x" +
3687 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003688 moveToEnd();
3689 return;
3690 }
3691 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003692 *E = malformedError(
3693 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3694 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3695 "at: 0x" +
3696 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003697 moveToEnd();
3698 return;
3699 }
3700 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003701 *E = malformedError(
3702 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3703 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3704 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003705 moveToEnd();
3706 return;
3707 }
3708 AdvanceAmount = readULEB128(&error) + PointerSize;
3709 if (error) {
3710 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003711 Twine(error) + " for opcode at: 0x" +
3712 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003713 moveToEnd();
3714 return;
3715 }
3716 // Note, this is not really an error until the next bind but make no sense
3717 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3718 // bind operation.
3719 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3720 AdvanceAmount, false);
3721 if (error) {
3722 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003723 "ULEB) " +
3724 Twine(error) + " for opcode at: 0x" +
3725 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003726 moveToEnd();
3727 return;
3728 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003729 RemainingLoopCount = 0;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003730 DEBUG_WITH_TYPE(
3731 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003732 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3733 << format("SegmentOffset=0x%06X", SegmentOffset)
3734 << ", AdvanceAmount=" << AdvanceAmount
3735 << ", RemainingLoopCount=" << RemainingLoopCount
3736 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003737 return;
3738 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003739 if (TableKind == Kind::Lazy) {
3740 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003741 "allowed in lazy bind table for opcode at: 0x" +
3742 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003743 moveToEnd();
3744 return;
3745 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003746 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3747 if (error) {
3748 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003749 Twine(error) + " for opcode at: 0x" +
3750 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003751 moveToEnd();
3752 return;
3753 }
3754 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003755 *E = malformedError(
3756 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3757 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3758 "opcode at: 0x" +
3759 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003760 moveToEnd();
3761 return;
3762 }
3763 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003764 *E = malformedError(
3765 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3766 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3767 "at: 0x" +
3768 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003769 moveToEnd();
3770 return;
3771 }
Nick Kledzik3b2aa052014-10-18 01:21:02 +00003772 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003773 RemainingLoopCount = 0;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003774 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3775 AdvanceAmount, false);
3776 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003777 *E =
3778 malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3779 " (after adding immediate times the pointer size) " +
3780 Twine(error) + " for opcode at: 0x" +
3781 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003782 moveToEnd();
3783 return;
3784 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003785 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003786 dbgs()
Nick Kledzik56ebef42014-09-16 01:41:51 +00003787 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003788 << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003789 return;
3790 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003791 if (TableKind == Kind::Lazy) {
3792 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003793 "allowed in lazy bind table for opcode at: 0x" +
3794 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003795 moveToEnd();
3796 return;
3797 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003798 Count = readULEB128(&error);
3799 if (Count != 0)
3800 RemainingLoopCount = Count - 1;
3801 else
3802 RemainingLoopCount = 0;
3803 if (error) {
3804 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003805 " (count value) " +
3806 Twine(error) + " for opcode at: 0x" +
3807 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003808 moveToEnd();
3809 return;
3810 }
3811 Skip = readULEB128(&error);
3812 AdvanceAmount = Skip + PointerSize;
3813 if (error) {
3814 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003815 " (skip value) " +
3816 Twine(error) + " for opcode at: 0x" +
3817 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003818 moveToEnd();
3819 return;
3820 }
3821 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3822 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003823 *E =
3824 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3825 Twine(error) + " for opcode at: 0x" +
3826 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003827 moveToEnd();
3828 return;
3829 }
3830 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003831 *E = malformedError(
3832 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3833 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3834 "opcode at: 0x" +
3835 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003836 moveToEnd();
3837 return;
3838 }
3839 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003840 *E = malformedError(
3841 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3842 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3843 "at: 0x" +
3844 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003845 moveToEnd();
3846 return;
3847 }
3848 error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
3849 SegmentIndex, SegmentOffset);
3850 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003851 *E =
3852 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3853 Twine(error) + " for opcode at: 0x" +
3854 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003855 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003856 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003857 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003858 DEBUG_WITH_TYPE(
3859 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003860 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3861 << format("SegmentOffset=0x%06X", SegmentOffset)
3862 << ", AdvanceAmount=" << AdvanceAmount
3863 << ", RemainingLoopCount=" << RemainingLoopCount
3864 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003865 return;
3866 default:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003867 *E = malformedError("bad bind info (bad opcode value 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003868 Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3869 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003870 moveToEnd();
3871 return;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003872 }
3873 }
3874}
3875
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003876uint64_t MachOBindEntry::readULEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003877 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003878 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003879 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003880 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003881 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003882 return Result;
3883}
3884
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003885int64_t MachOBindEntry::readSLEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003886 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003887 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003888 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003889 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003890 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003891 return Result;
3892}
3893
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003894int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003895
3896uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3897
3898StringRef MachOBindEntry::typeName() const {
3899 switch (BindType) {
3900 case MachO::BIND_TYPE_POINTER:
3901 return "pointer";
3902 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3903 return "text abs32";
3904 case MachO::BIND_TYPE_TEXT_PCREL32:
3905 return "text rel32";
3906 }
3907 return "unknown";
3908}
3909
3910StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3911
3912int64_t MachOBindEntry::addend() const { return Addend; }
3913
3914uint32_t MachOBindEntry::flags() const { return Flags; }
3915
3916int MachOBindEntry::ordinal() const { return Ordinal; }
3917
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003918// For use with the SegIndex of a checked Mach-O Bind entry
3919// to get the segment name.
3920StringRef MachOBindEntry::segmentName() const {
3921 return O->BindRebaseSegmentName(SegmentIndex);
3922}
3923
3924// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3925// to get the section name.
3926StringRef MachOBindEntry::sectionName() const {
3927 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3928}
3929
3930// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3931// to get the address.
3932uint64_t MachOBindEntry::address() const {
3933 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3934}
3935
Nick Kledzik56ebef42014-09-16 01:41:51 +00003936bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003937#ifdef EXPENSIVE_CHECKS
Nick Kledzik56ebef42014-09-16 01:41:51 +00003938 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003939#else
3940 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3941#endif
Nick Kledzik56ebef42014-09-16 01:41:51 +00003942 return (Ptr == Other.Ptr) &&
3943 (RemainingLoopCount == Other.RemainingLoopCount) &&
3944 (Done == Other.Done);
3945}
3946
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003947// Build table of sections so SegIndex/SegOffset pairs can be translated.
3948BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
3949 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
3950 StringRef CurSegName;
3951 uint64_t CurSegAddress;
3952 for (const SectionRef &Section : Obj->sections()) {
3953 SectionInfo Info;
3954 Section.getName(Info.SectionName);
3955 Info.Address = Section.getAddress();
3956 Info.Size = Section.getSize();
3957 Info.SegmentName =
3958 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
3959 if (!Info.SegmentName.equals(CurSegName)) {
3960 ++CurSegIndex;
3961 CurSegName = Info.SegmentName;
3962 CurSegAddress = Info.Address;
3963 }
3964 Info.SegmentIndex = CurSegIndex - 1;
3965 Info.OffsetInSegment = Info.Address - CurSegAddress;
3966 Info.SegmentStartAddress = CurSegAddress;
3967 Sections.push_back(Info);
3968 }
3969 MaxSegIndex = CurSegIndex;
3970}
3971
3972// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003973// validate a MachOBindEntry or MachORebaseEntry.
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003974const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
3975 uint64_t SegOffset,
3976 bool endInvalid) {
3977 if (SegIndex == -1)
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003978 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003979 if (SegIndex >= MaxSegIndex)
3980 return "bad segIndex (too large)";
3981 for (const SectionInfo &SI : Sections) {
3982 if (SI.SegmentIndex != SegIndex)
3983 continue;
3984 if (SI.OffsetInSegment > SegOffset)
3985 continue;
3986 if (SegOffset > (SI.OffsetInSegment + SI.Size))
3987 continue;
3988 if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
3989 continue;
3990 return nullptr;
3991 }
3992 return "bad segOffset, too large";
3993}
3994
3995// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003996// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
3997// MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
3998// REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
3999// been already checked.
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004000const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
4001 uint8_t PointerSize,
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00004002 int32_t SegIndex,
4003 uint64_t SegOffset) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004004 const SectionInfo &SI = findSection(SegIndex, SegOffset);
4005 uint64_t addr = SI.SegmentStartAddress + SegOffset;
4006 if (addr >= SI.Address + SI.Size)
4007 return "bad segOffset, too large";
4008 uint64_t i = 0;
4009 if (Count > 1)
4010 i = (Skip + PointerSize) * (Count - 1);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00004011 else if (Count == 1)
4012 i = Skip + PointerSize;
4013 if (addr + i >= SI.Address + SI.Size) {
4014 // For rebase opcodes they can step from one section to another.
4015 uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
4016 const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
4017 if (error)
4018 return "bad count and skip, too large";
4019 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004020 return nullptr;
4021}
4022
4023// For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4024// to get the segment name.
4025StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
4026 for (const SectionInfo &SI : Sections) {
4027 if (SI.SegmentIndex == SegIndex)
4028 return SI.SegmentName;
4029 }
4030 llvm_unreachable("invalid SegIndex");
4031}
4032
4033// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4034// to get the SectionInfo.
4035const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
4036 int32_t SegIndex, uint64_t SegOffset) {
4037 for (const SectionInfo &SI : Sections) {
4038 if (SI.SegmentIndex != SegIndex)
4039 continue;
4040 if (SI.OffsetInSegment > SegOffset)
4041 continue;
4042 if (SegOffset >= (SI.OffsetInSegment + SI.Size))
4043 continue;
4044 return SI;
4045 }
4046 llvm_unreachable("SegIndex and SegOffset not in any section");
4047}
4048
4049// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4050// entry to get the section name.
4051StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
4052 uint64_t SegOffset) {
4053 return findSection(SegIndex, SegOffset).SectionName;
4054}
4055
4056// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4057// entry to get the address.
4058uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
4059 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
4060 return SI.SegmentStartAddress + OffsetInSeg;
4061}
4062
Nick Kledzik56ebef42014-09-16 01:41:51 +00004063iterator_range<bind_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004064MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004065 ArrayRef<uint8_t> Opcodes, bool is64,
Nick Kledzik56ebef42014-09-16 01:41:51 +00004066 MachOBindEntry::Kind BKind) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004067 if (O->BindRebaseSectionTable == nullptr)
4068 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004069 MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00004070 Start.moveToFirst();
4071
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004072 MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00004073 Finish.moveToEnd();
4074
Craig Topper15576e12015-12-06 05:08:07 +00004075 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00004076}
4077
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004078iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004079 return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004080 MachOBindEntry::Kind::Regular);
4081}
4082
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004083iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004084 return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004085 MachOBindEntry::Kind::Lazy);
4086}
4087
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004088iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004089 return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004090 MachOBindEntry::Kind::Weak);
4091}
4092
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00004093MachOObjectFile::load_command_iterator
4094MachOObjectFile::begin_load_commands() const {
4095 return LoadCommands.begin();
4096}
4097
4098MachOObjectFile::load_command_iterator
4099MachOObjectFile::end_load_commands() const {
4100 return LoadCommands.end();
4101}
4102
4103iterator_range<MachOObjectFile::load_command_iterator>
4104MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00004105 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00004106}
4107
Rafael Espindola56f976f2013-04-18 18:08:55 +00004108StringRef
4109MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
4110 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
4111 return parseSegmentOrSectionName(Raw.data());
4112}
4113
4114ArrayRef<char>
4115MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00004116 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00004117 const section_base *Base =
4118 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00004119 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004120}
4121
4122ArrayRef<char>
4123MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00004124 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00004125 const section_base *Base =
4126 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00004127 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004128}
4129
4130bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00004131MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00004132 const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004133 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00004134 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00004135 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004136}
4137
Eric Christopher1d62c252013-07-22 22:25:07 +00004138unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004139 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004140 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00004141 return RE.r_word1 & 0xffffff;
4142 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004143}
4144
Eric Christopher1d62c252013-07-22 22:25:07 +00004145bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004146 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004147 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00004148 return (RE.r_word1 >> 27) & 1;
4149 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004150}
4151
Eric Christopher1d62c252013-07-22 22:25:07 +00004152bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004153 const MachO::any_relocation_info &RE) const {
4154 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004155}
4156
Eric Christopher1d62c252013-07-22 22:25:07 +00004157uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004158 const MachO::any_relocation_info &RE) const {
4159 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004160}
4161
Kevin Enderby9907d0a2014-11-04 00:43:16 +00004162uint32_t MachOObjectFile::getScatteredRelocationType(
4163 const MachO::any_relocation_info &RE) const {
4164 return (RE.r_word0 >> 24) & 0xf;
4165}
4166
Eric Christopher1d62c252013-07-22 22:25:07 +00004167unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004168 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004169 if (isRelocationScattered(RE))
4170 return getScatteredRelocationAddress(RE);
4171 return getPlainRelocationAddress(RE);
4172}
4173
Charles Davis8bdfafd2013-09-01 04:28:48 +00004174unsigned MachOObjectFile::getAnyRelocationPCRel(
4175 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004176 if (isRelocationScattered(RE))
Lang Hames697e7cd2016-12-04 01:56:10 +00004177 return getScatteredRelocationPCRel(RE);
4178 return getPlainRelocationPCRel(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004179}
4180
Eric Christopher1d62c252013-07-22 22:25:07 +00004181unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004182 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004183 if (isRelocationScattered(RE))
4184 return getScatteredRelocationLength(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00004185 return getPlainRelocationLength(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004186}
4187
4188unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00004189MachOObjectFile::getAnyRelocationType(
4190 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004191 if (isRelocationScattered(RE))
4192 return getScatteredRelocationType(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00004193 return getPlainRelocationType(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004194}
4195
Rafael Espindola52501032013-04-30 15:40:54 +00004196SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00004197MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004198 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00004199 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00004200 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00004201 unsigned SecNum = getPlainRelocationSymbolNum(RE);
4202 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
4203 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00004204 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00004205 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00004206 return SectionRef(DRI, this);
4207}
4208
Charles Davis8bdfafd2013-09-01 04:28:48 +00004209MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00004210 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00004211 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004212}
4213
Charles Davis8bdfafd2013-09-01 04:28:48 +00004214MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00004215 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00004216 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004217}
4218
Charles Davis8bdfafd2013-09-01 04:28:48 +00004219MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00004220 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004221 const char *Sec = getSectionPtr(*this, L, Index);
4222 return getStruct<MachO::section>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004223}
4224
Charles Davis8bdfafd2013-09-01 04:28:48 +00004225MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4226 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004227 const char *Sec = getSectionPtr(*this, L, Index);
4228 return getStruct<MachO::section_64>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004229}
4230
Charles Davis8bdfafd2013-09-01 04:28:48 +00004231MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00004232MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00004233 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004234 return getStruct<MachO::nlist>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004235}
4236
Charles Davis8bdfafd2013-09-01 04:28:48 +00004237MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00004238MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00004239 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004240 return getStruct<MachO::nlist_64>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004241}
4242
Charles Davis8bdfafd2013-09-01 04:28:48 +00004243MachO::linkedit_data_command
4244MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004245 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004246}
4247
Charles Davis8bdfafd2013-09-01 04:28:48 +00004248MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00004249MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004250 return getStruct<MachO::segment_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004251}
4252
Charles Davis8bdfafd2013-09-01 04:28:48 +00004253MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00004254MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004255 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004256}
4257
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00004258MachO::linker_option_command
4259MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004260 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004261}
4262
Jim Grosbach448334a2014-03-18 22:09:05 +00004263MachO::version_min_command
4264MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004265 return getStruct<MachO::version_min_command>(*this, L.Ptr);
Jim Grosbach448334a2014-03-18 22:09:05 +00004266}
4267
Kevin Enderbya4579c42017-01-19 17:36:31 +00004268MachO::note_command
4269MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
4270 return getStruct<MachO::note_command>(*this, L.Ptr);
4271}
4272
Steven Wu5b54a422017-01-23 20:07:55 +00004273MachO::build_version_command
4274MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
4275 return getStruct<MachO::build_version_command>(*this, L.Ptr);
4276}
4277
4278MachO::build_tool_version
4279MachOObjectFile::getBuildToolVersion(unsigned index) const {
4280 return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
4281}
4282
Tim Northover8f9590b2014-06-30 14:40:57 +00004283MachO::dylib_command
4284MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004285 return getStruct<MachO::dylib_command>(*this, L.Ptr);
Tim Northover8f9590b2014-06-30 14:40:57 +00004286}
4287
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004288MachO::dyld_info_command
4289MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004290 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004291}
4292
4293MachO::dylinker_command
4294MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004295 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004296}
4297
4298MachO::uuid_command
4299MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004300 return getStruct<MachO::uuid_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004301}
4302
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004303MachO::rpath_command
4304MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004305 return getStruct<MachO::rpath_command>(*this, L.Ptr);
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004306}
4307
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004308MachO::source_version_command
4309MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004310 return getStruct<MachO::source_version_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004311}
4312
4313MachO::entry_point_command
4314MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004315 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004316}
4317
Kevin Enderby0804f4672014-12-16 23:25:52 +00004318MachO::encryption_info_command
4319MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004320 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
Kevin Enderby0804f4672014-12-16 23:25:52 +00004321}
4322
Kevin Enderby57538292014-12-17 01:01:30 +00004323MachO::encryption_info_command_64
4324MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004325 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
Kevin Enderby57538292014-12-17 01:01:30 +00004326}
4327
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004328MachO::sub_framework_command
4329MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004330 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004331}
Tim Northover8f9590b2014-06-30 14:40:57 +00004332
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004333MachO::sub_umbrella_command
4334MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004335 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004336}
4337
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004338MachO::sub_library_command
4339MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004340 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004341}
4342
Kevin Enderby186eac32014-12-19 21:06:24 +00004343MachO::sub_client_command
4344MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004345 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
Kevin Enderby186eac32014-12-19 21:06:24 +00004346}
4347
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004348MachO::routines_command
4349MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004350 return getStruct<MachO::routines_command>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004351}
4352
4353MachO::routines_command_64
4354MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004355 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004356}
4357
Kevin Enderby48ef5342014-12-23 22:56:39 +00004358MachO::thread_command
4359MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004360 return getStruct<MachO::thread_command>(*this, L.Ptr);
Kevin Enderby48ef5342014-12-23 22:56:39 +00004361}
4362
Charles Davis8bdfafd2013-09-01 04:28:48 +00004363MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00004364MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00004365 uint32_t Offset;
Kevin Enderbyabf10f22017-06-22 17:41:22 +00004366 if (getHeader().filetype == MachO::MH_OBJECT) {
4367 DataRefImpl Sec;
4368 Sec.d.a = Rel.d.a;
4369 if (is64Bit()) {
4370 MachO::section_64 Sect = getSection64(Sec);
4371 Offset = Sect.reloff;
4372 } else {
4373 MachO::section Sect = getSection(Sec);
4374 Offset = Sect.reloff;
4375 }
Rafael Espindola128b8112014-04-03 23:51:28 +00004376 } else {
Kevin Enderbyabf10f22017-06-22 17:41:22 +00004377 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
Michael Trenta1703b12017-12-15 17:57:40 +00004378 if (Rel.d.a == 0)
4379 Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
4380 else
4381 Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
Rafael Espindola128b8112014-04-03 23:51:28 +00004382 }
4383
4384 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004385 getPtr(*this, Offset)) + Rel.d.b;
Rafael Espindola128b8112014-04-03 23:51:28 +00004386 return getStruct<MachO::any_relocation_info>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004387 *this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00004388}
4389
Charles Davis8bdfafd2013-09-01 04:28:48 +00004390MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00004391MachOObjectFile::getDice(DataRefImpl Rel) const {
4392 const char *P = reinterpret_cast<const char *>(Rel.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004393 return getStruct<MachO::data_in_code_entry>(*this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00004394}
4395
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004396const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00004397 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004398}
4399
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004400const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4401 assert(is64Bit());
4402 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004403}
4404
Charles Davis8bdfafd2013-09-01 04:28:48 +00004405uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4406 const MachO::dysymtab_command &DLC,
4407 unsigned Index) const {
4408 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
Lang Hames697e7cd2016-12-04 01:56:10 +00004409 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004410}
4411
Charles Davis8bdfafd2013-09-01 04:28:48 +00004412MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00004413MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4414 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004415 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
Lang Hames697e7cd2016-12-04 01:56:10 +00004416 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004417}
4418
Charles Davis8bdfafd2013-09-01 04:28:48 +00004419MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004420 if (SymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004421 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004422
4423 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4424 MachO::symtab_command Cmd;
4425 Cmd.cmd = MachO::LC_SYMTAB;
4426 Cmd.cmdsize = sizeof(MachO::symtab_command);
4427 Cmd.symoff = 0;
4428 Cmd.nsyms = 0;
4429 Cmd.stroff = 0;
4430 Cmd.strsize = 0;
4431 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004432}
4433
Charles Davis8bdfafd2013-09-01 04:28:48 +00004434MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004435 if (DysymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004436 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004437
4438 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4439 MachO::dysymtab_command Cmd;
4440 Cmd.cmd = MachO::LC_DYSYMTAB;
4441 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4442 Cmd.ilocalsym = 0;
4443 Cmd.nlocalsym = 0;
4444 Cmd.iextdefsym = 0;
4445 Cmd.nextdefsym = 0;
4446 Cmd.iundefsym = 0;
4447 Cmd.nundefsym = 0;
4448 Cmd.tocoff = 0;
4449 Cmd.ntoc = 0;
4450 Cmd.modtaboff = 0;
4451 Cmd.nmodtab = 0;
4452 Cmd.extrefsymoff = 0;
4453 Cmd.nextrefsyms = 0;
4454 Cmd.indirectsymoff = 0;
4455 Cmd.nindirectsyms = 0;
4456 Cmd.extreloff = 0;
4457 Cmd.nextrel = 0;
4458 Cmd.locreloff = 0;
4459 Cmd.nlocrel = 0;
4460 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004461}
4462
Charles Davis8bdfafd2013-09-01 04:28:48 +00004463MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00004464MachOObjectFile::getDataInCodeLoadCommand() const {
4465 if (DataInCodeLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004466 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00004467
4468 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00004469 MachO::linkedit_data_command Cmd;
4470 Cmd.cmd = MachO::LC_DATA_IN_CODE;
4471 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4472 Cmd.dataoff = 0;
4473 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00004474 return Cmd;
4475}
4476
Kevin Enderby9a509442015-01-27 21:28:24 +00004477MachO::linkedit_data_command
4478MachOObjectFile::getLinkOptHintsLoadCommand() const {
4479 if (LinkOptHintsLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004480 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
Kevin Enderby9a509442015-01-27 21:28:24 +00004481
4482 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4483 // fields.
4484 MachO::linkedit_data_command Cmd;
4485 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4486 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4487 Cmd.dataoff = 0;
4488 Cmd.datasize = 0;
4489 return Cmd;
4490}
4491
Nick Kledzikd04bc352014-08-30 00:20:14 +00004492ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004493 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004494 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004495
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004496 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004497 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004498 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004499 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00004500 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004501}
4502
4503ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004504 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004505 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004506
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004507 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004508 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004509 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004510 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004511 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004512}
4513
4514ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004515 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004516 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004517
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004518 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004519 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004520 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004521 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004522 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004523}
4524
4525ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004526 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004527 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004528
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004529 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004530 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004531 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004532 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004533 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004534}
4535
4536ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004537 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004538 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004539
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004540 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004541 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004542 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004543 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00004544 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004545}
4546
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004547ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
4548 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004549 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00004550 // Returning a pointer is fine as uuid doesn't need endian swapping.
4551 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00004552 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004553}
Nick Kledzikd04bc352014-08-30 00:20:14 +00004554
Rafael Espindola6e040c02013-04-26 20:07:33 +00004555StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004556 MachO::symtab_command S = getSymtabLoadCommand();
4557 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004558}
4559
Rafael Espindola56f976f2013-04-18 18:08:55 +00004560bool MachOObjectFile::is64Bit() const {
4561 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00004562 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004563}
4564
4565void MachOObjectFile::ReadULEB128s(uint64_t Index,
4566 SmallVectorImpl<uint64_t> &Out) const {
4567 DataExtractor extractor(ObjectFile::getData(), true, 0);
4568
4569 uint32_t offset = Index;
4570 uint64_t data = 0;
4571 while (uint64_t delta = extractor.getULEB128(&offset)) {
4572 data += delta;
4573 Out.push_back(data);
4574 }
4575}
4576
Rafael Espindolac66d7612014-08-17 19:09:37 +00004577bool MachOObjectFile::isRelocatableObject() const {
4578 return getHeader().filetype == MachO::MH_OBJECT;
4579}
4580
Lang Hamesff044b12016-03-25 23:11:52 +00004581Expected<std::unique_ptr<MachOObjectFile>>
Kevin Enderby79d6c632016-10-24 21:15:11 +00004582ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4583 uint32_t UniversalCputype,
4584 uint32_t UniversalIndex) {
Rafael Espindola48af1c22014-08-19 18:44:46 +00004585 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00004586 if (Magic == "\xFE\xED\xFA\xCE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004587 return MachOObjectFile::create(Buffer, false, false,
4588 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004589 if (Magic == "\xCE\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004590 return MachOObjectFile::create(Buffer, true, false,
4591 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004592 if (Magic == "\xFE\xED\xFA\xCF")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004593 return MachOObjectFile::create(Buffer, false, true,
4594 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004595 if (Magic == "\xCF\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004596 return MachOObjectFile::create(Buffer, true, true,
4597 UniversalCputype, UniversalIndex);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00004598 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00004599 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004600}
Wolfgang Pieb77d3e932017-06-06 01:22:34 +00004601
4602StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
4603 return StringSwitch<StringRef>(Name)
4604 .Case("debug_str_offs", "debug_str_offsets")
4605 .Default(Name);
4606}