blob: 3140316b50e8d01f8fcb80d2f719adc872f9cf2f [file] [log] [blame]
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00001//===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
Eric Christopher7b015c72011-04-22 03:19:48 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000015#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/None.h"
Tim Northover00ed9962014-03-29 10:18:08 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000019#include "llvm/ADT/StringRef.h"
Rafael Espindola72318b42014-08-08 16:30:17 +000020#include "llvm/ADT/StringSwitch.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/ADT/Triple.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000022#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/MachO.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000024#include "llvm/Object/Error.h"
25#include "llvm/Object/MachO.h"
26#include "llvm/Object/ObjectFile.h"
27#include "llvm/Object/SymbolicFile.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000028#include "llvm/Support/DataExtractor.h"
Nick Kledzikac431442014-09-12 21:34:15 +000029#include "llvm/Support/Debug.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000030#include "llvm/Support/Error.h"
31#include "llvm/Support/ErrorHandling.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000032#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000033#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000034#include "llvm/Support/LEB128.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000035#include "llvm/Support/MemoryBuffer.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000036#include "llvm/Support/SwapByteOrder.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000037#include "llvm/Support/raw_ostream.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000038#include <algorithm>
39#include <cassert>
40#include <cstddef>
41#include <cstdint>
Eric Christopher7b015c72011-04-22 03:19:48 +000042#include <cstring>
43#include <limits>
Kevin Enderbyd5039402016-10-31 20:29:48 +000044#include <list>
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000045#include <memory>
46#include <string>
47#include <system_error>
Eric Christopher7b015c72011-04-22 03:19:48 +000048
49using namespace llvm;
50using namespace object;
51
Artyom Skrobov7d602f72014-07-20 12:08:28 +000052namespace {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000053
Artyom Skrobov7d602f72014-07-20 12:08:28 +000054 struct section_base {
55 char sectname[16];
56 char segname[16];
57 };
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000058
59} // end anonymous namespace
Rafael Espindola56f976f2013-04-18 18:08:55 +000060
Benjamin Kramer760e00b2017-08-20 15:13:39 +000061static Error malformedError(const Twine &Msg) {
62 return make_error<GenericBinaryError>("truncated or malformed object (" +
63 Msg + ")",
Kevin Enderby89134962016-05-05 23:41:05 +000064 object_error::parse_failed);
Lang Hames9e964f32016-03-25 17:25:34 +000065}
66
Alexey Samsonov9f336632015-06-04 19:45:22 +000067// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000068template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000069static T getStruct(const MachOObjectFile &O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000070 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000071 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Filipe Cabecinhas40139502015-01-15 22:52:38 +000072 report_fatal_error("Malformed MachO file.");
73
Rafael Espindola3cdeb172013-04-19 13:45:05 +000074 T Cmd;
75 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000076 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000077 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000078 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000079}
80
Alexey Samsonov9f336632015-06-04 19:45:22 +000081template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000082static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000083 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000084 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000085 return malformedError("Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000086
87 T Cmd;
88 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000089 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Alexey Samsonov9f336632015-06-04 19:45:22 +000090 MachO::swapStruct(Cmd);
91 return Cmd;
92}
93
Rafael Espindola6e040c02013-04-26 20:07:33 +000094static const char *
Lang Hames697e7cd2016-12-04 01:56:10 +000095getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
Rafael Espindola6e040c02013-04-26 20:07:33 +000096 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000097 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
98
Lang Hames697e7cd2016-12-04 01:56:10 +000099 bool Is64 = O.is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +0000100 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
101 sizeof(MachO::segment_command);
102 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
103 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000104
105 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +0000106 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +0000107}
108
Lang Hames697e7cd2016-12-04 01:56:10 +0000109static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
110 return O.getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +0000111}
112
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000113static MachO::nlist_base
Lang Hames697e7cd2016-12-04 01:56:10 +0000114getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +0000115 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000116 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +0000117}
118
Rafael Espindola56f976f2013-04-18 18:08:55 +0000119static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000120 if (P[15] == 0)
121 // Null terminated.
122 return P;
123 // Not null terminated, so this is a 16 char string.
124 return StringRef(P, 16);
125}
126
Lang Hames697e7cd2016-12-04 01:56:10 +0000127static unsigned getCPUType(const MachOObjectFile &O) {
128 return O.getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000129}
130
Charles Davis8bdfafd2013-09-01 04:28:48 +0000131static uint32_t
132getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
133 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000134}
135
136static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000137getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
138 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000139}
140
Lang Hames697e7cd2016-12-04 01:56:10 +0000141static bool getPlainRelocationPCRel(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000142 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000143 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000144 return (RE.r_word1 >> 24) & 1;
145 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000146}
147
148static bool
Lang Hames697e7cd2016-12-04 01:56:10 +0000149getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000150 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000151}
152
Lang Hames697e7cd2016-12-04 01:56:10 +0000153static unsigned getPlainRelocationLength(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000154 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000155 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000156 return (RE.r_word1 >> 25) & 3;
157 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000158}
159
160static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000161getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
162 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000163}
164
Lang Hames697e7cd2016-12-04 01:56:10 +0000165static unsigned getPlainRelocationType(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000166 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000167 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000168 return RE.r_word1 >> 28;
169 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000170}
171
Lang Hames697e7cd2016-12-04 01:56:10 +0000172static uint32_t getSectionFlags(const MachOObjectFile &O,
Rafael Espindola56f976f2013-04-18 18:08:55 +0000173 DataRefImpl Sec) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000174 if (O.is64Bit()) {
175 MachO::section_64 Sect = O.getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000176 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000177 }
Lang Hames697e7cd2016-12-04 01:56:10 +0000178 MachO::section Sect = O.getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000179 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000180}
181
Lang Hames9e964f32016-03-25 17:25:34 +0000182static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000183getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000184 uint32_t LoadCommandIndex) {
Lang Hames9e964f32016-03-25 17:25:34 +0000185 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
Jonas Devlieghere81f5abe2017-09-13 13:43:01 +0000186 if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
187 return malformedError("load command " + Twine(LoadCommandIndex) +
188 " extends past end of file");
Lang Hames9e964f32016-03-25 17:25:34 +0000189 if (CmdOrErr->cmdsize < 8)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000190 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000191 " with size less than 8 bytes");
Lang Hames9e964f32016-03-25 17:25:34 +0000192 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
193 } else
194 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000195}
196
Lang Hames9e964f32016-03-25 17:25:34 +0000197static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000198getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
199 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
200 : sizeof(MachO::mach_header);
201 if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000202 return malformedError("load command 0 extends past the end all load "
Kevin Enderby89134962016-05-05 23:41:05 +0000203 "commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000204 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000205}
206
Lang Hames9e964f32016-03-25 17:25:34 +0000207static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000208getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000209 const MachOObjectFile::LoadCommandInfo &L) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000210 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
211 : sizeof(MachO::mach_header);
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000212 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
Lang Hames697e7cd2016-12-04 01:56:10 +0000213 Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000214 return malformedError("load command " + Twine(LoadCommandIndex + 1) +
Kevin Enderby89134962016-05-05 23:41:05 +0000215 " extends past the end all load commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000216 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000217}
218
Alexey Samsonov9f336632015-06-04 19:45:22 +0000219template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +0000220static void parseHeader(const MachOObjectFile &Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000221 Error &Err) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000222 if (sizeof(T) > Obj.getData().size()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000223 Err = malformedError("the mach header extends past the end of the "
Kevin Enderby89134962016-05-05 23:41:05 +0000224 "file");
Kevin Enderby87025742016-04-13 21:17:58 +0000225 return;
226 }
Lang Hames9e964f32016-03-25 17:25:34 +0000227 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
228 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000229 else
Lang Hames9e964f32016-03-25 17:25:34 +0000230 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000231}
232
Kevin Enderbyd5039402016-10-31 20:29:48 +0000233// This is used to check for overlapping of Mach-O elements.
234struct MachOElement {
235 uint64_t Offset;
236 uint64_t Size;
237 const char *Name;
238};
239
240static Error checkOverlappingElement(std::list<MachOElement> &Elements,
241 uint64_t Offset, uint64_t Size,
242 const char *Name) {
243 if (Size == 0)
244 return Error::success();
245
246 for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
247 auto E = *it;
248 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
249 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
250 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
251 return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
252 " with a size of " + Twine(Size) + ", overlaps " +
253 E.Name + " at offset " + Twine(E.Offset) + " with "
254 "a size of " + Twine(E.Size));
255 auto nt = it;
256 nt++;
257 if (nt != Elements.end()) {
258 auto N = *nt;
259 if (Offset + Size <= N.Offset) {
260 Elements.insert(nt, {Offset, Size, Name});
261 return Error::success();
262 }
263 }
264 }
265 Elements.push_back({Offset, Size, Name});
266 return Error::success();
267}
268
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000269// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
270// sections to \param Sections, and optionally sets
271// \param IsPageZeroSegment to true.
Kevin Enderbyc614d282016-08-12 20:10:25 +0000272template <typename Segment, typename Section>
Lang Hames9e964f32016-03-25 17:25:34 +0000273static Error parseSegmentLoadCommand(
Lang Hames697e7cd2016-12-04 01:56:10 +0000274 const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000275 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000276 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
277 std::list<MachOElement> &Elements) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000278 const unsigned SegmentLoadSize = sizeof(Segment);
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000279 if (Load.C.cmdsize < SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000280 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000281 " " + CmdName + " cmdsize too small");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000282 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
283 Segment S = SegOrErr.get();
284 const unsigned SectionSize = sizeof(Section);
Lang Hames697e7cd2016-12-04 01:56:10 +0000285 uint64_t FileSize = Obj.getData().size();
Lang Hames9e964f32016-03-25 17:25:34 +0000286 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
287 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000288 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000289 " inconsistent cmdsize in " + CmdName +
Kevin Enderby89134962016-05-05 23:41:05 +0000290 " for the number of sections");
Lang Hames9e964f32016-03-25 17:25:34 +0000291 for (unsigned J = 0; J < S.nsects; ++J) {
292 const char *Sec = getSectionPtr(Obj, Load, J);
293 Sections.push_back(Sec);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000294 Section s = getStruct<Section>(Obj, Sec);
Lang Hames697e7cd2016-12-04 01:56:10 +0000295 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
296 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000297 s.flags != MachO::S_ZEROFILL &&
298 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
299 s.offset > FileSize)
300 return malformedError("offset field of section " + Twine(J) + " in " +
301 CmdName + " command " + Twine(LoadCommandIndex) +
302 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000303 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
304 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000305 s.flags != MachO::S_ZEROFILL &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000306 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
307 s.offset < SizeOfHeaders && s.size != 0)
Kevin Enderbyc614d282016-08-12 20:10:25 +0000308 return malformedError("offset field of section " + Twine(J) + " in " +
309 CmdName + " command " + Twine(LoadCommandIndex) +
310 " not past the headers of the file");
311 uint64_t BigSize = s.offset;
312 BigSize += s.size;
Lang Hames697e7cd2016-12-04 01:56:10 +0000313 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
314 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000315 s.flags != MachO::S_ZEROFILL &&
316 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
317 BigSize > FileSize)
318 return malformedError("offset field plus size field of section " +
319 Twine(J) + " in " + CmdName + " command " +
320 Twine(LoadCommandIndex) +
321 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000322 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
323 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000324 s.flags != MachO::S_ZEROFILL &&
325 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
326 s.size > S.filesize)
327 return malformedError("size field of section " +
328 Twine(J) + " in " + CmdName + " command " +
329 Twine(LoadCommandIndex) +
330 " greater than the segment");
Lang Hames697e7cd2016-12-04 01:56:10 +0000331 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
332 Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000333 s.addr < S.vmaddr)
334 return malformedError("addr field of section " + Twine(J) + " in " +
335 CmdName + " command " + Twine(LoadCommandIndex) +
336 " less than the segment's vmaddr");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000337 BigSize = s.addr;
338 BigSize += s.size;
339 uint64_t BigEnd = S.vmaddr;
340 BigEnd += S.vmsize;
341 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000342 return malformedError("addr field plus size of section " + Twine(J) +
343 " in " + CmdName + " command " +
344 Twine(LoadCommandIndex) +
345 " greater than than "
Kevin Enderbyc614d282016-08-12 20:10:25 +0000346 "the segment's vmaddr plus vmsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000347 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
348 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000349 s.flags != MachO::S_ZEROFILL &&
350 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
351 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
352 "section contents"))
353 return Err;
Kevin Enderbyc614d282016-08-12 20:10:25 +0000354 if (s.reloff > FileSize)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000355 return malformedError("reloff field of section " + Twine(J) + " in " +
356 CmdName + " command " + Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000357 " extends past the end of the file");
358 BigSize = s.nreloc;
359 BigSize *= sizeof(struct MachO::relocation_info);
360 BigSize += s.reloff;
361 if (BigSize > FileSize)
362 return malformedError("reloff field plus nreloc field times sizeof("
363 "struct relocation_info) of section " +
364 Twine(J) + " in " + CmdName + " command " +
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000365 Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000366 " extends past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000367 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
368 sizeof(struct
369 MachO::relocation_info),
370 "section relocation entries"))
371 return Err;
Lang Hames9e964f32016-03-25 17:25:34 +0000372 }
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000373 if (S.fileoff > FileSize)
374 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000375 " fileoff field in " + CmdName +
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000376 " extends past the end of the file");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000377 uint64_t BigSize = S.fileoff;
378 BigSize += S.filesize;
379 if (BigSize > FileSize)
380 return malformedError("load command " + Twine(LoadCommandIndex) +
381 " fileoff field plus filesize field in " +
382 CmdName + " extends past the end of the file");
383 if (S.vmsize != 0 && S.filesize > S.vmsize)
384 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby86d8bd12017-02-07 21:20:44 +0000385 " filesize field in " + CmdName +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000386 " greater than vmsize field");
Lang Hames9e964f32016-03-25 17:25:34 +0000387 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
388 } else
389 return SegOrErr.takeError();
390
391 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000392}
393
Lang Hames697e7cd2016-12-04 01:56:10 +0000394static Error checkSymtabCommand(const MachOObjectFile &Obj,
Kevin Enderby0e52c922016-08-26 19:34:07 +0000395 const MachOObjectFile::LoadCommandInfo &Load,
396 uint32_t LoadCommandIndex,
Kevin Enderbyd5039402016-10-31 20:29:48 +0000397 const char **SymtabLoadCmd,
398 std::list<MachOElement> &Elements) {
Kevin Enderby0e52c922016-08-26 19:34:07 +0000399 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
400 return malformedError("load command " + Twine(LoadCommandIndex) +
401 " LC_SYMTAB cmdsize too small");
402 if (*SymtabLoadCmd != nullptr)
403 return malformedError("more than one LC_SYMTAB command");
404 MachO::symtab_command Symtab =
405 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
406 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
407 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
408 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000409 uint64_t FileSize = Obj.getData().size();
Kevin Enderby0e52c922016-08-26 19:34:07 +0000410 if (Symtab.symoff > FileSize)
411 return malformedError("symoff field of LC_SYMTAB command " +
412 Twine(LoadCommandIndex) + " extends past the end "
413 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000414 uint64_t SymtabSize = Symtab.nsyms;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000415 const char *struct_nlist_name;
Lang Hames697e7cd2016-12-04 01:56:10 +0000416 if (Obj.is64Bit()) {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000417 SymtabSize *= sizeof(MachO::nlist_64);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000418 struct_nlist_name = "struct nlist_64";
419 } else {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000420 SymtabSize *= sizeof(MachO::nlist);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000421 struct_nlist_name = "struct nlist";
422 }
Kevin Enderbyd5039402016-10-31 20:29:48 +0000423 uint64_t BigSize = SymtabSize;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000424 BigSize += Symtab.symoff;
425 if (BigSize > FileSize)
426 return malformedError("symoff field plus nsyms field times sizeof(" +
427 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
428 Twine(LoadCommandIndex) + " extends past the end "
429 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000430 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
431 "symbol table"))
432 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000433 if (Symtab.stroff > FileSize)
434 return malformedError("stroff field of LC_SYMTAB command " +
435 Twine(LoadCommandIndex) + " extends past the end "
436 "of the file");
437 BigSize = Symtab.stroff;
438 BigSize += Symtab.strsize;
439 if (BigSize > FileSize)
440 return malformedError("stroff field plus strsize field of LC_SYMTAB "
441 "command " + Twine(LoadCommandIndex) + " extends "
442 "past the end of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000443 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
444 Symtab.strsize, "string table"))
445 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000446 *SymtabLoadCmd = Load.Ptr;
447 return Error::success();
448}
449
Lang Hames697e7cd2016-12-04 01:56:10 +0000450static Error checkDysymtabCommand(const MachOObjectFile &Obj,
451 const MachOObjectFile::LoadCommandInfo &Load,
452 uint32_t LoadCommandIndex,
453 const char **DysymtabLoadCmd,
454 std::list<MachOElement> &Elements) {
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000455 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
456 return malformedError("load command " + Twine(LoadCommandIndex) +
457 " LC_DYSYMTAB cmdsize too small");
458 if (*DysymtabLoadCmd != nullptr)
459 return malformedError("more than one LC_DYSYMTAB command");
460 MachO::dysymtab_command Dysymtab =
461 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
462 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
463 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
464 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000465 uint64_t FileSize = Obj.getData().size();
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000466 if (Dysymtab.tocoff > FileSize)
467 return malformedError("tocoff field of LC_DYSYMTAB command " +
468 Twine(LoadCommandIndex) + " extends past the end of "
469 "the file");
470 uint64_t BigSize = Dysymtab.ntoc;
471 BigSize *= sizeof(MachO::dylib_table_of_contents);
472 BigSize += Dysymtab.tocoff;
473 if (BigSize > FileSize)
474 return malformedError("tocoff field plus ntoc field times sizeof(struct "
475 "dylib_table_of_contents) of LC_DYSYMTAB command " +
476 Twine(LoadCommandIndex) + " extends past the end of "
477 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000478 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
479 Dysymtab.ntoc * sizeof(struct
NAKAMURA Takumi6f43bd42017-10-18 13:31:28 +0000480 MachO::dylib_table_of_contents),
481 "table of contents"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000482 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000483 if (Dysymtab.modtaboff > FileSize)
484 return malformedError("modtaboff field of LC_DYSYMTAB command " +
485 Twine(LoadCommandIndex) + " extends past the end of "
486 "the file");
487 BigSize = Dysymtab.nmodtab;
488 const char *struct_dylib_module_name;
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000489 uint64_t sizeof_modtab;
Lang Hames697e7cd2016-12-04 01:56:10 +0000490 if (Obj.is64Bit()) {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000491 sizeof_modtab = sizeof(MachO::dylib_module_64);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000492 struct_dylib_module_name = "struct dylib_module_64";
493 } else {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000494 sizeof_modtab = sizeof(MachO::dylib_module);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000495 struct_dylib_module_name = "struct dylib_module";
496 }
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000497 BigSize *= sizeof_modtab;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000498 BigSize += Dysymtab.modtaboff;
499 if (BigSize > FileSize)
500 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
501 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
502 "command " + Twine(LoadCommandIndex) + " extends "
503 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000504 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
505 Dysymtab.nmodtab * sizeof_modtab,
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000506 "module table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000507 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000508 if (Dysymtab.extrefsymoff > FileSize)
509 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
510 Twine(LoadCommandIndex) + " extends past the end of "
511 "the file");
512 BigSize = Dysymtab.nextrefsyms;
513 BigSize *= sizeof(MachO::dylib_reference);
514 BigSize += Dysymtab.extrefsymoff;
515 if (BigSize > FileSize)
516 return malformedError("extrefsymoff field plus nextrefsyms field times "
517 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
518 "command " + Twine(LoadCommandIndex) + " extends "
519 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000520 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
521 Dysymtab.nextrefsyms *
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000522 sizeof(MachO::dylib_reference),
523 "reference table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000524 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000525 if (Dysymtab.indirectsymoff > FileSize)
526 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
527 Twine(LoadCommandIndex) + " extends past the end of "
528 "the file");
529 BigSize = Dysymtab.nindirectsyms;
530 BigSize *= sizeof(uint32_t);
531 BigSize += Dysymtab.indirectsymoff;
532 if (BigSize > FileSize)
533 return malformedError("indirectsymoff field plus nindirectsyms field times "
534 "sizeof(uint32_t) of LC_DYSYMTAB command " +
535 Twine(LoadCommandIndex) + " extends past the end of "
536 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000537 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
538 Dysymtab.nindirectsyms *
539 sizeof(uint32_t),
NAKAMURA Takumi6f43bd42017-10-18 13:31:28 +0000540 "indirect table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000541 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000542 if (Dysymtab.extreloff > FileSize)
543 return malformedError("extreloff field of LC_DYSYMTAB command " +
544 Twine(LoadCommandIndex) + " extends past the end of "
545 "the file");
546 BigSize = Dysymtab.nextrel;
547 BigSize *= sizeof(MachO::relocation_info);
548 BigSize += Dysymtab.extreloff;
549 if (BigSize > FileSize)
550 return malformedError("extreloff field plus nextrel field times sizeof"
551 "(struct relocation_info) of LC_DYSYMTAB command " +
552 Twine(LoadCommandIndex) + " extends past the end of "
553 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000554 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
555 Dysymtab.nextrel *
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000556 sizeof(MachO::relocation_info),
557 "external relocation table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000558 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000559 if (Dysymtab.locreloff > FileSize)
560 return malformedError("locreloff field of LC_DYSYMTAB command " +
561 Twine(LoadCommandIndex) + " extends past the end of "
562 "the file");
563 BigSize = Dysymtab.nlocrel;
564 BigSize *= sizeof(MachO::relocation_info);
565 BigSize += Dysymtab.locreloff;
566 if (BigSize > FileSize)
567 return malformedError("locreloff field plus nlocrel field times sizeof"
568 "(struct relocation_info) of LC_DYSYMTAB command " +
569 Twine(LoadCommandIndex) + " extends past the end of "
570 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000571 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
572 Dysymtab.nlocrel *
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +0000573 sizeof(MachO::relocation_info),
574 "local relocation table"))
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000575 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000576 *DysymtabLoadCmd = Load.Ptr;
577 return Error::success();
578}
579
Lang Hames697e7cd2016-12-04 01:56:10 +0000580static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000581 const MachOObjectFile::LoadCommandInfo &Load,
582 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000583 const char **LoadCmd, const char *CmdName,
584 std::list<MachOElement> &Elements,
585 const char *ElementName) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000586 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
587 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
588 CmdName + " cmdsize too small");
589 if (*LoadCmd != nullptr)
590 return malformedError("more than one " + Twine(CmdName) + " command");
591 MachO::linkedit_data_command LinkData =
592 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
593 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
594 return malformedError(Twine(CmdName) + " command " +
595 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000596 uint64_t FileSize = Obj.getData().size();
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000597 if (LinkData.dataoff > FileSize)
598 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
599 Twine(LoadCommandIndex) + " extends past the end of "
600 "the file");
601 uint64_t BigSize = LinkData.dataoff;
602 BigSize += LinkData.datasize;
603 if (BigSize > FileSize)
604 return malformedError("dataoff field plus datasize field of " +
605 Twine(CmdName) + " command " +
606 Twine(LoadCommandIndex) + " extends past the end of "
607 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000608 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
609 LinkData.datasize, ElementName))
610 return Err;
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000611 *LoadCmd = Load.Ptr;
612 return Error::success();
613}
614
Lang Hames697e7cd2016-12-04 01:56:10 +0000615static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000616 const MachOObjectFile::LoadCommandInfo &Load,
617 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000618 const char **LoadCmd, const char *CmdName,
619 std::list<MachOElement> &Elements) {
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000620 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
621 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
622 CmdName + " cmdsize too small");
623 if (*LoadCmd != nullptr)
624 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
625 "command");
626 MachO::dyld_info_command DyldInfo =
627 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
628 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
629 return malformedError(Twine(CmdName) + " command " +
630 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000631 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000632 if (DyldInfo.rebase_off > FileSize)
633 return malformedError("rebase_off field of " + Twine(CmdName) +
634 " command " + Twine(LoadCommandIndex) + " extends "
635 "past the end of the file");
636 uint64_t BigSize = DyldInfo.rebase_off;
637 BigSize += DyldInfo.rebase_size;
638 if (BigSize > FileSize)
639 return malformedError("rebase_off field plus rebase_size field of " +
640 Twine(CmdName) + " command " +
641 Twine(LoadCommandIndex) + " extends past the end of "
642 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000643 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
644 DyldInfo.rebase_size,
645 "dyld rebase info"))
646 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000647 if (DyldInfo.bind_off > FileSize)
648 return malformedError("bind_off field of " + Twine(CmdName) +
649 " command " + Twine(LoadCommandIndex) + " extends "
650 "past the end of the file");
651 BigSize = DyldInfo.bind_off;
652 BigSize += DyldInfo.bind_size;
653 if (BigSize > FileSize)
654 return malformedError("bind_off field plus bind_size field of " +
655 Twine(CmdName) + " command " +
656 Twine(LoadCommandIndex) + " extends past the end of "
657 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000658 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
659 DyldInfo.bind_size,
660 "dyld bind info"))
661 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000662 if (DyldInfo.weak_bind_off > FileSize)
663 return malformedError("weak_bind_off field of " + Twine(CmdName) +
664 " command " + Twine(LoadCommandIndex) + " extends "
665 "past the end of the file");
666 BigSize = DyldInfo.weak_bind_off;
667 BigSize += DyldInfo.weak_bind_size;
668 if (BigSize > FileSize)
669 return malformedError("weak_bind_off field plus weak_bind_size field of " +
670 Twine(CmdName) + " command " +
671 Twine(LoadCommandIndex) + " extends past the end of "
672 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000673 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
674 DyldInfo.weak_bind_size,
675 "dyld weak bind info"))
676 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000677 if (DyldInfo.lazy_bind_off > FileSize)
678 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
679 " command " + Twine(LoadCommandIndex) + " extends "
680 "past the end of the file");
681 BigSize = DyldInfo.lazy_bind_off;
682 BigSize += DyldInfo.lazy_bind_size;
683 if (BigSize > FileSize)
684 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
685 Twine(CmdName) + " command " +
686 Twine(LoadCommandIndex) + " extends past the end of "
687 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000688 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
689 DyldInfo.lazy_bind_size,
690 "dyld lazy bind info"))
691 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000692 if (DyldInfo.export_off > FileSize)
693 return malformedError("export_off field of " + Twine(CmdName) +
694 " command " + Twine(LoadCommandIndex) + " extends "
695 "past the end of the file");
696 BigSize = DyldInfo.export_off;
697 BigSize += DyldInfo.export_size;
698 if (BigSize > FileSize)
699 return malformedError("export_off field plus export_size field of " +
700 Twine(CmdName) + " command " +
701 Twine(LoadCommandIndex) + " extends past the end of "
702 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000703 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
704 DyldInfo.export_size,
705 "dyld export info"))
706 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000707 *LoadCmd = Load.Ptr;
708 return Error::success();
709}
710
Lang Hames697e7cd2016-12-04 01:56:10 +0000711static Error checkDylibCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000712 const MachOObjectFile::LoadCommandInfo &Load,
713 uint32_t LoadCommandIndex, const char *CmdName) {
714 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
715 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
716 CmdName + " cmdsize too small");
717 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
718 if (D.dylib.name < sizeof(MachO::dylib_command))
719 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
720 CmdName + " name.offset field too small, not past "
721 "the end of the dylib_command struct");
722 if (D.dylib.name >= D.cmdsize)
723 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
724 CmdName + " name.offset field extends past the end "
725 "of the load command");
726 // Make sure there is a null between the starting offset of the name and
727 // the end of the load command.
728 uint32_t i;
729 const char *P = (const char *)Load.Ptr;
730 for (i = D.dylib.name; i < D.cmdsize; i++)
731 if (P[i] == '\0')
732 break;
733 if (i >= D.cmdsize)
734 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
735 CmdName + " library name extends past the end of the "
736 "load command");
737 return Error::success();
738}
739
Lang Hames697e7cd2016-12-04 01:56:10 +0000740static Error checkDylibIdCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000741 const MachOObjectFile::LoadCommandInfo &Load,
742 uint32_t LoadCommandIndex,
743 const char **LoadCmd) {
744 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
745 "LC_ID_DYLIB"))
746 return Err;
747 if (*LoadCmd != nullptr)
748 return malformedError("more than one LC_ID_DYLIB command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000749 if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
750 Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000751 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
752 "file type");
753 *LoadCmd = Load.Ptr;
754 return Error::success();
755}
756
Lang Hames697e7cd2016-12-04 01:56:10 +0000757static Error checkDyldCommand(const MachOObjectFile &Obj,
Kevin Enderby3e490ef2016-09-27 23:24:13 +0000758 const MachOObjectFile::LoadCommandInfo &Load,
759 uint32_t LoadCommandIndex, const char *CmdName) {
760 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
761 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
762 CmdName + " cmdsize too small");
763 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
764 if (D.name < sizeof(MachO::dylinker_command))
765 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
766 CmdName + " name.offset field too small, not past "
767 "the end of the dylinker_command struct");
768 if (D.name >= D.cmdsize)
769 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
770 CmdName + " name.offset field extends past the end "
771 "of the load command");
772 // Make sure there is a null between the starting offset of the name and
773 // the end of the load command.
774 uint32_t i;
775 const char *P = (const char *)Load.Ptr;
776 for (i = D.name; i < D.cmdsize; i++)
777 if (P[i] == '\0')
778 break;
779 if (i >= D.cmdsize)
780 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
781 CmdName + " dyld name extends past the end of the "
782 "load command");
783 return Error::success();
784}
785
Lang Hames697e7cd2016-12-04 01:56:10 +0000786static Error checkVersCommand(const MachOObjectFile &Obj,
Kevin Enderby32359db2016-09-28 21:20:45 +0000787 const MachOObjectFile::LoadCommandInfo &Load,
788 uint32_t LoadCommandIndex,
789 const char **LoadCmd, const char *CmdName) {
790 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
791 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
792 CmdName + " has incorrect cmdsize");
793 if (*LoadCmd != nullptr)
794 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
795 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
796 "LC_VERSION_MIN_WATCHOS command");
797 *LoadCmd = Load.Ptr;
798 return Error::success();
799}
800
Kevin Enderbya4579c42017-01-19 17:36:31 +0000801static Error checkNoteCommand(const MachOObjectFile &Obj,
802 const MachOObjectFile::LoadCommandInfo &Load,
803 uint32_t LoadCommandIndex,
804 std::list<MachOElement> &Elements) {
805 if (Load.C.cmdsize != sizeof(MachO::note_command))
Jonas Devlieghere81f5abe2017-09-13 13:43:01 +0000806 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderbya4579c42017-01-19 17:36:31 +0000807 " LC_NOTE has incorrect cmdsize");
808 MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
809 uint64_t FileSize = Obj.getData().size();
810 if (Nt.offset > FileSize)
811 return malformedError("offset field of LC_NOTE command " +
812 Twine(LoadCommandIndex) + " extends "
813 "past the end of the file");
814 uint64_t BigSize = Nt.offset;
815 BigSize += Nt.size;
816 if (BigSize > FileSize)
817 return malformedError("size field plus offset field of LC_NOTE command " +
818 Twine(LoadCommandIndex) + " extends past the end of "
819 "the file");
820 if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
821 "LC_NOTE data"))
822 return Err;
823 return Error::success();
824}
825
Steven Wu5b54a422017-01-23 20:07:55 +0000826static Error
827parseBuildVersionCommand(const MachOObjectFile &Obj,
828 const MachOObjectFile::LoadCommandInfo &Load,
829 SmallVectorImpl<const char*> &BuildTools,
830 uint32_t LoadCommandIndex) {
831 MachO::build_version_command BVC =
832 getStruct<MachO::build_version_command>(Obj, Load.Ptr);
833 if (Load.C.cmdsize !=
834 sizeof(MachO::build_version_command) +
835 BVC.ntools * sizeof(MachO::build_tool_version))
836 return malformedError("load command " + Twine(LoadCommandIndex) +
837 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
838
839 auto Start = Load.Ptr + sizeof(MachO::build_version_command);
840 BuildTools.resize(BVC.ntools);
841 for (unsigned i = 0; i < BVC.ntools; ++i)
842 BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
843
844 return Error::success();
845}
846
Lang Hames697e7cd2016-12-04 01:56:10 +0000847static Error checkRpathCommand(const MachOObjectFile &Obj,
Kevin Enderby76966bf2016-09-28 23:16:01 +0000848 const MachOObjectFile::LoadCommandInfo &Load,
849 uint32_t LoadCommandIndex) {
850 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
851 return malformedError("load command " + Twine(LoadCommandIndex) +
852 " LC_RPATH cmdsize too small");
853 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
854 if (R.path < sizeof(MachO::rpath_command))
855 return malformedError("load command " + Twine(LoadCommandIndex) +
856 " LC_RPATH path.offset field too small, not past "
857 "the end of the rpath_command struct");
858 if (R.path >= R.cmdsize)
859 return malformedError("load command " + Twine(LoadCommandIndex) +
860 " LC_RPATH path.offset field extends past the end "
861 "of the load command");
862 // Make sure there is a null between the starting offset of the path and
863 // the end of the load command.
864 uint32_t i;
865 const char *P = (const char *)Load.Ptr;
866 for (i = R.path; i < R.cmdsize; i++)
867 if (P[i] == '\0')
868 break;
869 if (i >= R.cmdsize)
870 return malformedError("load command " + Twine(LoadCommandIndex) +
871 " LC_RPATH library name extends past the end of the "
872 "load command");
873 return Error::success();
874}
875
Lang Hames697e7cd2016-12-04 01:56:10 +0000876static Error checkEncryptCommand(const MachOObjectFile &Obj,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000877 const MachOObjectFile::LoadCommandInfo &Load,
878 uint32_t LoadCommandIndex,
879 uint64_t cryptoff, uint64_t cryptsize,
880 const char **LoadCmd, const char *CmdName) {
881 if (*LoadCmd != nullptr)
882 return malformedError("more than one LC_ENCRYPTION_INFO and or "
883 "LC_ENCRYPTION_INFO_64 command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000884 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000885 if (cryptoff > FileSize)
886 return malformedError("cryptoff field of " + Twine(CmdName) +
887 " command " + Twine(LoadCommandIndex) + " extends "
888 "past the end of the file");
889 uint64_t BigSize = cryptoff;
890 BigSize += cryptsize;
891 if (BigSize > FileSize)
892 return malformedError("cryptoff field plus cryptsize field of " +
893 Twine(CmdName) + " command " +
894 Twine(LoadCommandIndex) + " extends past the end of "
895 "the file");
896 *LoadCmd = Load.Ptr;
897 return Error::success();
898}
899
Lang Hames697e7cd2016-12-04 01:56:10 +0000900static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
Kevin Enderby68fffa82016-10-11 21:04:39 +0000901 const MachOObjectFile::LoadCommandInfo &Load,
902 uint32_t LoadCommandIndex) {
903 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
904 return malformedError("load command " + Twine(LoadCommandIndex) +
905 " LC_LINKER_OPTION cmdsize too small");
906 MachO::linker_option_command L =
907 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
908 // Make sure the count of strings is correct.
909 const char *string = (const char *)Load.Ptr +
910 sizeof(struct MachO::linker_option_command);
911 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
912 uint32_t i = 0;
913 while (left > 0) {
914 while (*string == '\0' && left > 0) {
915 string++;
916 left--;
917 }
918 if (left > 0) {
919 i++;
920 uint32_t NullPos = StringRef(string, left).find('\0');
921 uint32_t len = std::min(NullPos, left) + 1;
922 string += len;
923 left -= len;
924 }
925 }
926 if (L.count != i)
927 return malformedError("load command " + Twine(LoadCommandIndex) +
928 " LC_LINKER_OPTION string count " + Twine(L.count) +
929 " does not match number of strings");
930 return Error::success();
931}
932
Lang Hames697e7cd2016-12-04 01:56:10 +0000933static Error checkSubCommand(const MachOObjectFile &Obj,
Kevin Enderby2490de02016-10-17 22:09:25 +0000934 const MachOObjectFile::LoadCommandInfo &Load,
935 uint32_t LoadCommandIndex, const char *CmdName,
936 size_t SizeOfCmd, const char *CmdStructName,
937 uint32_t PathOffset, const char *PathFieldName) {
938 if (PathOffset < SizeOfCmd)
939 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
940 CmdName + " " + PathFieldName + ".offset field too "
941 "small, not past the end of the " + CmdStructName);
942 if (PathOffset >= Load.C.cmdsize)
943 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
944 CmdName + " " + PathFieldName + ".offset field "
945 "extends past the end of the load command");
946 // Make sure there is a null between the starting offset of the path and
947 // the end of the load command.
948 uint32_t i;
949 const char *P = (const char *)Load.Ptr;
950 for (i = PathOffset; i < Load.C.cmdsize; i++)
951 if (P[i] == '\0')
952 break;
953 if (i >= Load.C.cmdsize)
954 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
955 CmdName + " " + PathFieldName + " name extends past "
956 "the end of the load command");
957 return Error::success();
958}
959
Lang Hames697e7cd2016-12-04 01:56:10 +0000960static Error checkThreadCommand(const MachOObjectFile &Obj,
Kevin Enderby210030b2016-10-19 23:44:34 +0000961 const MachOObjectFile::LoadCommandInfo &Load,
962 uint32_t LoadCommandIndex,
963 const char *CmdName) {
964 if (Load.C.cmdsize < sizeof(MachO::thread_command))
965 return malformedError("load command " + Twine(LoadCommandIndex) +
966 CmdName + " cmdsize too small");
967 MachO::thread_command T =
968 getStruct<MachO::thread_command>(Obj, Load.Ptr);
969 const char *state = Load.Ptr + sizeof(MachO::thread_command);
970 const char *end = Load.Ptr + T.cmdsize;
971 uint32_t nflavor = 0;
972 uint32_t cputype = getCPUType(Obj);
973 while (state < end) {
974 if(state + sizeof(uint32_t) > end)
975 return malformedError("load command " + Twine(LoadCommandIndex) +
976 "flavor in " + CmdName + " extends past end of "
977 "command");
978 uint32_t flavor;
979 memcpy(&flavor, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000980 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000981 sys::swapByteOrder(flavor);
982 state += sizeof(uint32_t);
983
984 if(state + sizeof(uint32_t) > end)
985 return malformedError("load command " + Twine(LoadCommandIndex) +
986 " count in " + CmdName + " extends past end of "
987 "command");
988 uint32_t count;
989 memcpy(&count, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000990 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000991 sys::swapByteOrder(count);
992 state += sizeof(uint32_t);
993
Kevin Enderbyc3a035d2017-01-23 21:13:29 +0000994 if (cputype == MachO::CPU_TYPE_I386) {
995 if (flavor == MachO::x86_THREAD_STATE32) {
996 if (count != MachO::x86_THREAD_STATE32_COUNT)
997 return malformedError("load command " + Twine(LoadCommandIndex) +
998 " count not x86_THREAD_STATE32_COUNT for "
999 "flavor number " + Twine(nflavor) + " which is "
1000 "a x86_THREAD_STATE32 flavor in " + CmdName +
1001 " command");
1002 if (state + sizeof(MachO::x86_thread_state32_t) > end)
1003 return malformedError("load command " + Twine(LoadCommandIndex) +
1004 " x86_THREAD_STATE32 extends past end of "
1005 "command in " + CmdName + " command");
1006 state += sizeof(MachO::x86_thread_state32_t);
1007 } else {
1008 return malformedError("load command " + Twine(LoadCommandIndex) +
1009 " unknown flavor (" + Twine(flavor) + ") for "
1010 "flavor number " + Twine(nflavor) + " in " +
1011 CmdName + " command");
1012 }
1013 } else if (cputype == MachO::CPU_TYPE_X86_64) {
Kevin Enderby210030b2016-10-19 23:44:34 +00001014 if (flavor == MachO::x86_THREAD_STATE64) {
1015 if (count != MachO::x86_THREAD_STATE64_COUNT)
1016 return malformedError("load command " + Twine(LoadCommandIndex) +
1017 " count not x86_THREAD_STATE64_COUNT for "
1018 "flavor number " + Twine(nflavor) + " which is "
1019 "a x86_THREAD_STATE64 flavor in " + CmdName +
1020 " command");
1021 if (state + sizeof(MachO::x86_thread_state64_t) > end)
1022 return malformedError("load command " + Twine(LoadCommandIndex) +
1023 " x86_THREAD_STATE64 extends past end of "
1024 "command in " + CmdName + " command");
1025 state += sizeof(MachO::x86_thread_state64_t);
1026 } else {
1027 return malformedError("load command " + Twine(LoadCommandIndex) +
1028 " unknown flavor (" + Twine(flavor) + ") for "
1029 "flavor number " + Twine(nflavor) + " in " +
1030 CmdName + " command");
1031 }
1032 } else if (cputype == MachO::CPU_TYPE_ARM) {
1033 if (flavor == MachO::ARM_THREAD_STATE) {
1034 if (count != MachO::ARM_THREAD_STATE_COUNT)
1035 return malformedError("load command " + Twine(LoadCommandIndex) +
1036 " count not ARM_THREAD_STATE_COUNT for "
1037 "flavor number " + Twine(nflavor) + " which is "
1038 "a ARM_THREAD_STATE flavor in " + CmdName +
1039 " command");
1040 if (state + sizeof(MachO::arm_thread_state32_t) > end)
1041 return malformedError("load command " + Twine(LoadCommandIndex) +
1042 " ARM_THREAD_STATE extends past end of "
1043 "command in " + CmdName + " command");
1044 state += sizeof(MachO::arm_thread_state32_t);
1045 } else {
1046 return malformedError("load command " + Twine(LoadCommandIndex) +
1047 " unknown flavor (" + Twine(flavor) + ") for "
1048 "flavor number " + Twine(nflavor) + " in " +
1049 CmdName + " command");
1050 }
Kevin Enderby7747cb52016-11-03 20:51:28 +00001051 } else if (cputype == MachO::CPU_TYPE_ARM64) {
1052 if (flavor == MachO::ARM_THREAD_STATE64) {
1053 if (count != MachO::ARM_THREAD_STATE64_COUNT)
1054 return malformedError("load command " + Twine(LoadCommandIndex) +
1055 " count not ARM_THREAD_STATE64_COUNT for "
1056 "flavor number " + Twine(nflavor) + " which is "
1057 "a ARM_THREAD_STATE64 flavor in " + CmdName +
1058 " command");
1059 if (state + sizeof(MachO::arm_thread_state64_t) > end)
1060 return malformedError("load command " + Twine(LoadCommandIndex) +
1061 " ARM_THREAD_STATE64 extends past end of "
1062 "command in " + CmdName + " command");
1063 state += sizeof(MachO::arm_thread_state64_t);
1064 } else {
1065 return malformedError("load command " + Twine(LoadCommandIndex) +
1066 " unknown flavor (" + Twine(flavor) + ") for "
1067 "flavor number " + Twine(nflavor) + " in " +
1068 CmdName + " command");
1069 }
Kevin Enderby210030b2016-10-19 23:44:34 +00001070 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1071 if (flavor == MachO::PPC_THREAD_STATE) {
1072 if (count != MachO::PPC_THREAD_STATE_COUNT)
1073 return malformedError("load command " + Twine(LoadCommandIndex) +
1074 " count not PPC_THREAD_STATE_COUNT for "
1075 "flavor number " + Twine(nflavor) + " which is "
1076 "a PPC_THREAD_STATE flavor in " + CmdName +
1077 " command");
1078 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1079 return malformedError("load command " + Twine(LoadCommandIndex) +
1080 " PPC_THREAD_STATE extends past end of "
1081 "command in " + CmdName + " command");
1082 state += sizeof(MachO::ppc_thread_state32_t);
1083 } else {
1084 return malformedError("load command " + Twine(LoadCommandIndex) +
1085 " unknown flavor (" + Twine(flavor) + ") for "
1086 "flavor number " + Twine(nflavor) + " in " +
1087 CmdName + " command");
1088 }
1089 } else {
1090 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1091 "command " + Twine(LoadCommandIndex) + " for " +
1092 CmdName + " command can't be checked");
1093 }
1094 nflavor++;
1095 }
1096 return Error::success();
1097}
1098
Lang Hames697e7cd2016-12-04 01:56:10 +00001099static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001100 const MachOObjectFile::LoadCommandInfo
1101 &Load,
1102 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001103 const char **LoadCmd,
1104 std::list<MachOElement> &Elements) {
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001105 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1106 return malformedError("load command " + Twine(LoadCommandIndex) +
1107 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1108 if (*LoadCmd != nullptr)
1109 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1110 MachO::twolevel_hints_command Hints =
1111 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
Lang Hames697e7cd2016-12-04 01:56:10 +00001112 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001113 if (Hints.offset > FileSize)
1114 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1115 Twine(LoadCommandIndex) + " extends past the end of "
1116 "the file");
1117 uint64_t BigSize = Hints.nhints;
Jessica Paquette1a81dfb2017-10-17 20:43:33 +00001118 BigSize *= sizeof(MachO::twolevel_hint);
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001119 BigSize += Hints.offset;
1120 if (BigSize > FileSize)
1121 return malformedError("offset field plus nhints times sizeof(struct "
1122 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1123 Twine(LoadCommandIndex) + " extends past the end of "
1124 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001125 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1126 sizeof(MachO::twolevel_hint),
1127 "two level hints"))
1128 return Err;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001129 *LoadCmd = Load.Ptr;
1130 return Error::success();
1131}
1132
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001133// Returns true if the libObject code does not support the load command and its
1134// contents. The cmd value it is treated as an unknown load command but with
1135// an error message that says the cmd value is obsolete.
1136static bool isLoadCommandObsolete(uint32_t cmd) {
1137 if (cmd == MachO::LC_SYMSEG ||
1138 cmd == MachO::LC_LOADFVMLIB ||
1139 cmd == MachO::LC_IDFVMLIB ||
1140 cmd == MachO::LC_IDENT ||
1141 cmd == MachO::LC_FVMFILE ||
1142 cmd == MachO::LC_PREPAGE ||
1143 cmd == MachO::LC_PREBOUND_DYLIB ||
1144 cmd == MachO::LC_TWOLEVEL_HINTS ||
1145 cmd == MachO::LC_PREBIND_CKSUM)
1146 return true;
1147 return false;
1148}
1149
Lang Hames82627642016-03-25 21:59:14 +00001150Expected<std::unique_ptr<MachOObjectFile>>
1151MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001152 bool Is64Bits, uint32_t UniversalCputype,
1153 uint32_t UniversalIndex) {
Mehdi Amini41af4302016-11-11 04:28:40 +00001154 Error Err = Error::success();
Lang Hames82627642016-03-25 21:59:14 +00001155 std::unique_ptr<MachOObjectFile> Obj(
1156 new MachOObjectFile(std::move(Object), IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001157 Is64Bits, Err, UniversalCputype,
1158 UniversalIndex));
Lang Hames82627642016-03-25 21:59:14 +00001159 if (Err)
1160 return std::move(Err);
1161 return std::move(Obj);
1162}
1163
Rafael Espindola48af1c22014-08-19 18:44:46 +00001164MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001165 bool Is64bits, Error &Err,
1166 uint32_t UniversalCputype,
1167 uint32_t UniversalIndex)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00001168 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
Lang Hames5e51a2e2016-07-22 16:11:25 +00001169 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001170 uint64_t SizeOfHeaders;
Kevin Enderby79d6c632016-10-24 21:15:11 +00001171 uint32_t cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001172 if (is64Bit()) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001173 parseHeader(*this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001174 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001175 cputype = Header64.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001176 } else {
Lang Hames697e7cd2016-12-04 01:56:10 +00001177 parseHeader(*this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001178 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001179 cputype = Header.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001180 }
Lang Hames9e964f32016-03-25 17:25:34 +00001181 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +00001182 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +00001183 SizeOfHeaders += getHeader().sizeofcmds;
1184 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001185 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +00001186 return;
1187 }
Kevin Enderby79d6c632016-10-24 21:15:11 +00001188 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1189 Err = malformedError("universal header architecture: " +
1190 Twine(UniversalIndex) + "'s cputype does not match "
1191 "object file's mach header");
1192 return;
1193 }
Kevin Enderbyd5039402016-10-31 20:29:48 +00001194 std::list<MachOElement> Elements;
1195 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001196
1197 uint32_t LoadCommandCount = getHeader().ncmds;
Lang Hames9e964f32016-03-25 17:25:34 +00001198 LoadCommandInfo Load;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001199 if (LoadCommandCount != 0) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001200 if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001201 Load = *LoadOrErr;
1202 else {
1203 Err = LoadOrErr.takeError();
1204 return;
1205 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001206 }
Lang Hames9e964f32016-03-25 17:25:34 +00001207
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001208 const char *DyldIdLoadCmd = nullptr;
Kevin Enderby90986e62016-09-26 21:11:03 +00001209 const char *FuncStartsLoadCmd = nullptr;
1210 const char *SplitInfoLoadCmd = nullptr;
1211 const char *CodeSignDrsLoadCmd = nullptr;
Kevin Enderby89baf992016-10-18 20:24:12 +00001212 const char *CodeSignLoadCmd = nullptr;
Kevin Enderby32359db2016-09-28 21:20:45 +00001213 const char *VersLoadCmd = nullptr;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001214 const char *SourceLoadCmd = nullptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001215 const char *EntryPointLoadCmd = nullptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001216 const char *EncryptLoadCmd = nullptr;
Kevin Enderby6f695822016-10-18 17:54:17 +00001217 const char *RoutinesLoadCmd = nullptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001218 const char *UnixThreadLoadCmd = nullptr;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001219 const char *TwoLevelHintsLoadCmd = nullptr;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001220 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +00001221 if (is64Bit()) {
1222 if (Load.C.cmdsize % 8 != 0) {
1223 // We have a hack here to allow 64-bit Mach-O core files to have
1224 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1225 // allowed since the macOS kernel produces them.
1226 if (getHeader().filetype != MachO::MH_CORE ||
1227 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1228 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1229 "multiple of 8");
1230 return;
1231 }
1232 }
1233 } else {
1234 if (Load.C.cmdsize % 4 != 0) {
1235 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1236 "multiple of 4");
1237 return;
1238 }
1239 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001240 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001241 if (Load.C.cmd == MachO::LC_SYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001242 if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001243 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001244 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001245 if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001246 Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001247 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001248 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001249 if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001250 "LC_DATA_IN_CODE", Elements,
1251 "data in code info")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001252 return;
Kevin Enderby9a509442015-01-27 21:28:24 +00001253 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001254 if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001255 "LC_LINKER_OPTIMIZATION_HINT",
1256 Elements, "linker optimization "
1257 "hints")))
Kevin Enderby9a509442015-01-27 21:28:24 +00001258 return;
Kevin Enderby90986e62016-09-26 21:11:03 +00001259 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001260 if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001261 "LC_FUNCTION_STARTS", Elements,
1262 "function starts data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001263 return;
1264 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001265 if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001266 "LC_SEGMENT_SPLIT_INFO", Elements,
1267 "split info data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001268 return;
1269 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001270 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001271 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1272 "code signing RDs data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001273 return;
Kevin Enderby89baf992016-10-18 20:24:12 +00001274 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001275 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001276 "LC_CODE_SIGNATURE", Elements,
1277 "code signature data")))
Kevin Enderby89baf992016-10-18 20:24:12 +00001278 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001279 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001280 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001281 "LC_DYLD_INFO", Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001282 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001283 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001284 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001285 "LC_DYLD_INFO_ONLY", Elements)))
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001286 return;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001287 } else if (Load.C.cmd == MachO::LC_UUID) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001288 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1289 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1290 "cmdsize");
1291 return;
1292 }
David Majnemer73cc6ff2014-11-13 19:48:56 +00001293 if (UuidLoadCmd) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001294 Err = malformedError("more than one LC_UUID command");
David Majnemer73cc6ff2014-11-13 19:48:56 +00001295 return;
1296 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001297 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001298 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001299 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1300 MachO::section_64>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001301 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001302 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001303 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001304 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001305 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1306 MachO::section>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001307 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001308 "LC_SEGMENT", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001309 return;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001310 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001311 if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001312 return;
1313 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001314 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001315 return;
1316 Libraries.push_back(Load.Ptr);
1317 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001318 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001319 return;
1320 Libraries.push_back(Load.Ptr);
1321 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001322 if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001323 return;
1324 Libraries.push_back(Load.Ptr);
1325 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001326 if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001327 return;
1328 Libraries.push_back(Load.Ptr);
1329 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001330 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001331 return;
Kevin Enderby980b2582014-06-05 21:21:57 +00001332 Libraries.push_back(Load.Ptr);
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001333 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001334 if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001335 return;
1336 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001337 if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001338 return;
1339 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001340 if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001341 return;
Kevin Enderby32359db2016-09-28 21:20:45 +00001342 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001343 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001344 "LC_VERSION_MIN_MACOSX")))
1345 return;
1346 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001347 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001348 "LC_VERSION_MIN_IPHONEOS")))
1349 return;
1350 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001351 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001352 "LC_VERSION_MIN_TVOS")))
1353 return;
1354 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001355 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001356 "LC_VERSION_MIN_WATCHOS")))
1357 return;
Kevin Enderbya4579c42017-01-19 17:36:31 +00001358 } else if (Load.C.cmd == MachO::LC_NOTE) {
1359 if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1360 return;
Steven Wu5b54a422017-01-23 20:07:55 +00001361 } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1362 if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1363 return;
Kevin Enderby76966bf2016-09-28 23:16:01 +00001364 } else if (Load.C.cmd == MachO::LC_RPATH) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001365 if ((Err = checkRpathCommand(*this, Load, I)))
Kevin Enderby76966bf2016-09-28 23:16:01 +00001366 return;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001367 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1368 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1369 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1370 " has incorrect cmdsize");
1371 return;
1372 }
1373 if (SourceLoadCmd) {
1374 Err = malformedError("more than one LC_SOURCE_VERSION command");
1375 return;
1376 }
1377 SourceLoadCmd = Load.Ptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001378 } else if (Load.C.cmd == MachO::LC_MAIN) {
1379 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1380 Err = malformedError("LC_MAIN command " + Twine(I) +
1381 " has incorrect cmdsize");
1382 return;
1383 }
1384 if (EntryPointLoadCmd) {
1385 Err = malformedError("more than one LC_MAIN command");
1386 return;
1387 }
1388 EntryPointLoadCmd = Load.Ptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001389 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1390 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1391 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1392 " has incorrect cmdsize");
1393 return;
1394 }
1395 MachO::encryption_info_command E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001396 getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1397 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001398 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1399 return;
1400 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1401 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1402 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1403 " has incorrect cmdsize");
1404 return;
1405 }
1406 MachO::encryption_info_command_64 E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001407 getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1408 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001409 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1410 return;
Kevin Enderby68fffa82016-10-11 21:04:39 +00001411 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001412 if ((Err = checkLinkerOptCommand(*this, Load, I)))
Kevin Enderby68fffa82016-10-11 21:04:39 +00001413 return;
Kevin Enderby2490de02016-10-17 22:09:25 +00001414 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1415 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1416 Err = malformedError("load command " + Twine(I) +
1417 " LC_SUB_FRAMEWORK cmdsize too small");
1418 return;
1419 }
1420 MachO::sub_framework_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001421 getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1422 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
Kevin Enderby2490de02016-10-17 22:09:25 +00001423 sizeof(MachO::sub_framework_command),
1424 "sub_framework_command", S.umbrella,
1425 "umbrella")))
1426 return;
1427 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1428 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1429 Err = malformedError("load command " + Twine(I) +
1430 " LC_SUB_UMBRELLA cmdsize too small");
1431 return;
1432 }
1433 MachO::sub_umbrella_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001434 getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1435 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
Kevin Enderby2490de02016-10-17 22:09:25 +00001436 sizeof(MachO::sub_umbrella_command),
1437 "sub_umbrella_command", S.sub_umbrella,
1438 "sub_umbrella")))
1439 return;
1440 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1441 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1442 Err = malformedError("load command " + Twine(I) +
1443 " LC_SUB_LIBRARY cmdsize too small");
1444 return;
1445 }
1446 MachO::sub_library_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001447 getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1448 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
Kevin Enderby2490de02016-10-17 22:09:25 +00001449 sizeof(MachO::sub_library_command),
1450 "sub_library_command", S.sub_library,
1451 "sub_library")))
1452 return;
1453 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1454 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1455 Err = malformedError("load command " + Twine(I) +
1456 " LC_SUB_CLIENT cmdsize too small");
1457 return;
1458 }
1459 MachO::sub_client_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001460 getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1461 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
Kevin Enderby2490de02016-10-17 22:09:25 +00001462 sizeof(MachO::sub_client_command),
1463 "sub_client_command", S.client, "client")))
1464 return;
Kevin Enderby6f695822016-10-18 17:54:17 +00001465 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1466 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1467 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1468 " has incorrect cmdsize");
1469 return;
1470 }
1471 if (RoutinesLoadCmd) {
1472 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1473 "command");
1474 return;
1475 }
1476 RoutinesLoadCmd = Load.Ptr;
1477 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1478 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1479 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1480 " has incorrect cmdsize");
1481 return;
1482 }
1483 if (RoutinesLoadCmd) {
1484 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1485 "command");
1486 return;
1487 }
1488 RoutinesLoadCmd = Load.Ptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001489 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001490 if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001491 return;
1492 if (UnixThreadLoadCmd) {
1493 Err = malformedError("more than one LC_UNIXTHREAD command");
1494 return;
1495 }
1496 UnixThreadLoadCmd = Load.Ptr;
1497 } else if (Load.C.cmd == MachO::LC_THREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001498 if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001499 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001500 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001501 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001502 if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001503 &TwoLevelHintsLoadCmd, Elements)))
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001504 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001505 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1506 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1507 Twine(Load.C.cmd) + " is obsolete and not "
1508 "supported");
1509 return;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001510 }
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001511 // TODO: generate a error for unknown load commands by default. But still
1512 // need work out an approach to allow or not allow unknown values like this
1513 // as an option for some uses like lldb.
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001514 if (I < LoadCommandCount - 1) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001515 if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +00001516 Load = *LoadOrErr;
1517 else {
1518 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001519 return;
1520 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001521 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001522 }
Kevin Enderby1829c682016-01-22 22:49:55 +00001523 if (!SymtabLoadCmd) {
1524 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001525 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +00001526 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +00001527 return;
1528 }
1529 } else if (DysymtabLoadCmd) {
1530 MachO::symtab_command Symtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001531 getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001532 MachO::dysymtab_command Dysymtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001533 getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001534 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001535 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001536 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001537 return;
1538 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001539 uint64_t BigSize = Dysymtab.ilocalsym;
1540 BigSize += Dysymtab.nlocalsym;
1541 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001542 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001543 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001544 return;
1545 }
1546 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001547 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001548 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001549 return;
1550 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001551 BigSize = Dysymtab.iextdefsym;
1552 BigSize += Dysymtab.nextdefsym;
1553 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001554 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +00001555 "load command extends past the end of the symbol "
1556 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001557 return;
1558 }
1559 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001560 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001561 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001562 return;
1563 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001564 BigSize = Dysymtab.iundefsym;
1565 BigSize += Dysymtab.nundefsym;
1566 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001567 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001568 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001569 return;
1570 }
1571 }
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001572 if ((getHeader().filetype == MachO::MH_DYLIB ||
1573 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1574 DyldIdLoadCmd == nullptr) {
1575 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1576 "filetype");
1577 return;
1578 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001579 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +00001580
1581 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001582}
1583
Kevin Enderby22fc0072016-11-14 20:57:04 +00001584Error MachOObjectFile::checkSymbolTable() const {
1585 uint32_t Flags = 0;
1586 if (is64Bit()) {
1587 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1588 Flags = H_64.flags;
1589 } else {
1590 MachO::mach_header H = MachOObjectFile::getHeader();
1591 Flags = H.flags;
1592 }
1593 uint8_t NType = 0;
1594 uint8_t NSect = 0;
1595 uint16_t NDesc = 0;
1596 uint32_t NStrx = 0;
1597 uint64_t NValue = 0;
1598 uint32_t SymbolIndex = 0;
1599 MachO::symtab_command S = getSymtabLoadCommand();
1600 for (const SymbolRef &Symbol : symbols()) {
1601 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1602 if (is64Bit()) {
1603 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1604 NType = STE_64.n_type;
1605 NSect = STE_64.n_sect;
1606 NDesc = STE_64.n_desc;
1607 NStrx = STE_64.n_strx;
1608 NValue = STE_64.n_value;
1609 } else {
1610 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1611 NType = STE.n_type;
1612 NType = STE.n_type;
1613 NSect = STE.n_sect;
1614 NDesc = STE.n_desc;
1615 NStrx = STE.n_strx;
1616 NValue = STE.n_value;
1617 }
1618 if ((NType & MachO::N_STAB) == 0 &&
1619 (NType & MachO::N_TYPE) == MachO::N_SECT) {
1620 if (NSect == 0 || NSect > Sections.size())
1621 return malformedError("bad section index: " + Twine((int)NSect) +
1622 " for symbol at index " + Twine(SymbolIndex));
1623 }
1624 if ((NType & MachO::N_STAB) == 0 &&
1625 (NType & MachO::N_TYPE) == MachO::N_INDR) {
1626 if (NValue >= S.strsize)
1627 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1628 "the end of string table, for N_INDR symbol at "
1629 "index " + Twine(SymbolIndex));
1630 }
1631 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1632 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1633 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1634 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1635 if (LibraryOrdinal != 0 &&
1636 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1637 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1638 LibraryOrdinal - 1 >= Libraries.size() ) {
1639 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1640 " for symbol at index " + Twine(SymbolIndex));
1641 }
1642 }
1643 if (NStrx >= S.strsize)
1644 return malformedError("bad string table index: " + Twine((int)NStrx) +
1645 " past the end of string table, for symbol at "
1646 "index " + Twine(SymbolIndex));
1647 SymbolIndex++;
1648 }
1649 return Error::success();
1650}
1651
Rafael Espindola5e812af2014-01-30 02:49:50 +00001652void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001653 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001654 sizeof(MachO::nlist_64) :
1655 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +00001656 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001657}
1658
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001659Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001660 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001661 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Michael Trentca309022018-01-03 23:28:32 +00001662 if (Entry.n_strx == 0)
1663 // A n_strx value of 0 indicates that no name is associated with a
1664 // particular symbol table entry.
1665 return StringRef();
Charles Davis8bdfafd2013-09-01 04:28:48 +00001666 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001667 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001668 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +00001669 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001670 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00001671 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001672}
1673
Rafael Espindola0e77a942014-12-10 20:46:55 +00001674unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1675 DataRefImpl DRI = Sec.getRawDataRefImpl();
Lang Hames697e7cd2016-12-04 01:56:10 +00001676 uint32_t Flags = getSectionFlags(*this, DRI);
Rafael Espindola0e77a942014-12-10 20:46:55 +00001677 return Flags & MachO::SECTION_TYPE;
1678}
1679
Rafael Espindola59128922015-06-24 18:14:41 +00001680uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1681 if (is64Bit()) {
1682 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1683 return Entry.n_value;
1684 }
1685 MachO::nlist Entry = getSymbolTableEntry(Sym);
1686 return Entry.n_value;
1687}
1688
Kevin Enderby980b2582014-06-05 21:21:57 +00001689// getIndirectName() returns the name of the alias'ed symbol who's string table
1690// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +00001691std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1692 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001693 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001694 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Rafael Espindola59128922015-06-24 18:14:41 +00001695 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1696 return object_error::parse_failed;
1697 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +00001698 if (NValue >= StringTable.size())
1699 return object_error::parse_failed;
1700 const char *Start = &StringTable.data()[NValue];
1701 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +00001702 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001703}
1704
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +00001705uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +00001706 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +00001707}
1708
Kevin Enderby931cb652016-06-24 18:24:42 +00001709Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +00001710 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001711}
1712
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001713uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +00001714 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001715 if (flags & SymbolRef::SF_Common) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001716 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001717 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001718 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001719 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001720}
1721
Rafael Espindolad7a32ea2015-06-24 10:20:30 +00001722uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001723 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001724}
1725
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001726Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001727MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001728 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001729 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001730
Rafael Espindola56f976f2013-04-18 18:08:55 +00001731 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001732 if (n_type & MachO::N_STAB)
1733 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001734
Charles Davis74ec8b02013-08-27 05:00:13 +00001735 switch (n_type & MachO::N_TYPE) {
1736 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001737 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +00001738 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001739 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001740 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001741 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001742 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +00001743 if (Sec->isData() || Sec->isBSS())
1744 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001745 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001746 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001747 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001748}
1749
Rafael Espindola20122a42014-01-31 20:57:12 +00001750uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001751 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001752
Charles Davis8bdfafd2013-09-01 04:28:48 +00001753 uint8_t MachOType = Entry.n_type;
1754 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001755
Rafael Espindola20122a42014-01-31 20:57:12 +00001756 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001757
Tim Northovereaef0742014-05-30 13:22:59 +00001758 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1759 Result |= SymbolRef::SF_Indirect;
1760
Rafael Espindolaa1356322013-11-02 05:03:24 +00001761 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001762 Result |= SymbolRef::SF_FormatSpecific;
1763
Charles Davis74ec8b02013-08-27 05:00:13 +00001764 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001765 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +00001766 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001767 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001768 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +00001769 else
1770 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001771 }
Lang Hames7e0692b2015-01-15 22:33:30 +00001772
1773 if (!(MachOType & MachO::N_PEXT))
1774 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001775 }
1776
Charles Davis74ec8b02013-08-27 05:00:13 +00001777 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +00001778 Result |= SymbolRef::SF_Weak;
1779
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001780 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1781 Result |= SymbolRef::SF_Thumb;
1782
Charles Davis74ec8b02013-08-27 05:00:13 +00001783 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001784 Result |= SymbolRef::SF_Absolute;
1785
Rafael Espindola20122a42014-01-31 20:57:12 +00001786 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001787}
1788
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001789Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +00001790MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001791 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001792 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001793
Rafael Espindola8bab8892015-08-07 23:27:14 +00001794 if (index == 0)
1795 return section_end();
1796 DataRefImpl DRI;
1797 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001798 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001799 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +00001800 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001801 }
Rafael Espindola8bab8892015-08-07 23:27:14 +00001802 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001803}
1804
Rafael Espindola6bf32212015-06-24 19:57:32 +00001805unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1806 MachO::nlist_base Entry =
Lang Hames697e7cd2016-12-04 01:56:10 +00001807 getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
Rafael Espindola6bf32212015-06-24 19:57:32 +00001808 return Entry.n_sect - 1;
1809}
1810
Rafael Espindola5e812af2014-01-30 02:49:50 +00001811void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001812 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001813}
1814
Rafael Espindola3acea392014-06-12 21:46:39 +00001815std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1816 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001817 ArrayRef<char> Raw = getSectionRawName(Sec);
1818 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +00001819 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001820}
1821
Rafael Espindola80291272014-10-08 15:28:58 +00001822uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1823 if (is64Bit())
1824 return getSection64(Sec).addr;
1825 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001826}
1827
George Rimara25d3292017-05-27 18:10:23 +00001828uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1829 return Sec.d.a;
1830}
1831
Rafael Espindola80291272014-10-08 15:28:58 +00001832uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +00001833 // In the case if a malformed Mach-O file where the section offset is past
1834 // the end of the file or some part of the section size is past the end of
1835 // the file return a size of zero or a size that covers the rest of the file
1836 // but does not extend past the end of the file.
1837 uint32_t SectOffset, SectType;
1838 uint64_t SectSize;
1839
1840 if (is64Bit()) {
1841 MachO::section_64 Sect = getSection64(Sec);
1842 SectOffset = Sect.offset;
1843 SectSize = Sect.size;
1844 SectType = Sect.flags & MachO::SECTION_TYPE;
1845 } else {
1846 MachO::section Sect = getSection(Sec);
1847 SectOffset = Sect.offset;
1848 SectSize = Sect.size;
1849 SectType = Sect.flags & MachO::SECTION_TYPE;
1850 }
1851 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1852 return SectSize;
1853 uint64_t FileSize = getData().size();
1854 if (SectOffset > FileSize)
1855 return 0;
1856 if (FileSize - SectOffset < SectSize)
1857 return FileSize - SectOffset;
1858 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001859}
1860
Rafael Espindola3acea392014-06-12 21:46:39 +00001861std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1862 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001863 uint32_t Offset;
1864 uint64_t Size;
1865
1866 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001867 MachO::section_64 Sect = getSection64(Sec);
1868 Offset = Sect.offset;
1869 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001870 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001871 MachO::section Sect = getSection(Sec);
1872 Offset = Sect.offset;
1873 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001874 }
1875
1876 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +00001877 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001878}
1879
Rafael Espindola80291272014-10-08 15:28:58 +00001880uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001881 uint32_t Align;
1882 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001883 MachO::section_64 Sect = getSection64(Sec);
1884 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001885 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001886 MachO::section Sect = getSection(Sec);
1887 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001888 }
1889
Rafael Espindola80291272014-10-08 15:28:58 +00001890 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001891}
1892
George Rimar401e4e52016-05-24 12:48:46 +00001893bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1894 return false;
1895}
1896
Rafael Espindola80291272014-10-08 15:28:58 +00001897bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001898 uint32_t Flags = getSectionFlags(*this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +00001899 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001900}
1901
Rafael Espindola80291272014-10-08 15:28:58 +00001902bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001903 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001904 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001905 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1906 !(SectionType == MachO::S_ZEROFILL ||
1907 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +00001908}
1909
Rafael Espindola80291272014-10-08 15:28:58 +00001910bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001911 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001912 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001913 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1914 (SectionType == MachO::S_ZEROFILL ||
1915 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +00001916}
1917
Rafael Espindola6bf32212015-06-24 19:57:32 +00001918unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1919 return Sec.getRawDataRefImpl().d.a;
1920}
1921
Rafael Espindola80291272014-10-08 15:28:58 +00001922bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +00001923 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +00001924 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +00001925}
1926
Steven Wuf2fe0142016-02-29 19:40:10 +00001927bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1928 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1929 StringRef SectName;
1930 if (!getSectionName(Sec, SectName))
1931 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1932 return false;
1933}
1934
Jonas Devlieghere8af23872017-09-26 14:22:35 +00001935bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
1936 if (is64Bit())
1937 return getSection64(Sec).offset == 0;
1938 return getSection(Sec).offset == 0;
1939}
1940
Rui Ueyamabc654b12013-09-27 21:47:05 +00001941relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001942 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001943 Ret.d.a = Sec.d.a;
1944 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +00001945 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +00001946}
Rafael Espindolac0406e12013-04-08 20:45:01 +00001947
Rafael Espindola56f976f2013-04-18 18:08:55 +00001948relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +00001949MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001950 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001951 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001952 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001953 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001954 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001955 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001956 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001957 }
Eric Christopher7b015c72011-04-22 03:19:48 +00001958
Rafael Espindola56f976f2013-04-18 18:08:55 +00001959 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001960 Ret.d.a = Sec.d.a;
1961 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001962 return relocation_iterator(RelocationRef(Ret, this));
1963}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001964
Kevin Enderbyabf10f22017-06-22 17:41:22 +00001965relocation_iterator MachOObjectFile::extrel_begin() const {
1966 DataRefImpl Ret;
Michael Trenta1703b12017-12-15 17:57:40 +00001967 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
Kevin Enderbyabf10f22017-06-22 17:41:22 +00001968 Ret.d.a = 0; // Would normally be a section index.
1969 Ret.d.b = 0; // Index into the external relocations
1970 return relocation_iterator(RelocationRef(Ret, this));
1971}
1972
1973relocation_iterator MachOObjectFile::extrel_end() const {
1974 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
1975 DataRefImpl Ret;
Michael Trenta1703b12017-12-15 17:57:40 +00001976 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
Kevin Enderbyabf10f22017-06-22 17:41:22 +00001977 Ret.d.a = 0; // Would normally be a section index.
1978 Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
1979 return relocation_iterator(RelocationRef(Ret, this));
1980}
1981
Michael Trenta1703b12017-12-15 17:57:40 +00001982relocation_iterator MachOObjectFile::locrel_begin() const {
1983 DataRefImpl Ret;
1984 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
1985 Ret.d.a = 1; // Would normally be a section index.
1986 Ret.d.b = 0; // Index into the local relocations
1987 return relocation_iterator(RelocationRef(Ret, this));
1988}
1989
1990relocation_iterator MachOObjectFile::locrel_end() const {
1991 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
1992 DataRefImpl Ret;
1993 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
1994 Ret.d.a = 1; // Would normally be a section index.
1995 Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
1996 return relocation_iterator(RelocationRef(Ret, this));
1997}
1998
Rafael Espindola5e812af2014-01-30 02:49:50 +00001999void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002000 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00002001}
Owen Anderson171f4852011-10-24 23:20:07 +00002002
Rafael Espindola96d071c2015-06-29 23:29:12 +00002003uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Kevin Enderbyabf10f22017-06-22 17:41:22 +00002004 assert((getHeader().filetype == MachO::MH_OBJECT ||
2005 getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
2006 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002007 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +00002008 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +00002009}
2010
Rafael Espindola806f0062013-06-05 01:33:53 +00002011symbol_iterator
2012MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002013 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00002014 if (isRelocationScattered(RE))
2015 return symbol_end();
2016
Rafael Espindola56f976f2013-04-18 18:08:55 +00002017 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
2018 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00002019 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00002020 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00002021
Charles Davis8bdfafd2013-09-01 04:28:48 +00002022 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00002023 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002024 sizeof(MachO::nlist_64) :
2025 sizeof(MachO::nlist);
2026 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00002027 DataRefImpl Sym;
Lang Hames697e7cd2016-12-04 01:56:10 +00002028 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00002029 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002030}
2031
Keno Fischerc780e8e2015-05-21 21:24:32 +00002032section_iterator
2033MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2034 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2035}
2036
Rafael Espindola99c041b2015-06-30 01:53:01 +00002037uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002038 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00002039 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002040}
2041
Rafael Espindola41bb4322015-06-30 04:08:37 +00002042void MachOObjectFile::getRelocationTypeName(
2043 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002044 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00002045 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002046
2047 unsigned Arch = this->getArch();
2048
2049 switch (Arch) {
2050 case Triple::x86: {
2051 static const char *const Table[] = {
2052 "GENERIC_RELOC_VANILLA",
2053 "GENERIC_RELOC_PAIR",
2054 "GENERIC_RELOC_SECTDIFF",
2055 "GENERIC_RELOC_PB_LA_PTR",
2056 "GENERIC_RELOC_LOCAL_SECTDIFF",
2057 "GENERIC_RELOC_TLV" };
2058
Eric Christopher13250cb2013-12-06 02:33:38 +00002059 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002060 res = "Unknown";
2061 else
2062 res = Table[RType];
2063 break;
2064 }
2065 case Triple::x86_64: {
2066 static const char *const Table[] = {
2067 "X86_64_RELOC_UNSIGNED",
2068 "X86_64_RELOC_SIGNED",
2069 "X86_64_RELOC_BRANCH",
2070 "X86_64_RELOC_GOT_LOAD",
2071 "X86_64_RELOC_GOT",
2072 "X86_64_RELOC_SUBTRACTOR",
2073 "X86_64_RELOC_SIGNED_1",
2074 "X86_64_RELOC_SIGNED_2",
2075 "X86_64_RELOC_SIGNED_4",
2076 "X86_64_RELOC_TLV" };
2077
2078 if (RType > 9)
2079 res = "Unknown";
2080 else
2081 res = Table[RType];
2082 break;
2083 }
2084 case Triple::arm: {
2085 static const char *const Table[] = {
2086 "ARM_RELOC_VANILLA",
2087 "ARM_RELOC_PAIR",
2088 "ARM_RELOC_SECTDIFF",
2089 "ARM_RELOC_LOCAL_SECTDIFF",
2090 "ARM_RELOC_PB_LA_PTR",
2091 "ARM_RELOC_BR24",
2092 "ARM_THUMB_RELOC_BR22",
2093 "ARM_THUMB_32BIT_BRANCH",
2094 "ARM_RELOC_HALF",
2095 "ARM_RELOC_HALF_SECTDIFF" };
2096
2097 if (RType > 9)
2098 res = "Unknown";
2099 else
2100 res = Table[RType];
2101 break;
2102 }
Tim Northover00ed9962014-03-29 10:18:08 +00002103 case Triple::aarch64: {
2104 static const char *const Table[] = {
2105 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2106 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2107 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2108 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2109 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2110 "ARM64_RELOC_ADDEND"
2111 };
2112
2113 if (RType >= array_lengthof(Table))
2114 res = "Unknown";
2115 else
2116 res = Table[RType];
2117 break;
2118 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00002119 case Triple::ppc: {
2120 static const char *const Table[] = {
2121 "PPC_RELOC_VANILLA",
2122 "PPC_RELOC_PAIR",
2123 "PPC_RELOC_BR14",
2124 "PPC_RELOC_BR24",
2125 "PPC_RELOC_HI16",
2126 "PPC_RELOC_LO16",
2127 "PPC_RELOC_HA16",
2128 "PPC_RELOC_LO14",
2129 "PPC_RELOC_SECTDIFF",
2130 "PPC_RELOC_PB_LA_PTR",
2131 "PPC_RELOC_HI16_SECTDIFF",
2132 "PPC_RELOC_LO16_SECTDIFF",
2133 "PPC_RELOC_HA16_SECTDIFF",
2134 "PPC_RELOC_JBSR",
2135 "PPC_RELOC_LO14_SECTDIFF",
2136 "PPC_RELOC_LOCAL_SECTDIFF" };
2137
Eric Christopher13250cb2013-12-06 02:33:38 +00002138 if (RType > 15)
2139 res = "Unknown";
2140 else
2141 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00002142 break;
2143 }
2144 case Triple::UnknownArch:
2145 res = "Unknown";
2146 break;
2147 }
2148 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00002149}
2150
Keno Fischer281b6942015-05-30 19:44:53 +00002151uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2152 MachO::any_relocation_info RE = getRelocation(Rel);
2153 return getAnyRelocationLength(RE);
2154}
2155
Kevin Enderby980b2582014-06-05 21:21:57 +00002156//
2157// guessLibraryShortName() is passed a name of a dynamic library and returns a
2158// guess on what the short name is. Then name is returned as a substring of the
2159// StringRef Name passed in. The name of the dynamic library is recognized as
2160// a framework if it has one of the two following forms:
2161// Foo.framework/Versions/A/Foo
2162// Foo.framework/Foo
2163// Where A and Foo can be any string. And may contain a trailing suffix
2164// starting with an underbar. If the Name is recognized as a framework then
2165// isFramework is set to true else it is set to false. If the Name has a
2166// suffix then Suffix is set to the substring in Name that contains the suffix
2167// else it is set to a NULL StringRef.
2168//
2169// The Name of the dynamic library is recognized as a library name if it has
2170// one of the two following forms:
2171// libFoo.A.dylib
2172// libFoo.dylib
2173// The library may have a suffix trailing the name Foo of the form:
2174// libFoo_profile.A.dylib
2175// libFoo_profile.dylib
2176//
2177// The Name of the dynamic library is also recognized as a library name if it
2178// has the following form:
2179// Foo.qtx
2180//
2181// If the Name of the dynamic library is none of the forms above then a NULL
2182// StringRef is returned.
2183//
2184StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2185 bool &isFramework,
2186 StringRef &Suffix) {
2187 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2188 size_t a, b, c, d, Idx;
2189
2190 isFramework = false;
2191 Suffix = StringRef();
2192
2193 // Pull off the last component and make Foo point to it
2194 a = Name.rfind('/');
2195 if (a == Name.npos || a == 0)
2196 goto guess_library;
2197 Foo = Name.slice(a+1, Name.npos);
2198
2199 // Look for a suffix starting with a '_'
2200 Idx = Foo.rfind('_');
2201 if (Idx != Foo.npos && Foo.size() >= 2) {
2202 Suffix = Foo.slice(Idx, Foo.npos);
2203 Foo = Foo.slice(0, Idx);
2204 }
2205
2206 // First look for the form Foo.framework/Foo
2207 b = Name.rfind('/', a);
2208 if (b == Name.npos)
2209 Idx = 0;
2210 else
2211 Idx = b+1;
2212 F = Name.slice(Idx, Idx + Foo.size());
2213 DotFramework = Name.slice(Idx + Foo.size(),
2214 Idx + Foo.size() + sizeof(".framework/")-1);
2215 if (F == Foo && DotFramework == ".framework/") {
2216 isFramework = true;
2217 return Foo;
2218 }
2219
2220 // Next look for the form Foo.framework/Versions/A/Foo
2221 if (b == Name.npos)
2222 goto guess_library;
2223 c = Name.rfind('/', b);
2224 if (c == Name.npos || c == 0)
2225 goto guess_library;
2226 V = Name.slice(c+1, Name.npos);
2227 if (!V.startswith("Versions/"))
2228 goto guess_library;
2229 d = Name.rfind('/', c);
2230 if (d == Name.npos)
2231 Idx = 0;
2232 else
2233 Idx = d+1;
2234 F = Name.slice(Idx, Idx + Foo.size());
2235 DotFramework = Name.slice(Idx + Foo.size(),
2236 Idx + Foo.size() + sizeof(".framework/")-1);
2237 if (F == Foo && DotFramework == ".framework/") {
2238 isFramework = true;
2239 return Foo;
2240 }
2241
2242guess_library:
2243 // pull off the suffix after the "." and make a point to it
2244 a = Name.rfind('.');
2245 if (a == Name.npos || a == 0)
2246 return StringRef();
2247 Dylib = Name.slice(a, Name.npos);
2248 if (Dylib != ".dylib")
2249 goto guess_qtx;
2250
2251 // First pull off the version letter for the form Foo.A.dylib if any.
2252 if (a >= 3) {
2253 Dot = Name.slice(a-2, a-1);
2254 if (Dot == ".")
2255 a = a - 2;
2256 }
2257
2258 b = Name.rfind('/', a);
2259 if (b == Name.npos)
2260 b = 0;
2261 else
2262 b = b+1;
2263 // ignore any suffix after an underbar like Foo_profile.A.dylib
2264 Idx = Name.find('_', b);
2265 if (Idx != Name.npos && Idx != b) {
2266 Lib = Name.slice(b, Idx);
2267 Suffix = Name.slice(Idx, a);
2268 }
2269 else
2270 Lib = Name.slice(b, a);
2271 // There are incorrect library names of the form:
2272 // libATS.A_profile.dylib so check for these.
2273 if (Lib.size() >= 3) {
2274 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2275 if (Dot == ".")
2276 Lib = Lib.slice(0, Lib.size()-2);
2277 }
2278 return Lib;
2279
2280guess_qtx:
2281 Qtx = Name.slice(a, Name.npos);
2282 if (Qtx != ".qtx")
2283 return StringRef();
2284 b = Name.rfind('/', a);
2285 if (b == Name.npos)
2286 Lib = Name.slice(0, a);
2287 else
2288 Lib = Name.slice(b+1, a);
2289 // There are library names of the form: QT.A.qtx so check for these.
2290 if (Lib.size() >= 3) {
2291 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2292 if (Dot == ".")
2293 Lib = Lib.slice(0, Lib.size()-2);
2294 }
2295 return Lib;
2296}
2297
2298// getLibraryShortNameByIndex() is used to get the short name of the library
2299// for an undefined symbol in a linked Mach-O binary that was linked with the
2300// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2301// It is passed the index (0 - based) of the library as translated from
2302// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00002303std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00002304 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00002305 if (Index >= Libraries.size())
2306 return object_error::parse_failed;
2307
Kevin Enderby980b2582014-06-05 21:21:57 +00002308 // If the cache of LibrariesShortNames is not built up do that first for
2309 // all the Libraries.
2310 if (LibrariesShortNames.size() == 0) {
2311 for (unsigned i = 0; i < Libraries.size(); i++) {
2312 MachO::dylib_command D =
Lang Hames697e7cd2016-12-04 01:56:10 +00002313 getStruct<MachO::dylib_command>(*this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00002314 if (D.dylib.name >= D.cmdsize)
2315 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00002316 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00002317 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00002318 if (D.dylib.name+Name.size() >= D.cmdsize)
2319 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00002320 StringRef Suffix;
2321 bool isFramework;
2322 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00002323 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00002324 LibrariesShortNames.push_back(Name);
2325 else
2326 LibrariesShortNames.push_back(shortName);
2327 }
2328 }
2329
2330 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00002331 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00002332}
2333
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00002334uint32_t MachOObjectFile::getLibraryCount() const {
2335 return Libraries.size();
2336}
2337
Rafael Espindola76ad2322015-07-06 14:55:37 +00002338section_iterator
2339MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2340 DataRefImpl Sec;
2341 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2342 return section_iterator(SectionRef(Sec, this));
2343}
2344
Peter Collingbourne435890a2016-11-22 03:38:40 +00002345basic_symbol_iterator MachOObjectFile::symbol_begin() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00002346 DataRefImpl DRI;
2347 MachO::symtab_command Symtab = getSymtabLoadCommand();
2348 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2349 return basic_symbol_iterator(SymbolRef(DRI, this));
2350
Lang Hames36072da2014-05-12 21:39:59 +00002351 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002352}
2353
Peter Collingbourne435890a2016-11-22 03:38:40 +00002354basic_symbol_iterator MachOObjectFile::symbol_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002355 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00002356 MachO::symtab_command Symtab = getSymtabLoadCommand();
2357 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002358 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00002359
Rafael Espindola75c30362013-04-24 19:47:55 +00002360 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002361 sizeof(MachO::nlist_64) :
2362 sizeof(MachO::nlist);
2363 unsigned Offset = Symtab.symoff +
2364 Symtab.nsyms * SymbolTableEntrySize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002365 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002366 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002367}
2368
Lang Hames36072da2014-05-12 21:39:59 +00002369basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00002370 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00002371 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002372 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00002373 unsigned SymbolTableEntrySize =
2374 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00002375 DataRefImpl DRI;
Lang Hames697e7cd2016-12-04 01:56:10 +00002376 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Lang Hames36072da2014-05-12 21:39:59 +00002377 DRI.p += Index * SymbolTableEntrySize;
2378 return basic_symbol_iterator(SymbolRef(DRI, this));
2379}
2380
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002381uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2382 MachO::symtab_command Symtab = getSymtabLoadCommand();
2383 if (!SymtabLoadCmd)
2384 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2385 unsigned SymbolTableEntrySize =
2386 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2387 DataRefImpl DRIstart;
Lang Hames697e7cd2016-12-04 01:56:10 +00002388 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002389 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2390 return Index;
2391}
2392
Rafael Espindolab5155a52014-02-10 20:24:04 +00002393section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002394 DataRefImpl DRI;
2395 return section_iterator(SectionRef(DRI, this));
2396}
2397
Rafael Espindolab5155a52014-02-10 20:24:04 +00002398section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002399 DataRefImpl DRI;
2400 DRI.d.a = Sections.size();
2401 return section_iterator(SectionRef(DRI, this));
2402}
2403
Rafael Espindola56f976f2013-04-18 18:08:55 +00002404uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00002405 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00002406}
2407
Rafael Espindola56f976f2013-04-18 18:08:55 +00002408StringRef MachOObjectFile::getFileFormatName() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002409 unsigned CPUType = getCPUType(*this);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002410 if (!is64Bit()) {
2411 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002412 case MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002413 return "Mach-O 32-bit i386";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002414 case MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002415 return "Mach-O arm";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002416 case MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002417 return "Mach-O 32-bit ppc";
2418 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002419 return "Mach-O 32-bit unknown";
2420 }
2421 }
2422
Rafael Espindola56f976f2013-04-18 18:08:55 +00002423 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002424 case MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002425 return "Mach-O 64-bit x86-64";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002426 case MachO::CPU_TYPE_ARM64:
Tim Northover00ed9962014-03-29 10:18:08 +00002427 return "Mach-O arm64";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002428 case MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002429 return "Mach-O 64-bit ppc64";
2430 default:
2431 return "Mach-O 64-bit unknown";
2432 }
2433}
2434
Alexey Samsonove6388e62013-06-18 15:03:28 +00002435Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2436 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002437 case MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002438 return Triple::x86;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002439 case MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002440 return Triple::x86_64;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002441 case MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002442 return Triple::arm;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002443 case MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00002444 return Triple::aarch64;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002445 case MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002446 return Triple::ppc;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002447 case MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002448 return Triple::ppc64;
2449 default:
2450 return Triple::UnknownArch;
2451 }
2452}
2453
Tim Northover9e8eb412016-04-22 23:21:13 +00002454Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
Kevin Enderby59343a92016-12-16 22:54:02 +00002455 const char **McpuDefault,
2456 const char **ArchFlag) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002457 if (McpuDefault)
2458 *McpuDefault = nullptr;
Kevin Enderby59343a92016-12-16 22:54:02 +00002459 if (ArchFlag)
2460 *ArchFlag = nullptr;
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002461
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002462 switch (CPUType) {
2463 case MachO::CPU_TYPE_I386:
2464 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2465 case MachO::CPU_SUBTYPE_I386_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002466 if (ArchFlag)
2467 *ArchFlag = "i386";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002468 return Triple("i386-apple-darwin");
2469 default:
2470 return Triple();
2471 }
2472 case MachO::CPU_TYPE_X86_64:
2473 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2474 case MachO::CPU_SUBTYPE_X86_64_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002475 if (ArchFlag)
2476 *ArchFlag = "x86_64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002477 return Triple("x86_64-apple-darwin");
2478 case MachO::CPU_SUBTYPE_X86_64_H:
Kevin Enderby59343a92016-12-16 22:54:02 +00002479 if (ArchFlag)
2480 *ArchFlag = "x86_64h";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002481 return Triple("x86_64h-apple-darwin");
2482 default:
2483 return Triple();
2484 }
2485 case MachO::CPU_TYPE_ARM:
2486 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2487 case MachO::CPU_SUBTYPE_ARM_V4T:
Kevin Enderby59343a92016-12-16 22:54:02 +00002488 if (ArchFlag)
2489 *ArchFlag = "armv4t";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002490 return Triple("armv4t-apple-darwin");
2491 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
Kevin Enderby59343a92016-12-16 22:54:02 +00002492 if (ArchFlag)
2493 *ArchFlag = "armv5e";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002494 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002495 case MachO::CPU_SUBTYPE_ARM_XSCALE:
Kevin Enderby59343a92016-12-16 22:54:02 +00002496 if (ArchFlag)
2497 *ArchFlag = "xscale";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002498 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002499 case MachO::CPU_SUBTYPE_ARM_V6:
Kevin Enderby59343a92016-12-16 22:54:02 +00002500 if (ArchFlag)
2501 *ArchFlag = "armv6";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002502 return Triple("armv6-apple-darwin");
2503 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002504 if (McpuDefault)
2505 *McpuDefault = "cortex-m0";
Kevin Enderby59343a92016-12-16 22:54:02 +00002506 if (ArchFlag)
2507 *ArchFlag = "armv6m";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002508 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002509 case MachO::CPU_SUBTYPE_ARM_V7:
Kevin Enderby59343a92016-12-16 22:54:02 +00002510 if (ArchFlag)
2511 *ArchFlag = "armv7";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002512 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002513 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002514 if (McpuDefault)
2515 *McpuDefault = "cortex-m4";
Kevin Enderby59343a92016-12-16 22:54:02 +00002516 if (ArchFlag)
2517 *ArchFlag = "armv7em";
Tim Northover9e8eb412016-04-22 23:21:13 +00002518 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002519 case MachO::CPU_SUBTYPE_ARM_V7K:
Kevin Enderby7a165752017-01-24 23:41:04 +00002520 if (McpuDefault)
2521 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002522 if (ArchFlag)
2523 *ArchFlag = "armv7k";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002524 return Triple("armv7k-apple-darwin");
2525 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002526 if (McpuDefault)
2527 *McpuDefault = "cortex-m3";
Kevin Enderby59343a92016-12-16 22:54:02 +00002528 if (ArchFlag)
2529 *ArchFlag = "armv7m";
Tim Northover9e8eb412016-04-22 23:21:13 +00002530 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002531 case MachO::CPU_SUBTYPE_ARM_V7S:
Kevin Enderby7a165752017-01-24 23:41:04 +00002532 if (McpuDefault)
2533 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002534 if (ArchFlag)
2535 *ArchFlag = "armv7s";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002536 return Triple("armv7s-apple-darwin");
2537 default:
2538 return Triple();
2539 }
2540 case MachO::CPU_TYPE_ARM64:
2541 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2542 case MachO::CPU_SUBTYPE_ARM64_ALL:
Kevin Enderbydc412cc2017-02-10 19:27:10 +00002543 if (McpuDefault)
2544 *McpuDefault = "cyclone";
Kevin Enderby59343a92016-12-16 22:54:02 +00002545 if (ArchFlag)
2546 *ArchFlag = "arm64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002547 return Triple("arm64-apple-darwin");
2548 default:
2549 return Triple();
2550 }
2551 case MachO::CPU_TYPE_POWERPC:
2552 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2553 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002554 if (ArchFlag)
2555 *ArchFlag = "ppc";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002556 return Triple("ppc-apple-darwin");
2557 default:
2558 return Triple();
2559 }
2560 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00002561 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002562 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002563 if (ArchFlag)
2564 *ArchFlag = "ppc64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002565 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002566 default:
2567 return Triple();
2568 }
2569 default:
2570 return Triple();
2571 }
2572}
2573
2574Triple MachOObjectFile::getHostArch() {
2575 return Triple(sys::getDefaultTargetTriple());
2576}
2577
Rafael Espindola72318b42014-08-08 16:30:17 +00002578bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2579 return StringSwitch<bool>(ArchFlag)
2580 .Case("i386", true)
2581 .Case("x86_64", true)
2582 .Case("x86_64h", true)
2583 .Case("armv4t", true)
2584 .Case("arm", true)
2585 .Case("armv5e", true)
2586 .Case("armv6", true)
2587 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00002588 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002589 .Case("armv7em", true)
2590 .Case("armv7k", true)
2591 .Case("armv7m", true)
2592 .Case("armv7s", true)
2593 .Case("arm64", true)
2594 .Case("ppc", true)
2595 .Case("ppc64", true)
2596 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002597}
2598
Zachary Turner260fe3e2017-12-14 22:07:03 +00002599Triple::ArchType MachOObjectFile::getArch() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002600 return getArch(getCPUType(*this));
Alexey Samsonove6388e62013-06-18 15:03:28 +00002601}
2602
Tim Northover9e8eb412016-04-22 23:21:13 +00002603Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2604 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002605}
2606
Rui Ueyamabc654b12013-09-27 21:47:05 +00002607relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002608 DataRefImpl DRI;
2609 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002610 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002611}
2612
Rui Ueyamabc654b12013-09-27 21:47:05 +00002613relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002614 DataRefImpl DRI;
2615 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002616 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002617}
2618
Kevin Enderby273ae012013-06-06 17:20:50 +00002619dice_iterator MachOObjectFile::begin_dices() const {
2620 DataRefImpl DRI;
2621 if (!DataInCodeLoadCmd)
2622 return dice_iterator(DiceRef(DRI, this));
2623
Charles Davis8bdfafd2013-09-01 04:28:48 +00002624 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
Lang Hames697e7cd2016-12-04 01:56:10 +00002625 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00002626 return dice_iterator(DiceRef(DRI, this));
2627}
2628
2629dice_iterator MachOObjectFile::end_dices() const {
2630 DataRefImpl DRI;
2631 if (!DataInCodeLoadCmd)
2632 return dice_iterator(DiceRef(DRI, this));
2633
Charles Davis8bdfafd2013-09-01 04:28:48 +00002634 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2635 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002636 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Kevin Enderby273ae012013-06-06 17:20:50 +00002637 return dice_iterator(DiceRef(DRI, this));
2638}
2639
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002640ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
2641 ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002642
2643void ExportEntry::moveToFirst() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002644 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002645 pushNode(0);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002646 if (*E)
2647 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002648 pushDownUntilBottom();
2649}
2650
2651void ExportEntry::moveToEnd() {
2652 Stack.clear();
2653 Done = true;
2654}
2655
2656bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002657 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002658 if (Done || Other.Done)
2659 return (Done == Other.Done);
2660 // Not equal if different stack sizes.
2661 if (Stack.size() != Other.Stack.size())
2662 return false;
2663 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00002664 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00002665 return false;
2666 // Equal if all nodes in both stacks match.
2667 for (unsigned i=0; i < Stack.size(); ++i) {
2668 if (Stack[i].Start != Other.Stack[i].Start)
2669 return false;
2670 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002671 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002672}
2673
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002674uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002675 unsigned Count;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002676 uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002677 Ptr += Count;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002678 if (Ptr > Trie.end())
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002679 Ptr = Trie.end();
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002680 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002681}
2682
2683StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00002684 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002685}
2686
2687uint64_t ExportEntry::flags() const {
2688 return Stack.back().Flags;
2689}
2690
2691uint64_t ExportEntry::address() const {
2692 return Stack.back().Address;
2693}
2694
2695uint64_t ExportEntry::other() const {
2696 return Stack.back().Other;
2697}
2698
2699StringRef ExportEntry::otherName() const {
2700 const char* ImportName = Stack.back().ImportName;
2701 if (ImportName)
2702 return StringRef(ImportName);
2703 return StringRef();
2704}
2705
2706uint32_t ExportEntry::nodeOffset() const {
2707 return Stack.back().Start - Trie.begin();
2708}
2709
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002710ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002711 : Start(Ptr), Current(Ptr) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002712
2713void ExportEntry::pushNode(uint64_t offset) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002714 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002715 const uint8_t *Ptr = Trie.begin() + offset;
2716 NodeState State(Ptr);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002717 const char *error;
2718 uint64_t ExportInfoSize = readULEB128(State.Current, &error);
2719 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002720 *E = malformedError("export info size " + Twine(error) +
2721 " in export trie data at node: 0x" +
2722 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002723 moveToEnd();
2724 return;
2725 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002726 State.IsExportNode = (ExportInfoSize != 0);
2727 const uint8_t* Children = State.Current + ExportInfoSize;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002728 if (Children > Trie.end()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002729 *E = malformedError(
2730 "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
2731 " in export trie data at node: 0x" + Twine::utohexstr(offset) +
2732 " too big and extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002733 moveToEnd();
2734 return;
2735 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002736 if (State.IsExportNode) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002737 const uint8_t *ExportStart = State.Current;
2738 State.Flags = readULEB128(State.Current, &error);
2739 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002740 *E = malformedError("flags " + Twine(error) +
2741 " in export trie data at node: 0x" +
2742 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002743 moveToEnd();
2744 return;
2745 }
2746 uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
2747 if (State.Flags != 0 &&
2748 (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
2749 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
2750 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002751 *E = malformedError(
2752 "unsupported exported symbol kind: " + Twine((int)Kind) +
2753 " in flags: 0x" + Twine::utohexstr(State.Flags) +
2754 " in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002755 moveToEnd();
2756 return;
2757 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002758 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2759 State.Address = 0;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002760 State.Other = readULEB128(State.Current, &error); // dylib ordinal
2761 if (error) {
2762 *E = malformedError("dylib ordinal of re-export " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002763 " in export trie data at node: 0x" +
2764 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002765 moveToEnd();
2766 return;
2767 }
2768 if (O != nullptr) {
2769 if (State.Other > O->getLibraryCount()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002770 *E = malformedError(
2771 "bad library ordinal: " + Twine((int)State.Other) + " (max " +
2772 Twine((int)O->getLibraryCount()) +
2773 ") in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002774 moveToEnd();
2775 return;
2776 }
2777 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002778 State.ImportName = reinterpret_cast<const char*>(State.Current);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002779 if (*State.ImportName == '\0') {
2780 State.Current++;
2781 } else {
2782 const uint8_t *End = State.Current + 1;
2783 if (End >= Trie.end()) {
2784 *E = malformedError("import name of re-export in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002785 "node: 0x" +
2786 Twine::utohexstr(offset) +
2787 " starts past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002788 moveToEnd();
2789 return;
2790 }
2791 while(*End != '\0' && End < Trie.end())
2792 End++;
2793 if (*End != '\0') {
2794 *E = malformedError("import name of re-export in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002795 "node: 0x" +
2796 Twine::utohexstr(offset) +
2797 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002798 moveToEnd();
2799 return;
2800 }
2801 State.Current = End + 1;
2802 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002803 } else {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002804 State.Address = readULEB128(State.Current, &error);
2805 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002806 *E = malformedError("address " + Twine(error) +
2807 " in export trie data at node: 0x" +
2808 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002809 moveToEnd();
2810 return;
2811 }
2812 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
2813 State.Other = readULEB128(State.Current, &error);
2814 if (error) {
2815 *E = malformedError("resolver of stub and resolver " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002816 " in export trie data at node: 0x" +
2817 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002818 moveToEnd();
2819 return;
2820 }
2821 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002822 }
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002823 if(ExportStart + ExportInfoSize != State.Current) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002824 *E = malformedError(
2825 "inconsistant export info size: 0x" +
2826 Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
2827 Twine::utohexstr(State.Current - ExportStart) +
2828 " in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002829 moveToEnd();
2830 return;
2831 }
2832 }
Kevin Enderby8100cde2017-07-24 20:33:41 +00002833 State.ChildCount = *Children;
2834 if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002835 *E = malformedError("byte for count of childern in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002836 "node: 0x" +
2837 Twine::utohexstr(offset) +
2838 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002839 moveToEnd();
2840 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002841 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002842 State.Current = Children + 1;
2843 State.NextChildIndex = 0;
2844 State.ParentStringLength = CumulativeString.size();
2845 Stack.push_back(State);
2846}
2847
2848void ExportEntry::pushDownUntilBottom() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002849 ErrorAsOutParameter ErrAsOutParam(E);
2850 const char *error;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002851 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2852 NodeState &Top = Stack.back();
2853 CumulativeString.resize(Top.ParentStringLength);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002854 for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002855 char C = *Top.Current;
2856 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002857 }
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002858 if (Top.Current >= Trie.end()) {
2859 *E = malformedError("edge sub-string in export trie data at node: 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002860 Twine::utohexstr(Top.Start - Trie.begin()) +
2861 " for child #" + Twine((int)Top.NextChildIndex) +
2862 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002863 moveToEnd();
2864 return;
2865 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002866 Top.Current += 1;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002867 uint64_t childNodeIndex = readULEB128(Top.Current, &error);
2868 if (error) {
2869 *E = malformedError("child node offset " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002870 " in export trie data at node: 0x" +
2871 Twine::utohexstr(Top.Start - Trie.begin()));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002872 moveToEnd();
2873 return;
2874 }
2875 for (const NodeState &node : nodes()) {
2876 if (node.Start == Trie.begin() + childNodeIndex){
2877 *E = malformedError("loop in childern in export trie data at node: 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002878 Twine::utohexstr(Top.Start - Trie.begin()) +
2879 " back to node: 0x" +
2880 Twine::utohexstr(childNodeIndex));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002881 moveToEnd();
2882 return;
2883 }
2884 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002885 Top.NextChildIndex += 1;
2886 pushNode(childNodeIndex);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002887 if (*E)
2888 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002889 }
2890 if (!Stack.back().IsExportNode) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002891 *E = malformedError("node is not an export node in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002892 "node: 0x" +
2893 Twine::utohexstr(Stack.back().Start - Trie.begin()));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002894 moveToEnd();
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002895 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002896 }
2897}
2898
2899// We have a trie data structure and need a way to walk it that is compatible
2900// with the C++ iterator model. The solution is a non-recursive depth first
2901// traversal where the iterator contains a stack of parent nodes along with a
2902// string that is the accumulation of all edge strings along the parent chain
2903// to this point.
2904//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00002905// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00002906// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002907// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002908//
2909// The algorithm for moveNext() is to keep moving down the leftmost unvisited
2910// child until hitting a node with no children (which is an export node or
2911// else the trie is malformed). On the way down, each node is pushed on the
2912// stack ivar. If there is no more ways down, it pops up one and tries to go
2913// down a sibling path until a childless node is reached.
2914void ExportEntry::moveNext() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002915 assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
2916 if (!Stack.back().IsExportNode) {
2917 *E = malformedError("node is not an export node in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002918 "node: 0x" +
2919 Twine::utohexstr(Stack.back().Start - Trie.begin()));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002920 moveToEnd();
2921 return;
2922 }
2923
2924 Stack.pop_back();
2925 while (!Stack.empty()) {
2926 NodeState &Top = Stack.back();
2927 if (Top.NextChildIndex < Top.ChildCount) {
2928 pushDownUntilBottom();
2929 // Now at the next export node.
2930 return;
2931 } else {
2932 if (Top.IsExportNode) {
2933 // This node has no children but is itself an export node.
2934 CumulativeString.resize(Top.ParentStringLength);
2935 return;
2936 }
2937 Stack.pop_back();
2938 }
2939 }
2940 Done = true;
2941}
2942
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002943iterator_range<export_iterator>
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002944MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
2945 const MachOObjectFile *O) {
2946 ExportEntry Start(&E, O, Trie);
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002947 if (Trie.empty())
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00002948 Start.moveToEnd();
2949 else
2950 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002951
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002952 ExportEntry Finish(&E, O, Trie);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002953 Finish.moveToEnd();
2954
Craig Topper15576e12015-12-06 05:08:07 +00002955 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002956}
2957
Alexander Shaposhnikove5740342017-07-29 00:30:45 +00002958iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
2959 return exports(Err, getDyldInfoExportsTrie(), this);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002960}
2961
Kevin Enderbya8d256c2017-03-20 19:46:55 +00002962MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
2963 ArrayRef<uint8_t> Bytes, bool is64Bit)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002964 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
2965 PointerSize(is64Bit ? 8 : 4) {}
Nick Kledzikac431442014-09-12 21:34:15 +00002966
2967void MachORebaseEntry::moveToFirst() {
2968 Ptr = Opcodes.begin();
2969 moveNext();
2970}
2971
2972void MachORebaseEntry::moveToEnd() {
2973 Ptr = Opcodes.end();
2974 RemainingLoopCount = 0;
2975 Done = true;
2976}
2977
2978void MachORebaseEntry::moveNext() {
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002979 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikac431442014-09-12 21:34:15 +00002980 // If in the middle of some loop, move to next rebasing in loop.
2981 SegmentOffset += AdvanceAmount;
2982 if (RemainingLoopCount) {
2983 --RemainingLoopCount;
2984 return;
2985 }
Juergen Ributzkacad12492017-03-30 19:56:50 +00002986 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
2987 // pointer size. Therefore it is possible to reach the end without ever having
2988 // seen REBASE_OPCODE_DONE.
2989 if (Ptr == Opcodes.end()) {
Nick Kledzikac431442014-09-12 21:34:15 +00002990 Done = true;
2991 return;
2992 }
2993 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002994 while (More) {
Nick Kledzikac431442014-09-12 21:34:15 +00002995 // Parse next opcode and set up next loop.
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00002996 const uint8_t *OpcodeStart = Ptr;
Nick Kledzikac431442014-09-12 21:34:15 +00002997 uint8_t Byte = *Ptr++;
2998 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
2999 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003000 uint32_t Count, Skip;
3001 const char *error = nullptr;
Nick Kledzikac431442014-09-12 21:34:15 +00003002 switch (Opcode) {
3003 case MachO::REBASE_OPCODE_DONE:
3004 More = false;
3005 Done = true;
3006 moveToEnd();
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003007 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003008 break;
3009 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
3010 RebaseType = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003011 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003012 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3013 Twine((int)RebaseType) + " for opcode at: 0x" +
3014 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3015 moveToEnd();
3016 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003017 }
Nick Kledzikac431442014-09-12 21:34:15 +00003018 DEBUG_WITH_TYPE(
3019 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003020 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3021 << "RebaseType=" << (int) RebaseType << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003022 break;
3023 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3024 SegmentIndex = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003025 SegmentOffset = readULEB128(&error);
3026 if (error) {
3027 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003028 Twine(error) + " for opcode at: 0x" +
3029 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003030 moveToEnd();
3031 return;
3032 }
3033 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3034 true);
3035 if (error) {
3036 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003037 Twine(error) + " for opcode at: 0x" +
3038 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003039 moveToEnd();
3040 return;
3041 }
Nick Kledzikac431442014-09-12 21:34:15 +00003042 DEBUG_WITH_TYPE(
3043 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003044 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3045 << "SegmentIndex=" << SegmentIndex << ", "
3046 << format("SegmentOffset=0x%06X", SegmentOffset)
3047 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003048 break;
3049 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003050 SegmentOffset += readULEB128(&error);
3051 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003052 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3053 " for opcode at: 0x" +
3054 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003055 moveToEnd();
3056 return;
3057 }
3058 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3059 true);
3060 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003061 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3062 " for opcode at: 0x" +
3063 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003064 moveToEnd();
3065 return;
3066 }
Nick Kledzikac431442014-09-12 21:34:15 +00003067 DEBUG_WITH_TYPE("mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003068 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3069 << format("SegmentOffset=0x%06X",
3070 SegmentOffset) << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003071 break;
3072 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003073 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3074 true);
3075 if (error) {
3076 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003077 Twine(error) + " for opcode at: 0x" +
3078 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003079 moveToEnd();
3080 return;
3081 }
Nick Kledzikac431442014-09-12 21:34:15 +00003082 SegmentOffset += ImmValue * PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003083 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3084 false);
3085 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003086 *E =
3087 malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3088 " (after adding immediate times the pointer size) " +
3089 Twine(error) + " for opcode at: 0x" +
3090 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003091 moveToEnd();
3092 return;
3093 }
Nick Kledzikac431442014-09-12 21:34:15 +00003094 DEBUG_WITH_TYPE("mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003095 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3096 << format("SegmentOffset=0x%06X",
3097 SegmentOffset) << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003098 break;
3099 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003100 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3101 true);
3102 if (error) {
3103 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003104 Twine(error) + " for opcode at: 0x" +
3105 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003106 moveToEnd();
3107 return;
3108 }
Nick Kledzikac431442014-09-12 21:34:15 +00003109 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003110 Skip = 0;
3111 Count = ImmValue;
3112 if (ImmValue != 0)
3113 RemainingLoopCount = ImmValue - 1;
3114 else
3115 RemainingLoopCount = 0;
3116 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3117 SegmentIndex, SegmentOffset);
3118 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003119 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3120 Twine(error) + " for opcode at: 0x" +
3121 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003122 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003123 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003124 }
Nick Kledzikac431442014-09-12 21:34:15 +00003125 DEBUG_WITH_TYPE(
3126 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003127 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3128 << format("SegmentOffset=0x%06X", SegmentOffset)
3129 << ", AdvanceAmount=" << AdvanceAmount
3130 << ", RemainingLoopCount=" << RemainingLoopCount
3131 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003132 return;
3133 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003134 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3135 true);
3136 if (error) {
3137 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003138 Twine(error) + " for opcode at: 0x" +
3139 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003140 moveToEnd();
3141 return;
3142 }
Nick Kledzikac431442014-09-12 21:34:15 +00003143 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003144 Skip = 0;
3145 Count = readULEB128(&error);
3146 if (error) {
3147 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003148 Twine(error) + " for opcode at: 0x" +
3149 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003150 moveToEnd();
3151 return;
3152 }
3153 if (Count != 0)
3154 RemainingLoopCount = Count - 1;
3155 else
3156 RemainingLoopCount = 0;
3157 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3158 SegmentIndex, SegmentOffset);
3159 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003160 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3161 Twine(error) + " for opcode at: 0x" +
3162 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003163 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003164 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003165 }
Nick Kledzikac431442014-09-12 21:34:15 +00003166 DEBUG_WITH_TYPE(
3167 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003168 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3169 << format("SegmentOffset=0x%06X", SegmentOffset)
3170 << ", AdvanceAmount=" << AdvanceAmount
3171 << ", RemainingLoopCount=" << RemainingLoopCount
3172 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003173 return;
3174 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003175 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3176 true);
3177 if (error) {
3178 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003179 Twine(error) + " for opcode at: 0x" +
3180 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003181 moveToEnd();
3182 return;
3183 }
3184 Skip = readULEB128(&error);
3185 if (error) {
3186 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003187 Twine(error) + " for opcode at: 0x" +
3188 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003189 moveToEnd();
3190 return;
3191 }
3192 AdvanceAmount = Skip + PointerSize;
3193 Count = 1;
Nick Kledzikac431442014-09-12 21:34:15 +00003194 RemainingLoopCount = 0;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003195 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3196 SegmentIndex, SegmentOffset);
3197 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003198 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3199 Twine(error) + " for opcode at: 0x" +
3200 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003201 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003202 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003203 }
Nick Kledzikac431442014-09-12 21:34:15 +00003204 DEBUG_WITH_TYPE(
3205 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003206 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3207 << format("SegmentOffset=0x%06X", SegmentOffset)
3208 << ", AdvanceAmount=" << AdvanceAmount
3209 << ", RemainingLoopCount=" << RemainingLoopCount
3210 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003211 return;
3212 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003213 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3214 true);
3215 if (error) {
3216 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003217 "ULEB " +
3218 Twine(error) + " for opcode at: 0x" +
3219 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003220 moveToEnd();
3221 return;
3222 }
3223 Count = readULEB128(&error);
3224 if (error) {
3225 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003226 "ULEB " +
3227 Twine(error) + " for opcode at: 0x" +
3228 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003229 moveToEnd();
3230 return;
3231 }
3232 if (Count != 0)
3233 RemainingLoopCount = Count - 1;
3234 else
3235 RemainingLoopCount = 0;
3236 Skip = readULEB128(&error);
3237 if (error) {
3238 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003239 "ULEB " +
3240 Twine(error) + " for opcode at: 0x" +
3241 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003242 moveToEnd();
3243 return;
3244 }
3245 AdvanceAmount = Skip + PointerSize;
3246
3247 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3248 SegmentIndex, SegmentOffset);
3249 if (error) {
3250 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003251 "ULEB " +
3252 Twine(error) + " for opcode at: 0x" +
3253 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003254 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003255 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003256 }
Nick Kledzikac431442014-09-12 21:34:15 +00003257 DEBUG_WITH_TYPE(
3258 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003259 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3260 << format("SegmentOffset=0x%06X", SegmentOffset)
3261 << ", AdvanceAmount=" << AdvanceAmount
3262 << ", RemainingLoopCount=" << RemainingLoopCount
3263 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003264 return;
3265 default:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003266 *E = malformedError("bad rebase info (bad opcode value 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003267 Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3268 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003269 moveToEnd();
3270 return;
Nick Kledzikac431442014-09-12 21:34:15 +00003271 }
3272 }
3273}
3274
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003275uint64_t MachORebaseEntry::readULEB128(const char **error) {
Nick Kledzikac431442014-09-12 21:34:15 +00003276 unsigned Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003277 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzikac431442014-09-12 21:34:15 +00003278 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003279 if (Ptr > Opcodes.end())
Nick Kledzikac431442014-09-12 21:34:15 +00003280 Ptr = Opcodes.end();
Nick Kledzikac431442014-09-12 21:34:15 +00003281 return Result;
3282}
3283
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003284int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzikac431442014-09-12 21:34:15 +00003285
3286uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3287
3288StringRef MachORebaseEntry::typeName() const {
3289 switch (RebaseType) {
3290 case MachO::REBASE_TYPE_POINTER:
3291 return "pointer";
3292 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3293 return "text abs32";
3294 case MachO::REBASE_TYPE_TEXT_PCREL32:
3295 return "text rel32";
3296 }
3297 return "unknown";
3298}
3299
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003300// For use with the SegIndex of a checked Mach-O Rebase entry
3301// to get the segment name.
3302StringRef MachORebaseEntry::segmentName() const {
3303 return O->BindRebaseSegmentName(SegmentIndex);
3304}
3305
3306// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3307// to get the section name.
3308StringRef MachORebaseEntry::sectionName() const {
3309 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3310}
3311
3312// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3313// to get the address.
3314uint64_t MachORebaseEntry::address() const {
3315 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3316}
3317
Nick Kledzikac431442014-09-12 21:34:15 +00003318bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003319#ifdef EXPENSIVE_CHECKS
Nick Kledzikac431442014-09-12 21:34:15 +00003320 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003321#else
3322 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3323#endif
Nick Kledzikac431442014-09-12 21:34:15 +00003324 return (Ptr == Other.Ptr) &&
3325 (RemainingLoopCount == Other.RemainingLoopCount) &&
3326 (Done == Other.Done);
3327}
3328
3329iterator_range<rebase_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003330MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3331 ArrayRef<uint8_t> Opcodes, bool is64) {
3332 if (O->BindRebaseSectionTable == nullptr)
3333 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3334 MachORebaseEntry Start(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003335 Start.moveToFirst();
3336
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003337 MachORebaseEntry Finish(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003338 Finish.moveToEnd();
3339
Craig Topper15576e12015-12-06 05:08:07 +00003340 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00003341}
3342
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003343iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3344 return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
Nick Kledzikac431442014-09-12 21:34:15 +00003345}
3346
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003347MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3348 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003349 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3350 PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
Nick Kledzik56ebef42014-09-16 01:41:51 +00003351
3352void MachOBindEntry::moveToFirst() {
3353 Ptr = Opcodes.begin();
3354 moveNext();
3355}
3356
3357void MachOBindEntry::moveToEnd() {
3358 Ptr = Opcodes.end();
3359 RemainingLoopCount = 0;
3360 Done = true;
3361}
3362
3363void MachOBindEntry::moveNext() {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003364 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003365 // If in the middle of some loop, move to next binding in loop.
3366 SegmentOffset += AdvanceAmount;
3367 if (RemainingLoopCount) {
3368 --RemainingLoopCount;
3369 return;
3370 }
Juergen Ributzkacad12492017-03-30 19:56:50 +00003371 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3372 // pointer size. Therefore it is possible to reach the end without ever having
3373 // seen BIND_OPCODE_DONE.
3374 if (Ptr == Opcodes.end()) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003375 Done = true;
3376 return;
3377 }
3378 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003379 while (More) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003380 // Parse next opcode and set up next loop.
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003381 const uint8_t *OpcodeStart = Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003382 uint8_t Byte = *Ptr++;
3383 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3384 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3385 int8_t SignExtended;
3386 const uint8_t *SymStart;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003387 uint32_t Count, Skip;
3388 const char *error = nullptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003389 switch (Opcode) {
3390 case MachO::BIND_OPCODE_DONE:
3391 if (TableKind == Kind::Lazy) {
3392 // Lazying bindings have a DONE opcode between entries. Need to ignore
3393 // it to advance to next entry. But need not if this is last entry.
3394 bool NotLastEntry = false;
3395 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3396 if (*P) {
3397 NotLastEntry = true;
3398 }
3399 }
3400 if (NotLastEntry)
3401 break;
3402 }
3403 More = false;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003404 moveToEnd();
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003405 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003406 break;
3407 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003408 if (TableKind == Kind::Weak) {
3409 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003410 "weak bind table for opcode at: 0x" +
3411 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003412 moveToEnd();
3413 return;
3414 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003415 Ordinal = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003416 LibraryOrdinalSet = true;
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003417 if (ImmValue > O->getLibraryCount()) {
3418 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003419 "library ordinal: " +
3420 Twine((int)ImmValue) + " (max " +
3421 Twine((int)O->getLibraryCount()) +
3422 ") for opcode at: 0x" +
3423 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003424 moveToEnd();
3425 return;
3426 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003427 DEBUG_WITH_TYPE(
3428 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003429 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3430 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003431 break;
3432 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003433 if (TableKind == Kind::Weak) {
3434 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003435 "weak bind table for opcode at: 0x" +
3436 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003437 moveToEnd();
3438 return;
3439 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003440 Ordinal = readULEB128(&error);
3441 LibraryOrdinalSet = true;
3442 if (error) {
3443 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003444 Twine(error) + " for opcode at: 0x" +
3445 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003446 moveToEnd();
3447 return;
3448 }
3449 if (Ordinal > (int)O->getLibraryCount()) {
3450 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003451 "library ordinal: " +
3452 Twine((int)Ordinal) + " (max " +
3453 Twine((int)O->getLibraryCount()) +
3454 ") for opcode at: 0x" +
3455 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003456 moveToEnd();
3457 return;
3458 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003459 DEBUG_WITH_TYPE(
3460 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003461 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3462 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003463 break;
3464 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003465 if (TableKind == Kind::Weak) {
3466 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003467 "weak bind table for opcode at: 0x" +
3468 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003469 moveToEnd();
3470 return;
3471 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003472 if (ImmValue) {
3473 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3474 Ordinal = SignExtended;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003475 if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3476 *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003477 "special ordinal: " +
3478 Twine((int)Ordinal) + " for opcode at: 0x" +
3479 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003480 moveToEnd();
3481 return;
3482 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003483 } else
3484 Ordinal = 0;
Steven Wu97e2cf82017-05-31 22:17:43 +00003485 LibraryOrdinalSet = true;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003486 DEBUG_WITH_TYPE(
3487 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003488 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3489 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003490 break;
3491 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3492 Flags = ImmValue;
3493 SymStart = Ptr;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003494 while (*Ptr && (Ptr < Opcodes.end())) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003495 ++Ptr;
3496 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003497 if (Ptr == Opcodes.end()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003498 *E = malformedError(
3499 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3500 "symbol name extends past opcodes for opcode at: 0x" +
3501 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3502 moveToEnd();
3503 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003504 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003505 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3506 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00003507 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003508 DEBUG_WITH_TYPE(
3509 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003510 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3511 << "SymbolName=" << SymbolName << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003512 if (TableKind == Kind::Weak) {
3513 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3514 return;
3515 }
3516 break;
3517 case MachO::BIND_OPCODE_SET_TYPE_IMM:
3518 BindType = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003519 if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003520 *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3521 Twine((int)ImmValue) + " for opcode at: 0x" +
3522 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3523 moveToEnd();
3524 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003525 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003526 DEBUG_WITH_TYPE(
3527 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003528 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3529 << "BindType=" << (int)BindType << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003530 break;
3531 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003532 Addend = readSLEB128(&error);
3533 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003534 *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
3535 " for opcode at: 0x" +
3536 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003537 moveToEnd();
3538 return;
3539 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003540 DEBUG_WITH_TYPE(
3541 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003542 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3543 << "Addend=" << Addend << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003544 break;
3545 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3546 SegmentIndex = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003547 SegmentOffset = readULEB128(&error);
3548 if (error) {
3549 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003550 Twine(error) + " for opcode at: 0x" +
3551 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003552 moveToEnd();
3553 return;
3554 }
3555 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3556 if (error) {
3557 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003558 Twine(error) + " for opcode at: 0x" +
3559 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003560 moveToEnd();
3561 return;
3562 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003563 DEBUG_WITH_TYPE(
3564 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003565 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3566 << "SegmentIndex=" << SegmentIndex << ", "
3567 << format("SegmentOffset=0x%06X", SegmentOffset)
3568 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003569 break;
3570 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003571 SegmentOffset += readULEB128(&error);
3572 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003573 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3574 " for opcode at: 0x" +
3575 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003576 moveToEnd();
3577 return;
3578 }
3579 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3580 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003581 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3582 " for opcode at: 0x" +
3583 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003584 moveToEnd();
3585 return;
3586 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003587 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003588 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3589 << format("SegmentOffset=0x%06X",
3590 SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003591 break;
3592 case MachO::BIND_OPCODE_DO_BIND:
3593 AdvanceAmount = PointerSize;
3594 RemainingLoopCount = 0;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003595 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3596 if (error) {
3597 *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003598 " for opcode at: 0x" +
3599 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003600 moveToEnd();
3601 return;
3602 }
3603 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003604 *E = malformedError(
3605 "for BIND_OPCODE_DO_BIND missing preceding "
3606 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3607 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003608 moveToEnd();
3609 return;
3610 }
3611 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003612 *E =
3613 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3614 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3615 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003616 moveToEnd();
3617 return;
3618 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003619 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003620 dbgs() << "BIND_OPCODE_DO_BIND: "
3621 << format("SegmentOffset=0x%06X",
3622 SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003623 return;
3624 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003625 if (TableKind == Kind::Lazy) {
3626 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003627 "lazy bind table for opcode at: 0x" +
3628 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003629 moveToEnd();
3630 return;
3631 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003632 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3633 if (error) {
3634 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003635 Twine(error) + " for opcode at: 0x" +
3636 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003637 moveToEnd();
3638 return;
3639 }
3640 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003641 *E = malformedError(
3642 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3643 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3644 "at: 0x" +
3645 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003646 moveToEnd();
3647 return;
3648 }
3649 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003650 *E = malformedError(
3651 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3652 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3653 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003654 moveToEnd();
3655 return;
3656 }
3657 AdvanceAmount = readULEB128(&error) + PointerSize;
3658 if (error) {
3659 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003660 Twine(error) + " for opcode at: 0x" +
3661 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003662 moveToEnd();
3663 return;
3664 }
3665 // Note, this is not really an error until the next bind but make no sense
3666 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3667 // bind operation.
3668 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3669 AdvanceAmount, false);
3670 if (error) {
3671 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003672 "ULEB) " +
3673 Twine(error) + " for opcode at: 0x" +
3674 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003675 moveToEnd();
3676 return;
3677 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003678 RemainingLoopCount = 0;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003679 DEBUG_WITH_TYPE(
3680 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003681 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3682 << format("SegmentOffset=0x%06X", SegmentOffset)
3683 << ", AdvanceAmount=" << AdvanceAmount
3684 << ", RemainingLoopCount=" << RemainingLoopCount
3685 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003686 return;
3687 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003688 if (TableKind == Kind::Lazy) {
3689 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003690 "allowed in lazy bind table for opcode at: 0x" +
3691 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003692 moveToEnd();
3693 return;
3694 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003695 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3696 if (error) {
3697 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003698 Twine(error) + " for opcode at: 0x" +
3699 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003700 moveToEnd();
3701 return;
3702 }
3703 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003704 *E = malformedError(
3705 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3706 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3707 "opcode at: 0x" +
3708 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003709 moveToEnd();
3710 return;
3711 }
3712 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003713 *E = malformedError(
3714 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3715 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3716 "at: 0x" +
3717 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003718 moveToEnd();
3719 return;
3720 }
Nick Kledzik3b2aa052014-10-18 01:21:02 +00003721 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003722 RemainingLoopCount = 0;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003723 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3724 AdvanceAmount, false);
3725 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003726 *E =
3727 malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3728 " (after adding immediate times the pointer size) " +
3729 Twine(error) + " for opcode at: 0x" +
3730 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003731 moveToEnd();
3732 return;
3733 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003734 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003735 dbgs()
Nick Kledzik56ebef42014-09-16 01:41:51 +00003736 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003737 << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003738 return;
3739 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003740 if (TableKind == Kind::Lazy) {
3741 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003742 "allowed in lazy bind table for opcode at: 0x" +
3743 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003744 moveToEnd();
3745 return;
3746 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003747 Count = readULEB128(&error);
3748 if (Count != 0)
3749 RemainingLoopCount = Count - 1;
3750 else
3751 RemainingLoopCount = 0;
3752 if (error) {
3753 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003754 " (count value) " +
3755 Twine(error) + " for opcode at: 0x" +
3756 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003757 moveToEnd();
3758 return;
3759 }
3760 Skip = readULEB128(&error);
3761 AdvanceAmount = Skip + PointerSize;
3762 if (error) {
3763 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003764 " (skip value) " +
3765 Twine(error) + " for opcode at: 0x" +
3766 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003767 moveToEnd();
3768 return;
3769 }
3770 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3771 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003772 *E =
3773 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3774 Twine(error) + " for opcode at: 0x" +
3775 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003776 moveToEnd();
3777 return;
3778 }
3779 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003780 *E = malformedError(
3781 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3782 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3783 "opcode at: 0x" +
3784 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003785 moveToEnd();
3786 return;
3787 }
3788 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003789 *E = malformedError(
3790 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3791 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3792 "at: 0x" +
3793 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003794 moveToEnd();
3795 return;
3796 }
3797 error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
3798 SegmentIndex, SegmentOffset);
3799 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003800 *E =
3801 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3802 Twine(error) + " for opcode at: 0x" +
3803 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003804 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003805 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003806 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003807 DEBUG_WITH_TYPE(
3808 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003809 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3810 << format("SegmentOffset=0x%06X", SegmentOffset)
3811 << ", AdvanceAmount=" << AdvanceAmount
3812 << ", RemainingLoopCount=" << RemainingLoopCount
3813 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003814 return;
3815 default:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003816 *E = malformedError("bad bind info (bad opcode value 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003817 Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3818 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003819 moveToEnd();
3820 return;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003821 }
3822 }
3823}
3824
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003825uint64_t MachOBindEntry::readULEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003826 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003827 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003828 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003829 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003830 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003831 return Result;
3832}
3833
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003834int64_t MachOBindEntry::readSLEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003835 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003836 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003837 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003838 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003839 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003840 return Result;
3841}
3842
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003843int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003844
3845uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3846
3847StringRef MachOBindEntry::typeName() const {
3848 switch (BindType) {
3849 case MachO::BIND_TYPE_POINTER:
3850 return "pointer";
3851 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3852 return "text abs32";
3853 case MachO::BIND_TYPE_TEXT_PCREL32:
3854 return "text rel32";
3855 }
3856 return "unknown";
3857}
3858
3859StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3860
3861int64_t MachOBindEntry::addend() const { return Addend; }
3862
3863uint32_t MachOBindEntry::flags() const { return Flags; }
3864
3865int MachOBindEntry::ordinal() const { return Ordinal; }
3866
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003867// For use with the SegIndex of a checked Mach-O Bind entry
3868// to get the segment name.
3869StringRef MachOBindEntry::segmentName() const {
3870 return O->BindRebaseSegmentName(SegmentIndex);
3871}
3872
3873// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3874// to get the section name.
3875StringRef MachOBindEntry::sectionName() const {
3876 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3877}
3878
3879// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3880// to get the address.
3881uint64_t MachOBindEntry::address() const {
3882 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3883}
3884
Nick Kledzik56ebef42014-09-16 01:41:51 +00003885bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003886#ifdef EXPENSIVE_CHECKS
Nick Kledzik56ebef42014-09-16 01:41:51 +00003887 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003888#else
3889 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3890#endif
Nick Kledzik56ebef42014-09-16 01:41:51 +00003891 return (Ptr == Other.Ptr) &&
3892 (RemainingLoopCount == Other.RemainingLoopCount) &&
3893 (Done == Other.Done);
3894}
3895
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003896// Build table of sections so SegIndex/SegOffset pairs can be translated.
3897BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
3898 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
3899 StringRef CurSegName;
3900 uint64_t CurSegAddress;
3901 for (const SectionRef &Section : Obj->sections()) {
3902 SectionInfo Info;
3903 Section.getName(Info.SectionName);
3904 Info.Address = Section.getAddress();
3905 Info.Size = Section.getSize();
3906 Info.SegmentName =
3907 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
3908 if (!Info.SegmentName.equals(CurSegName)) {
3909 ++CurSegIndex;
3910 CurSegName = Info.SegmentName;
3911 CurSegAddress = Info.Address;
3912 }
3913 Info.SegmentIndex = CurSegIndex - 1;
3914 Info.OffsetInSegment = Info.Address - CurSegAddress;
3915 Info.SegmentStartAddress = CurSegAddress;
3916 Sections.push_back(Info);
3917 }
3918 MaxSegIndex = CurSegIndex;
3919}
3920
3921// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003922// validate a MachOBindEntry or MachORebaseEntry.
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003923const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
3924 uint64_t SegOffset,
3925 bool endInvalid) {
3926 if (SegIndex == -1)
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003927 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003928 if (SegIndex >= MaxSegIndex)
3929 return "bad segIndex (too large)";
3930 for (const SectionInfo &SI : Sections) {
3931 if (SI.SegmentIndex != SegIndex)
3932 continue;
3933 if (SI.OffsetInSegment > SegOffset)
3934 continue;
3935 if (SegOffset > (SI.OffsetInSegment + SI.Size))
3936 continue;
3937 if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
3938 continue;
3939 return nullptr;
3940 }
3941 return "bad segOffset, too large";
3942}
3943
3944// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003945// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
3946// MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
3947// REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
3948// been already checked.
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003949const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
3950 uint8_t PointerSize,
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003951 int32_t SegIndex,
3952 uint64_t SegOffset) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003953 const SectionInfo &SI = findSection(SegIndex, SegOffset);
3954 uint64_t addr = SI.SegmentStartAddress + SegOffset;
3955 if (addr >= SI.Address + SI.Size)
3956 return "bad segOffset, too large";
3957 uint64_t i = 0;
3958 if (Count > 1)
3959 i = (Skip + PointerSize) * (Count - 1);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003960 else if (Count == 1)
3961 i = Skip + PointerSize;
3962 if (addr + i >= SI.Address + SI.Size) {
3963 // For rebase opcodes they can step from one section to another.
3964 uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
3965 const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
3966 if (error)
3967 return "bad count and skip, too large";
3968 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003969 return nullptr;
3970}
3971
3972// For use with the SegIndex of a checked Mach-O Bind or Rebase entry
3973// to get the segment name.
3974StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
3975 for (const SectionInfo &SI : Sections) {
3976 if (SI.SegmentIndex == SegIndex)
3977 return SI.SegmentName;
3978 }
3979 llvm_unreachable("invalid SegIndex");
3980}
3981
3982// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3983// to get the SectionInfo.
3984const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
3985 int32_t SegIndex, uint64_t SegOffset) {
3986 for (const SectionInfo &SI : Sections) {
3987 if (SI.SegmentIndex != SegIndex)
3988 continue;
3989 if (SI.OffsetInSegment > SegOffset)
3990 continue;
3991 if (SegOffset >= (SI.OffsetInSegment + SI.Size))
3992 continue;
3993 return SI;
3994 }
3995 llvm_unreachable("SegIndex and SegOffset not in any section");
3996}
3997
3998// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3999// entry to get the section name.
4000StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
4001 uint64_t SegOffset) {
4002 return findSection(SegIndex, SegOffset).SectionName;
4003}
4004
4005// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4006// entry to get the address.
4007uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
4008 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
4009 return SI.SegmentStartAddress + OffsetInSeg;
4010}
4011
Nick Kledzik56ebef42014-09-16 01:41:51 +00004012iterator_range<bind_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004013MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004014 ArrayRef<uint8_t> Opcodes, bool is64,
Nick Kledzik56ebef42014-09-16 01:41:51 +00004015 MachOBindEntry::Kind BKind) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004016 if (O->BindRebaseSectionTable == nullptr)
4017 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004018 MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00004019 Start.moveToFirst();
4020
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004021 MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00004022 Finish.moveToEnd();
4023
Craig Topper15576e12015-12-06 05:08:07 +00004024 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00004025}
4026
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004027iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004028 return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004029 MachOBindEntry::Kind::Regular);
4030}
4031
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004032iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004033 return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004034 MachOBindEntry::Kind::Lazy);
4035}
4036
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004037iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004038 return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004039 MachOBindEntry::Kind::Weak);
4040}
4041
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00004042MachOObjectFile::load_command_iterator
4043MachOObjectFile::begin_load_commands() const {
4044 return LoadCommands.begin();
4045}
4046
4047MachOObjectFile::load_command_iterator
4048MachOObjectFile::end_load_commands() const {
4049 return LoadCommands.end();
4050}
4051
4052iterator_range<MachOObjectFile::load_command_iterator>
4053MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00004054 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00004055}
4056
Rafael Espindola56f976f2013-04-18 18:08:55 +00004057StringRef
4058MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
4059 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
4060 return parseSegmentOrSectionName(Raw.data());
4061}
4062
4063ArrayRef<char>
4064MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00004065 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00004066 const section_base *Base =
4067 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00004068 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004069}
4070
4071ArrayRef<char>
4072MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00004073 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00004074 const section_base *Base =
4075 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00004076 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004077}
4078
4079bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00004080MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00004081 const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004082 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00004083 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00004084 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004085}
4086
Eric Christopher1d62c252013-07-22 22:25:07 +00004087unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004088 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004089 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00004090 return RE.r_word1 & 0xffffff;
4091 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004092}
4093
Eric Christopher1d62c252013-07-22 22:25:07 +00004094bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004095 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004096 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00004097 return (RE.r_word1 >> 27) & 1;
4098 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004099}
4100
Eric Christopher1d62c252013-07-22 22:25:07 +00004101bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004102 const MachO::any_relocation_info &RE) const {
4103 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004104}
4105
Eric Christopher1d62c252013-07-22 22:25:07 +00004106uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004107 const MachO::any_relocation_info &RE) const {
4108 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004109}
4110
Kevin Enderby9907d0a2014-11-04 00:43:16 +00004111uint32_t MachOObjectFile::getScatteredRelocationType(
4112 const MachO::any_relocation_info &RE) const {
4113 return (RE.r_word0 >> 24) & 0xf;
4114}
4115
Eric Christopher1d62c252013-07-22 22:25:07 +00004116unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004117 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004118 if (isRelocationScattered(RE))
4119 return getScatteredRelocationAddress(RE);
4120 return getPlainRelocationAddress(RE);
4121}
4122
Charles Davis8bdfafd2013-09-01 04:28:48 +00004123unsigned MachOObjectFile::getAnyRelocationPCRel(
4124 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004125 if (isRelocationScattered(RE))
Lang Hames697e7cd2016-12-04 01:56:10 +00004126 return getScatteredRelocationPCRel(RE);
4127 return getPlainRelocationPCRel(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004128}
4129
Eric Christopher1d62c252013-07-22 22:25:07 +00004130unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004131 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004132 if (isRelocationScattered(RE))
4133 return getScatteredRelocationLength(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00004134 return getPlainRelocationLength(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004135}
4136
4137unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00004138MachOObjectFile::getAnyRelocationType(
4139 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004140 if (isRelocationScattered(RE))
4141 return getScatteredRelocationType(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00004142 return getPlainRelocationType(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004143}
4144
Rafael Espindola52501032013-04-30 15:40:54 +00004145SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00004146MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004147 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00004148 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00004149 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00004150 unsigned SecNum = getPlainRelocationSymbolNum(RE);
4151 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
4152 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00004153 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00004154 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00004155 return SectionRef(DRI, this);
4156}
4157
Charles Davis8bdfafd2013-09-01 04:28:48 +00004158MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00004159 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00004160 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004161}
4162
Charles Davis8bdfafd2013-09-01 04:28:48 +00004163MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00004164 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00004165 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004166}
4167
Charles Davis8bdfafd2013-09-01 04:28:48 +00004168MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00004169 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004170 const char *Sec = getSectionPtr(*this, L, Index);
4171 return getStruct<MachO::section>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004172}
4173
Charles Davis8bdfafd2013-09-01 04:28:48 +00004174MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4175 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004176 const char *Sec = getSectionPtr(*this, L, Index);
4177 return getStruct<MachO::section_64>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004178}
4179
Charles Davis8bdfafd2013-09-01 04:28:48 +00004180MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00004181MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00004182 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004183 return getStruct<MachO::nlist>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004184}
4185
Charles Davis8bdfafd2013-09-01 04:28:48 +00004186MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00004187MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00004188 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004189 return getStruct<MachO::nlist_64>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004190}
4191
Charles Davis8bdfafd2013-09-01 04:28:48 +00004192MachO::linkedit_data_command
4193MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004194 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004195}
4196
Charles Davis8bdfafd2013-09-01 04:28:48 +00004197MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00004198MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004199 return getStruct<MachO::segment_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004200}
4201
Charles Davis8bdfafd2013-09-01 04:28:48 +00004202MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00004203MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004204 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004205}
4206
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00004207MachO::linker_option_command
4208MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004209 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004210}
4211
Jim Grosbach448334a2014-03-18 22:09:05 +00004212MachO::version_min_command
4213MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004214 return getStruct<MachO::version_min_command>(*this, L.Ptr);
Jim Grosbach448334a2014-03-18 22:09:05 +00004215}
4216
Kevin Enderbya4579c42017-01-19 17:36:31 +00004217MachO::note_command
4218MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
4219 return getStruct<MachO::note_command>(*this, L.Ptr);
4220}
4221
Steven Wu5b54a422017-01-23 20:07:55 +00004222MachO::build_version_command
4223MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
4224 return getStruct<MachO::build_version_command>(*this, L.Ptr);
4225}
4226
4227MachO::build_tool_version
4228MachOObjectFile::getBuildToolVersion(unsigned index) const {
4229 return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
4230}
4231
Tim Northover8f9590b2014-06-30 14:40:57 +00004232MachO::dylib_command
4233MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004234 return getStruct<MachO::dylib_command>(*this, L.Ptr);
Tim Northover8f9590b2014-06-30 14:40:57 +00004235}
4236
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004237MachO::dyld_info_command
4238MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004239 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004240}
4241
4242MachO::dylinker_command
4243MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004244 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004245}
4246
4247MachO::uuid_command
4248MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004249 return getStruct<MachO::uuid_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004250}
4251
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004252MachO::rpath_command
4253MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004254 return getStruct<MachO::rpath_command>(*this, L.Ptr);
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004255}
4256
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004257MachO::source_version_command
4258MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004259 return getStruct<MachO::source_version_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004260}
4261
4262MachO::entry_point_command
4263MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004264 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004265}
4266
Kevin Enderby0804f4672014-12-16 23:25:52 +00004267MachO::encryption_info_command
4268MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004269 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
Kevin Enderby0804f4672014-12-16 23:25:52 +00004270}
4271
Kevin Enderby57538292014-12-17 01:01:30 +00004272MachO::encryption_info_command_64
4273MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004274 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
Kevin Enderby57538292014-12-17 01:01:30 +00004275}
4276
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004277MachO::sub_framework_command
4278MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004279 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004280}
Tim Northover8f9590b2014-06-30 14:40:57 +00004281
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004282MachO::sub_umbrella_command
4283MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004284 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004285}
4286
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004287MachO::sub_library_command
4288MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004289 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004290}
4291
Kevin Enderby186eac32014-12-19 21:06:24 +00004292MachO::sub_client_command
4293MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004294 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
Kevin Enderby186eac32014-12-19 21:06:24 +00004295}
4296
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004297MachO::routines_command
4298MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004299 return getStruct<MachO::routines_command>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004300}
4301
4302MachO::routines_command_64
4303MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004304 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004305}
4306
Kevin Enderby48ef5342014-12-23 22:56:39 +00004307MachO::thread_command
4308MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004309 return getStruct<MachO::thread_command>(*this, L.Ptr);
Kevin Enderby48ef5342014-12-23 22:56:39 +00004310}
4311
Charles Davis8bdfafd2013-09-01 04:28:48 +00004312MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00004313MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00004314 uint32_t Offset;
Kevin Enderbyabf10f22017-06-22 17:41:22 +00004315 if (getHeader().filetype == MachO::MH_OBJECT) {
4316 DataRefImpl Sec;
4317 Sec.d.a = Rel.d.a;
4318 if (is64Bit()) {
4319 MachO::section_64 Sect = getSection64(Sec);
4320 Offset = Sect.reloff;
4321 } else {
4322 MachO::section Sect = getSection(Sec);
4323 Offset = Sect.reloff;
4324 }
Rafael Espindola128b8112014-04-03 23:51:28 +00004325 } else {
Kevin Enderbyabf10f22017-06-22 17:41:22 +00004326 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
Michael Trenta1703b12017-12-15 17:57:40 +00004327 if (Rel.d.a == 0)
4328 Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
4329 else
4330 Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
Rafael Espindola128b8112014-04-03 23:51:28 +00004331 }
4332
4333 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004334 getPtr(*this, Offset)) + Rel.d.b;
Rafael Espindola128b8112014-04-03 23:51:28 +00004335 return getStruct<MachO::any_relocation_info>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004336 *this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00004337}
4338
Charles Davis8bdfafd2013-09-01 04:28:48 +00004339MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00004340MachOObjectFile::getDice(DataRefImpl Rel) const {
4341 const char *P = reinterpret_cast<const char *>(Rel.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004342 return getStruct<MachO::data_in_code_entry>(*this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00004343}
4344
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004345const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00004346 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004347}
4348
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004349const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4350 assert(is64Bit());
4351 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004352}
4353
Charles Davis8bdfafd2013-09-01 04:28:48 +00004354uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4355 const MachO::dysymtab_command &DLC,
4356 unsigned Index) const {
4357 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
Lang Hames697e7cd2016-12-04 01:56:10 +00004358 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004359}
4360
Charles Davis8bdfafd2013-09-01 04:28:48 +00004361MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00004362MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4363 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004364 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
Lang Hames697e7cd2016-12-04 01:56:10 +00004365 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004366}
4367
Charles Davis8bdfafd2013-09-01 04:28:48 +00004368MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004369 if (SymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004370 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004371
4372 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4373 MachO::symtab_command Cmd;
4374 Cmd.cmd = MachO::LC_SYMTAB;
4375 Cmd.cmdsize = sizeof(MachO::symtab_command);
4376 Cmd.symoff = 0;
4377 Cmd.nsyms = 0;
4378 Cmd.stroff = 0;
4379 Cmd.strsize = 0;
4380 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004381}
4382
Charles Davis8bdfafd2013-09-01 04:28:48 +00004383MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004384 if (DysymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004385 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004386
4387 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4388 MachO::dysymtab_command Cmd;
4389 Cmd.cmd = MachO::LC_DYSYMTAB;
4390 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4391 Cmd.ilocalsym = 0;
4392 Cmd.nlocalsym = 0;
4393 Cmd.iextdefsym = 0;
4394 Cmd.nextdefsym = 0;
4395 Cmd.iundefsym = 0;
4396 Cmd.nundefsym = 0;
4397 Cmd.tocoff = 0;
4398 Cmd.ntoc = 0;
4399 Cmd.modtaboff = 0;
4400 Cmd.nmodtab = 0;
4401 Cmd.extrefsymoff = 0;
4402 Cmd.nextrefsyms = 0;
4403 Cmd.indirectsymoff = 0;
4404 Cmd.nindirectsyms = 0;
4405 Cmd.extreloff = 0;
4406 Cmd.nextrel = 0;
4407 Cmd.locreloff = 0;
4408 Cmd.nlocrel = 0;
4409 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004410}
4411
Charles Davis8bdfafd2013-09-01 04:28:48 +00004412MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00004413MachOObjectFile::getDataInCodeLoadCommand() const {
4414 if (DataInCodeLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004415 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00004416
4417 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00004418 MachO::linkedit_data_command Cmd;
4419 Cmd.cmd = MachO::LC_DATA_IN_CODE;
4420 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4421 Cmd.dataoff = 0;
4422 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00004423 return Cmd;
4424}
4425
Kevin Enderby9a509442015-01-27 21:28:24 +00004426MachO::linkedit_data_command
4427MachOObjectFile::getLinkOptHintsLoadCommand() const {
4428 if (LinkOptHintsLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004429 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
Kevin Enderby9a509442015-01-27 21:28:24 +00004430
4431 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4432 // fields.
4433 MachO::linkedit_data_command Cmd;
4434 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4435 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4436 Cmd.dataoff = 0;
4437 Cmd.datasize = 0;
4438 return Cmd;
4439}
4440
Nick Kledzikd04bc352014-08-30 00:20:14 +00004441ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004442 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004443 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004444
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004445 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004446 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004447 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004448 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00004449 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004450}
4451
4452ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004453 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004454 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004455
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004456 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004457 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004458 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004459 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004460 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004461}
4462
4463ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004464 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004465 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004466
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004467 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004468 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004469 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004470 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004471 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004472}
4473
4474ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004475 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004476 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004477
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004478 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004479 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004480 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004481 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004482 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004483}
4484
4485ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004486 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004487 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004488
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004489 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004490 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004491 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004492 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00004493 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004494}
4495
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004496ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
4497 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004498 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00004499 // Returning a pointer is fine as uuid doesn't need endian swapping.
4500 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00004501 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004502}
Nick Kledzikd04bc352014-08-30 00:20:14 +00004503
Rafael Espindola6e040c02013-04-26 20:07:33 +00004504StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004505 MachO::symtab_command S = getSymtabLoadCommand();
4506 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004507}
4508
Rafael Espindola56f976f2013-04-18 18:08:55 +00004509bool MachOObjectFile::is64Bit() const {
4510 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00004511 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004512}
4513
4514void MachOObjectFile::ReadULEB128s(uint64_t Index,
4515 SmallVectorImpl<uint64_t> &Out) const {
4516 DataExtractor extractor(ObjectFile::getData(), true, 0);
4517
4518 uint32_t offset = Index;
4519 uint64_t data = 0;
4520 while (uint64_t delta = extractor.getULEB128(&offset)) {
4521 data += delta;
4522 Out.push_back(data);
4523 }
4524}
4525
Rafael Espindolac66d7612014-08-17 19:09:37 +00004526bool MachOObjectFile::isRelocatableObject() const {
4527 return getHeader().filetype == MachO::MH_OBJECT;
4528}
4529
Lang Hamesff044b12016-03-25 23:11:52 +00004530Expected<std::unique_ptr<MachOObjectFile>>
Kevin Enderby79d6c632016-10-24 21:15:11 +00004531ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4532 uint32_t UniversalCputype,
4533 uint32_t UniversalIndex) {
Rafael Espindola48af1c22014-08-19 18:44:46 +00004534 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00004535 if (Magic == "\xFE\xED\xFA\xCE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004536 return MachOObjectFile::create(Buffer, false, false,
4537 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004538 if (Magic == "\xCE\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004539 return MachOObjectFile::create(Buffer, true, false,
4540 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004541 if (Magic == "\xFE\xED\xFA\xCF")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004542 return MachOObjectFile::create(Buffer, false, true,
4543 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004544 if (Magic == "\xCF\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004545 return MachOObjectFile::create(Buffer, true, true,
4546 UniversalCputype, UniversalIndex);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00004547 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00004548 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004549}
Wolfgang Pieb77d3e932017-06-06 01:22:34 +00004550
4551StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
4552 return StringSwitch<StringRef>(Name)
4553 .Case("debug_str_offs", "debug_str_offsets")
4554 .Default(Name);
4555}