blob: ba811071b9774766b01c263c7df3213d980e77ad [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//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Christopher7b015c72011-04-22 03:19:48 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the MachOObjectFile class, which binds the MachOObject
10// class to the generic ObjectFile wrapper.
11//
12//===----------------------------------------------------------------------===//
13
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000014#include "llvm/ADT/ArrayRef.h"
15#include "llvm/ADT/None.h"
Tim Northover00ed9962014-03-29 10:18:08 +000016#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000017#include "llvm/ADT/SmallVector.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000018#include "llvm/ADT/StringRef.h"
Rafael Espindola72318b42014-08-08 16:30:17 +000019#include "llvm/ADT/StringSwitch.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000020#include "llvm/ADT/Triple.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000021#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000022#include "llvm/BinaryFormat/MachO.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000023#include "llvm/Object/Error.h"
24#include "llvm/Object/MachO.h"
25#include "llvm/Object/ObjectFile.h"
26#include "llvm/Object/SymbolicFile.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000027#include "llvm/Support/DataExtractor.h"
Nick Kledzikac431442014-09-12 21:34:15 +000028#include "llvm/Support/Debug.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000029#include "llvm/Support/Error.h"
30#include "llvm/Support/ErrorHandling.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000031#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000032#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000033#include "llvm/Support/LEB128.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000034#include "llvm/Support/MemoryBuffer.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000035#include "llvm/Support/SwapByteOrder.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000036#include "llvm/Support/raw_ostream.h"
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000037#include <algorithm>
38#include <cassert>
39#include <cstddef>
40#include <cstdint>
Eric Christopher7b015c72011-04-22 03:19:48 +000041#include <cstring>
42#include <limits>
Kevin Enderbyd5039402016-10-31 20:29:48 +000043#include <list>
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000044#include <memory>
45#include <string>
46#include <system_error>
Eric Christopher7b015c72011-04-22 03:19:48 +000047
48using namespace llvm;
49using namespace object;
50
Artyom Skrobov7d602f72014-07-20 12:08:28 +000051namespace {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000052
Artyom Skrobov7d602f72014-07-20 12:08:28 +000053 struct section_base {
54 char sectname[16];
55 char segname[16];
56 };
Eugene Zelenko9f5094d2017-04-21 22:03:05 +000057
58} // end anonymous namespace
Rafael Espindola56f976f2013-04-18 18:08:55 +000059
Benjamin Kramer760e00b2017-08-20 15:13:39 +000060static Error malformedError(const Twine &Msg) {
61 return make_error<GenericBinaryError>("truncated or malformed object (" +
62 Msg + ")",
Kevin Enderby89134962016-05-05 23:41:05 +000063 object_error::parse_failed);
Lang Hames9e964f32016-03-25 17:25:34 +000064}
65
Alexey Samsonov9f336632015-06-04 19:45:22 +000066// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000067template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000068static T getStruct(const MachOObjectFile &O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000069 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000070 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Filipe Cabecinhas40139502015-01-15 22:52:38 +000071 report_fatal_error("Malformed MachO file.");
72
Rafael Espindola3cdeb172013-04-19 13:45:05 +000073 T Cmd;
74 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000075 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000076 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000077 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000078}
79
Alexey Samsonov9f336632015-06-04 19:45:22 +000080template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000081static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000082 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000083 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000084 return malformedError("Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000085
86 T Cmd;
87 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000088 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Alexey Samsonov9f336632015-06-04 19:45:22 +000089 MachO::swapStruct(Cmd);
90 return Cmd;
91}
92
Rafael Espindola6e040c02013-04-26 20:07:33 +000093static const char *
Lang Hames697e7cd2016-12-04 01:56:10 +000094getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
Rafael Espindola6e040c02013-04-26 20:07:33 +000095 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000096 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
97
Lang Hames697e7cd2016-12-04 01:56:10 +000098 bool Is64 = O.is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000099 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
100 sizeof(MachO::segment_command);
101 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
102 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000103
104 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +0000105 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +0000106}
107
Lang Hames697e7cd2016-12-04 01:56:10 +0000108static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
Sam Clegg675a5172018-06-04 17:01:20 +0000109 assert(Offset <= O.getData().size());
Sam Clegga81fb842018-05-30 03:37:26 +0000110 return O.getData().data() + Offset;
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');
Michael Trent76d66122019-03-11 18:29:25 +0000921 if (0xffffffff == NullPos)
922 return malformedError("load command " + Twine(LoadCommandIndex) +
923 " LC_LINKER_OPTION string #" + Twine(i) +
924 " is not NULL terminated");
Kevin Enderby68fffa82016-10-11 21:04:39 +0000925 uint32_t len = std::min(NullPos, left) + 1;
926 string += len;
927 left -= len;
928 }
929 }
930 if (L.count != i)
931 return malformedError("load command " + Twine(LoadCommandIndex) +
932 " LC_LINKER_OPTION string count " + Twine(L.count) +
933 " does not match number of strings");
934 return Error::success();
935}
936
Lang Hames697e7cd2016-12-04 01:56:10 +0000937static Error checkSubCommand(const MachOObjectFile &Obj,
Kevin Enderby2490de02016-10-17 22:09:25 +0000938 const MachOObjectFile::LoadCommandInfo &Load,
939 uint32_t LoadCommandIndex, const char *CmdName,
940 size_t SizeOfCmd, const char *CmdStructName,
941 uint32_t PathOffset, const char *PathFieldName) {
942 if (PathOffset < SizeOfCmd)
943 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
944 CmdName + " " + PathFieldName + ".offset field too "
945 "small, not past the end of the " + CmdStructName);
946 if (PathOffset >= Load.C.cmdsize)
947 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
948 CmdName + " " + PathFieldName + ".offset field "
949 "extends past the end of the load command");
950 // Make sure there is a null between the starting offset of the path and
951 // the end of the load command.
952 uint32_t i;
953 const char *P = (const char *)Load.Ptr;
954 for (i = PathOffset; i < Load.C.cmdsize; i++)
955 if (P[i] == '\0')
956 break;
957 if (i >= Load.C.cmdsize)
958 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
959 CmdName + " " + PathFieldName + " name extends past "
960 "the end of the load command");
961 return Error::success();
962}
963
Lang Hames697e7cd2016-12-04 01:56:10 +0000964static Error checkThreadCommand(const MachOObjectFile &Obj,
Kevin Enderby210030b2016-10-19 23:44:34 +0000965 const MachOObjectFile::LoadCommandInfo &Load,
966 uint32_t LoadCommandIndex,
967 const char *CmdName) {
968 if (Load.C.cmdsize < sizeof(MachO::thread_command))
969 return malformedError("load command " + Twine(LoadCommandIndex) +
970 CmdName + " cmdsize too small");
971 MachO::thread_command T =
972 getStruct<MachO::thread_command>(Obj, Load.Ptr);
973 const char *state = Load.Ptr + sizeof(MachO::thread_command);
974 const char *end = Load.Ptr + T.cmdsize;
975 uint32_t nflavor = 0;
976 uint32_t cputype = getCPUType(Obj);
977 while (state < end) {
978 if(state + sizeof(uint32_t) > end)
979 return malformedError("load command " + Twine(LoadCommandIndex) +
980 "flavor in " + CmdName + " extends past end of "
981 "command");
982 uint32_t flavor;
983 memcpy(&flavor, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000984 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000985 sys::swapByteOrder(flavor);
986 state += sizeof(uint32_t);
987
988 if(state + sizeof(uint32_t) > end)
989 return malformedError("load command " + Twine(LoadCommandIndex) +
990 " count in " + CmdName + " extends past end of "
991 "command");
992 uint32_t count;
993 memcpy(&count, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000994 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000995 sys::swapByteOrder(count);
996 state += sizeof(uint32_t);
997
Kevin Enderbyc3a035d2017-01-23 21:13:29 +0000998 if (cputype == MachO::CPU_TYPE_I386) {
999 if (flavor == MachO::x86_THREAD_STATE32) {
1000 if (count != MachO::x86_THREAD_STATE32_COUNT)
1001 return malformedError("load command " + Twine(LoadCommandIndex) +
1002 " count not x86_THREAD_STATE32_COUNT for "
1003 "flavor number " + Twine(nflavor) + " which is "
1004 "a x86_THREAD_STATE32 flavor in " + CmdName +
1005 " command");
1006 if (state + sizeof(MachO::x86_thread_state32_t) > end)
1007 return malformedError("load command " + Twine(LoadCommandIndex) +
1008 " x86_THREAD_STATE32 extends past end of "
1009 "command in " + CmdName + " command");
1010 state += sizeof(MachO::x86_thread_state32_t);
1011 } else {
1012 return malformedError("load command " + Twine(LoadCommandIndex) +
1013 " unknown flavor (" + Twine(flavor) + ") for "
1014 "flavor number " + Twine(nflavor) + " in " +
1015 CmdName + " command");
1016 }
1017 } else if (cputype == MachO::CPU_TYPE_X86_64) {
Kevin Enderby299cd892018-03-08 23:10:38 +00001018 if (flavor == MachO::x86_THREAD_STATE) {
1019 if (count != MachO::x86_THREAD_STATE_COUNT)
1020 return malformedError("load command " + Twine(LoadCommandIndex) +
1021 " count not x86_THREAD_STATE_COUNT for "
1022 "flavor number " + Twine(nflavor) + " which is "
1023 "a x86_THREAD_STATE flavor in " + CmdName +
1024 " command");
1025 if (state + sizeof(MachO::x86_thread_state_t) > end)
1026 return malformedError("load command " + Twine(LoadCommandIndex) +
1027 " x86_THREAD_STATE extends past end of "
1028 "command in " + CmdName + " command");
1029 state += sizeof(MachO::x86_thread_state_t);
1030 } else if (flavor == MachO::x86_FLOAT_STATE) {
1031 if (count != MachO::x86_FLOAT_STATE_COUNT)
1032 return malformedError("load command " + Twine(LoadCommandIndex) +
1033 " count not x86_FLOAT_STATE_COUNT for "
1034 "flavor number " + Twine(nflavor) + " which is "
1035 "a x86_FLOAT_STATE flavor in " + CmdName +
1036 " command");
1037 if (state + sizeof(MachO::x86_float_state_t) > end)
1038 return malformedError("load command " + Twine(LoadCommandIndex) +
1039 " x86_FLOAT_STATE extends past end of "
1040 "command in " + CmdName + " command");
1041 state += sizeof(MachO::x86_float_state_t);
1042 } else if (flavor == MachO::x86_EXCEPTION_STATE) {
1043 if (count != MachO::x86_EXCEPTION_STATE_COUNT)
1044 return malformedError("load command " + Twine(LoadCommandIndex) +
1045 " count not x86_EXCEPTION_STATE_COUNT for "
1046 "flavor number " + Twine(nflavor) + " which is "
1047 "a x86_EXCEPTION_STATE flavor in " + CmdName +
1048 " command");
1049 if (state + sizeof(MachO::x86_exception_state_t) > end)
1050 return malformedError("load command " + Twine(LoadCommandIndex) +
1051 " x86_EXCEPTION_STATE extends past end of "
1052 "command in " + CmdName + " command");
1053 state += sizeof(MachO::x86_exception_state_t);
1054 } else if (flavor == MachO::x86_THREAD_STATE64) {
Kevin Enderby210030b2016-10-19 23:44:34 +00001055 if (count != MachO::x86_THREAD_STATE64_COUNT)
1056 return malformedError("load command " + Twine(LoadCommandIndex) +
1057 " count not x86_THREAD_STATE64_COUNT for "
1058 "flavor number " + Twine(nflavor) + " which is "
1059 "a x86_THREAD_STATE64 flavor in " + CmdName +
1060 " command");
1061 if (state + sizeof(MachO::x86_thread_state64_t) > end)
1062 return malformedError("load command " + Twine(LoadCommandIndex) +
1063 " x86_THREAD_STATE64 extends past end of "
1064 "command in " + CmdName + " command");
1065 state += sizeof(MachO::x86_thread_state64_t);
Kevin Enderby299cd892018-03-08 23:10:38 +00001066 } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
1067 if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
1068 return malformedError("load command " + Twine(LoadCommandIndex) +
1069 " count not x86_EXCEPTION_STATE64_COUNT for "
1070 "flavor number " + Twine(nflavor) + " which is "
1071 "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
1072 " command");
1073 if (state + sizeof(MachO::x86_exception_state64_t) > end)
1074 return malformedError("load command " + Twine(LoadCommandIndex) +
1075 " x86_EXCEPTION_STATE64 extends past end of "
1076 "command in " + CmdName + " command");
1077 state += sizeof(MachO::x86_exception_state64_t);
Kevin Enderby210030b2016-10-19 23:44:34 +00001078 } else {
1079 return malformedError("load command " + Twine(LoadCommandIndex) +
1080 " unknown flavor (" + Twine(flavor) + ") for "
1081 "flavor number " + Twine(nflavor) + " in " +
1082 CmdName + " command");
1083 }
1084 } else if (cputype == MachO::CPU_TYPE_ARM) {
1085 if (flavor == MachO::ARM_THREAD_STATE) {
1086 if (count != MachO::ARM_THREAD_STATE_COUNT)
1087 return malformedError("load command " + Twine(LoadCommandIndex) +
1088 " count not ARM_THREAD_STATE_COUNT for "
1089 "flavor number " + Twine(nflavor) + " which is "
1090 "a ARM_THREAD_STATE flavor in " + CmdName +
1091 " command");
1092 if (state + sizeof(MachO::arm_thread_state32_t) > end)
1093 return malformedError("load command " + Twine(LoadCommandIndex) +
1094 " ARM_THREAD_STATE extends past end of "
1095 "command in " + CmdName + " command");
1096 state += sizeof(MachO::arm_thread_state32_t);
1097 } else {
1098 return malformedError("load command " + Twine(LoadCommandIndex) +
1099 " unknown flavor (" + Twine(flavor) + ") for "
1100 "flavor number " + Twine(nflavor) + " in " +
1101 CmdName + " command");
1102 }
Tim Northoverff6875a2019-05-14 11:25:44 +00001103 } else if (cputype == MachO::CPU_TYPE_ARM64 ||
1104 cputype == MachO::CPU_TYPE_ARM64_32) {
Kevin Enderby7747cb52016-11-03 20:51:28 +00001105 if (flavor == MachO::ARM_THREAD_STATE64) {
1106 if (count != MachO::ARM_THREAD_STATE64_COUNT)
1107 return malformedError("load command " + Twine(LoadCommandIndex) +
1108 " count not ARM_THREAD_STATE64_COUNT for "
1109 "flavor number " + Twine(nflavor) + " which is "
1110 "a ARM_THREAD_STATE64 flavor in " + CmdName +
1111 " command");
1112 if (state + sizeof(MachO::arm_thread_state64_t) > end)
1113 return malformedError("load command " + Twine(LoadCommandIndex) +
1114 " ARM_THREAD_STATE64 extends past end of "
1115 "command in " + CmdName + " command");
1116 state += sizeof(MachO::arm_thread_state64_t);
1117 } else {
1118 return malformedError("load command " + Twine(LoadCommandIndex) +
1119 " unknown flavor (" + Twine(flavor) + ") for "
1120 "flavor number " + Twine(nflavor) + " in " +
1121 CmdName + " command");
1122 }
Kevin Enderby210030b2016-10-19 23:44:34 +00001123 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1124 if (flavor == MachO::PPC_THREAD_STATE) {
1125 if (count != MachO::PPC_THREAD_STATE_COUNT)
1126 return malformedError("load command " + Twine(LoadCommandIndex) +
1127 " count not PPC_THREAD_STATE_COUNT for "
1128 "flavor number " + Twine(nflavor) + " which is "
1129 "a PPC_THREAD_STATE flavor in " + CmdName +
1130 " command");
1131 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1132 return malformedError("load command " + Twine(LoadCommandIndex) +
1133 " PPC_THREAD_STATE extends past end of "
1134 "command in " + CmdName + " command");
1135 state += sizeof(MachO::ppc_thread_state32_t);
1136 } else {
1137 return malformedError("load command " + Twine(LoadCommandIndex) +
1138 " unknown flavor (" + Twine(flavor) + ") for "
1139 "flavor number " + Twine(nflavor) + " in " +
1140 CmdName + " command");
1141 }
1142 } else {
1143 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1144 "command " + Twine(LoadCommandIndex) + " for " +
1145 CmdName + " command can't be checked");
1146 }
1147 nflavor++;
1148 }
1149 return Error::success();
1150}
1151
Lang Hames697e7cd2016-12-04 01:56:10 +00001152static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001153 const MachOObjectFile::LoadCommandInfo
1154 &Load,
1155 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001156 const char **LoadCmd,
1157 std::list<MachOElement> &Elements) {
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001158 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1159 return malformedError("load command " + Twine(LoadCommandIndex) +
1160 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1161 if (*LoadCmd != nullptr)
1162 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1163 MachO::twolevel_hints_command Hints =
1164 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
Lang Hames697e7cd2016-12-04 01:56:10 +00001165 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001166 if (Hints.offset > FileSize)
1167 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1168 Twine(LoadCommandIndex) + " extends past the end of "
1169 "the file");
1170 uint64_t BigSize = Hints.nhints;
Jessica Paquette1a81dfb2017-10-17 20:43:33 +00001171 BigSize *= sizeof(MachO::twolevel_hint);
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001172 BigSize += Hints.offset;
1173 if (BigSize > FileSize)
1174 return malformedError("offset field plus nhints times sizeof(struct "
1175 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1176 Twine(LoadCommandIndex) + " extends past the end of "
1177 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001178 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1179 sizeof(MachO::twolevel_hint),
1180 "two level hints"))
1181 return Err;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001182 *LoadCmd = Load.Ptr;
1183 return Error::success();
1184}
1185
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001186// Returns true if the libObject code does not support the load command and its
1187// contents. The cmd value it is treated as an unknown load command but with
1188// an error message that says the cmd value is obsolete.
1189static bool isLoadCommandObsolete(uint32_t cmd) {
1190 if (cmd == MachO::LC_SYMSEG ||
1191 cmd == MachO::LC_LOADFVMLIB ||
1192 cmd == MachO::LC_IDFVMLIB ||
1193 cmd == MachO::LC_IDENT ||
1194 cmd == MachO::LC_FVMFILE ||
1195 cmd == MachO::LC_PREPAGE ||
1196 cmd == MachO::LC_PREBOUND_DYLIB ||
1197 cmd == MachO::LC_TWOLEVEL_HINTS ||
1198 cmd == MachO::LC_PREBIND_CKSUM)
1199 return true;
1200 return false;
1201}
1202
Lang Hames82627642016-03-25 21:59:14 +00001203Expected<std::unique_ptr<MachOObjectFile>>
1204MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001205 bool Is64Bits, uint32_t UniversalCputype,
1206 uint32_t UniversalIndex) {
Mehdi Amini41af4302016-11-11 04:28:40 +00001207 Error Err = Error::success();
Lang Hames82627642016-03-25 21:59:14 +00001208 std::unique_ptr<MachOObjectFile> Obj(
1209 new MachOObjectFile(std::move(Object), IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001210 Is64Bits, Err, UniversalCputype,
1211 UniversalIndex));
Lang Hames82627642016-03-25 21:59:14 +00001212 if (Err)
1213 return std::move(Err);
1214 return std::move(Obj);
1215}
1216
Rafael Espindola48af1c22014-08-19 18:44:46 +00001217MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001218 bool Is64bits, Error &Err,
1219 uint32_t UniversalCputype,
1220 uint32_t UniversalIndex)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00001221 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
Lang Hames5e51a2e2016-07-22 16:11:25 +00001222 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001223 uint64_t SizeOfHeaders;
Kevin Enderby79d6c632016-10-24 21:15:11 +00001224 uint32_t cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001225 if (is64Bit()) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001226 parseHeader(*this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001227 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001228 cputype = Header64.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001229 } else {
Lang Hames697e7cd2016-12-04 01:56:10 +00001230 parseHeader(*this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001231 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001232 cputype = Header.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001233 }
Lang Hames9e964f32016-03-25 17:25:34 +00001234 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +00001235 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +00001236 SizeOfHeaders += getHeader().sizeofcmds;
1237 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001238 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +00001239 return;
1240 }
Kevin Enderby79d6c632016-10-24 21:15:11 +00001241 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1242 Err = malformedError("universal header architecture: " +
1243 Twine(UniversalIndex) + "'s cputype does not match "
1244 "object file's mach header");
1245 return;
1246 }
Kevin Enderbyd5039402016-10-31 20:29:48 +00001247 std::list<MachOElement> Elements;
1248 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001249
1250 uint32_t LoadCommandCount = getHeader().ncmds;
Lang Hames9e964f32016-03-25 17:25:34 +00001251 LoadCommandInfo Load;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001252 if (LoadCommandCount != 0) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001253 if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001254 Load = *LoadOrErr;
1255 else {
1256 Err = LoadOrErr.takeError();
1257 return;
1258 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001259 }
Lang Hames9e964f32016-03-25 17:25:34 +00001260
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001261 const char *DyldIdLoadCmd = nullptr;
Kevin Enderby90986e62016-09-26 21:11:03 +00001262 const char *FuncStartsLoadCmd = nullptr;
1263 const char *SplitInfoLoadCmd = nullptr;
1264 const char *CodeSignDrsLoadCmd = nullptr;
Kevin Enderby89baf992016-10-18 20:24:12 +00001265 const char *CodeSignLoadCmd = nullptr;
Kevin Enderby32359db2016-09-28 21:20:45 +00001266 const char *VersLoadCmd = nullptr;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001267 const char *SourceLoadCmd = nullptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001268 const char *EntryPointLoadCmd = nullptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001269 const char *EncryptLoadCmd = nullptr;
Kevin Enderby6f695822016-10-18 17:54:17 +00001270 const char *RoutinesLoadCmd = nullptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001271 const char *UnixThreadLoadCmd = nullptr;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001272 const char *TwoLevelHintsLoadCmd = nullptr;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001273 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +00001274 if (is64Bit()) {
1275 if (Load.C.cmdsize % 8 != 0) {
1276 // We have a hack here to allow 64-bit Mach-O core files to have
1277 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1278 // allowed since the macOS kernel produces them.
1279 if (getHeader().filetype != MachO::MH_CORE ||
1280 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1281 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1282 "multiple of 8");
1283 return;
1284 }
1285 }
1286 } else {
1287 if (Load.C.cmdsize % 4 != 0) {
1288 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1289 "multiple of 4");
1290 return;
1291 }
1292 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001293 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001294 if (Load.C.cmd == MachO::LC_SYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001295 if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001296 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001297 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001298 if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001299 Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001300 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001301 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001302 if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001303 "LC_DATA_IN_CODE", Elements,
1304 "data in code info")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001305 return;
Kevin Enderby9a509442015-01-27 21:28:24 +00001306 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001307 if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001308 "LC_LINKER_OPTIMIZATION_HINT",
1309 Elements, "linker optimization "
1310 "hints")))
Kevin Enderby9a509442015-01-27 21:28:24 +00001311 return;
Kevin Enderby90986e62016-09-26 21:11:03 +00001312 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001313 if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001314 "LC_FUNCTION_STARTS", Elements,
1315 "function starts data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001316 return;
1317 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001318 if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001319 "LC_SEGMENT_SPLIT_INFO", Elements,
1320 "split info data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001321 return;
1322 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001323 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001324 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1325 "code signing RDs data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001326 return;
Kevin Enderby89baf992016-10-18 20:24:12 +00001327 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001328 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001329 "LC_CODE_SIGNATURE", Elements,
1330 "code signature data")))
Kevin Enderby89baf992016-10-18 20:24:12 +00001331 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001332 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001333 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001334 "LC_DYLD_INFO", Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001335 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001336 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001337 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001338 "LC_DYLD_INFO_ONLY", Elements)))
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001339 return;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001340 } else if (Load.C.cmd == MachO::LC_UUID) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001341 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1342 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1343 "cmdsize");
1344 return;
1345 }
David Majnemer73cc6ff2014-11-13 19:48:56 +00001346 if (UuidLoadCmd) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001347 Err = malformedError("more than one LC_UUID command");
David Majnemer73cc6ff2014-11-13 19:48:56 +00001348 return;
1349 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001350 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001351 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001352 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1353 MachO::section_64>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001354 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001355 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001356 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001357 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001358 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1359 MachO::section>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001360 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001361 "LC_SEGMENT", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001362 return;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001363 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001364 if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001365 return;
1366 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001367 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001368 return;
1369 Libraries.push_back(Load.Ptr);
1370 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001371 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001372 return;
1373 Libraries.push_back(Load.Ptr);
1374 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001375 if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001376 return;
1377 Libraries.push_back(Load.Ptr);
1378 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001379 if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001380 return;
1381 Libraries.push_back(Load.Ptr);
1382 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001383 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001384 return;
Kevin Enderby980b2582014-06-05 21:21:57 +00001385 Libraries.push_back(Load.Ptr);
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001386 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001387 if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001388 return;
1389 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001390 if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001391 return;
1392 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001393 if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001394 return;
Kevin Enderby32359db2016-09-28 21:20:45 +00001395 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001396 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001397 "LC_VERSION_MIN_MACOSX")))
1398 return;
1399 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001400 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001401 "LC_VERSION_MIN_IPHONEOS")))
1402 return;
1403 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001404 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001405 "LC_VERSION_MIN_TVOS")))
1406 return;
1407 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001408 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001409 "LC_VERSION_MIN_WATCHOS")))
1410 return;
Kevin Enderbya4579c42017-01-19 17:36:31 +00001411 } else if (Load.C.cmd == MachO::LC_NOTE) {
1412 if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1413 return;
Steven Wu5b54a422017-01-23 20:07:55 +00001414 } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1415 if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1416 return;
Kevin Enderby76966bf2016-09-28 23:16:01 +00001417 } else if (Load.C.cmd == MachO::LC_RPATH) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001418 if ((Err = checkRpathCommand(*this, Load, I)))
Kevin Enderby76966bf2016-09-28 23:16:01 +00001419 return;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001420 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1421 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1422 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1423 " has incorrect cmdsize");
1424 return;
1425 }
1426 if (SourceLoadCmd) {
1427 Err = malformedError("more than one LC_SOURCE_VERSION command");
1428 return;
1429 }
1430 SourceLoadCmd = Load.Ptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001431 } else if (Load.C.cmd == MachO::LC_MAIN) {
1432 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1433 Err = malformedError("LC_MAIN command " + Twine(I) +
1434 " has incorrect cmdsize");
1435 return;
1436 }
1437 if (EntryPointLoadCmd) {
1438 Err = malformedError("more than one LC_MAIN command");
1439 return;
1440 }
1441 EntryPointLoadCmd = Load.Ptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001442 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1443 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1444 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1445 " has incorrect cmdsize");
1446 return;
1447 }
1448 MachO::encryption_info_command E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001449 getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1450 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001451 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1452 return;
1453 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1454 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1455 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1456 " has incorrect cmdsize");
1457 return;
1458 }
1459 MachO::encryption_info_command_64 E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001460 getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1461 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001462 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1463 return;
Kevin Enderby68fffa82016-10-11 21:04:39 +00001464 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001465 if ((Err = checkLinkerOptCommand(*this, Load, I)))
Kevin Enderby68fffa82016-10-11 21:04:39 +00001466 return;
Kevin Enderby2490de02016-10-17 22:09:25 +00001467 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1468 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1469 Err = malformedError("load command " + Twine(I) +
1470 " LC_SUB_FRAMEWORK cmdsize too small");
1471 return;
1472 }
1473 MachO::sub_framework_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001474 getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1475 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
Kevin Enderby2490de02016-10-17 22:09:25 +00001476 sizeof(MachO::sub_framework_command),
1477 "sub_framework_command", S.umbrella,
1478 "umbrella")))
1479 return;
1480 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1481 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1482 Err = malformedError("load command " + Twine(I) +
1483 " LC_SUB_UMBRELLA cmdsize too small");
1484 return;
1485 }
1486 MachO::sub_umbrella_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001487 getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1488 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
Kevin Enderby2490de02016-10-17 22:09:25 +00001489 sizeof(MachO::sub_umbrella_command),
1490 "sub_umbrella_command", S.sub_umbrella,
1491 "sub_umbrella")))
1492 return;
1493 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1494 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1495 Err = malformedError("load command " + Twine(I) +
1496 " LC_SUB_LIBRARY cmdsize too small");
1497 return;
1498 }
1499 MachO::sub_library_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001500 getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1501 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
Kevin Enderby2490de02016-10-17 22:09:25 +00001502 sizeof(MachO::sub_library_command),
1503 "sub_library_command", S.sub_library,
1504 "sub_library")))
1505 return;
1506 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1507 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1508 Err = malformedError("load command " + Twine(I) +
1509 " LC_SUB_CLIENT cmdsize too small");
1510 return;
1511 }
1512 MachO::sub_client_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001513 getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1514 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
Kevin Enderby2490de02016-10-17 22:09:25 +00001515 sizeof(MachO::sub_client_command),
1516 "sub_client_command", S.client, "client")))
1517 return;
Kevin Enderby6f695822016-10-18 17:54:17 +00001518 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1519 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1520 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1521 " has incorrect cmdsize");
1522 return;
1523 }
1524 if (RoutinesLoadCmd) {
1525 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1526 "command");
1527 return;
1528 }
1529 RoutinesLoadCmd = Load.Ptr;
1530 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1531 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1532 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1533 " has incorrect cmdsize");
1534 return;
1535 }
1536 if (RoutinesLoadCmd) {
1537 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1538 "command");
1539 return;
1540 }
1541 RoutinesLoadCmd = Load.Ptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001542 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001543 if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001544 return;
1545 if (UnixThreadLoadCmd) {
1546 Err = malformedError("more than one LC_UNIXTHREAD command");
1547 return;
1548 }
1549 UnixThreadLoadCmd = Load.Ptr;
1550 } else if (Load.C.cmd == MachO::LC_THREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001551 if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001552 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001553 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001554 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001555 if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001556 &TwoLevelHintsLoadCmd, Elements)))
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001557 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001558 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1559 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1560 Twine(Load.C.cmd) + " is obsolete and not "
1561 "supported");
1562 return;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001563 }
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001564 // TODO: generate a error for unknown load commands by default. But still
1565 // need work out an approach to allow or not allow unknown values like this
1566 // as an option for some uses like lldb.
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001567 if (I < LoadCommandCount - 1) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001568 if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +00001569 Load = *LoadOrErr;
1570 else {
1571 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001572 return;
1573 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001574 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001575 }
Kevin Enderby1829c682016-01-22 22:49:55 +00001576 if (!SymtabLoadCmd) {
1577 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001578 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +00001579 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +00001580 return;
1581 }
1582 } else if (DysymtabLoadCmd) {
1583 MachO::symtab_command Symtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001584 getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001585 MachO::dysymtab_command Dysymtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001586 getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001587 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001588 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001589 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001590 return;
1591 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001592 uint64_t BigSize = Dysymtab.ilocalsym;
1593 BigSize += Dysymtab.nlocalsym;
1594 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001595 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001596 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001597 return;
1598 }
Francis Visoiu Mistrih7690af42018-09-04 16:31:48 +00001599 if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {
Francis Visoiu Mistrih2d3f01c2018-09-04 16:31:53 +00001600 Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001601 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001602 return;
1603 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001604 BigSize = Dysymtab.iextdefsym;
1605 BigSize += Dysymtab.nextdefsym;
1606 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001607 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +00001608 "load command extends past the end of the symbol "
1609 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001610 return;
1611 }
1612 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Francis Visoiu Mistrih2d3f01c2018-09-04 16:31:53 +00001613 Err = malformedError("iundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001614 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001615 return;
1616 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001617 BigSize = Dysymtab.iundefsym;
1618 BigSize += Dysymtab.nundefsym;
1619 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001620 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001621 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001622 return;
1623 }
1624 }
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001625 if ((getHeader().filetype == MachO::MH_DYLIB ||
1626 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1627 DyldIdLoadCmd == nullptr) {
1628 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1629 "filetype");
1630 return;
1631 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001632 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +00001633
1634 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001635}
1636
Kevin Enderby22fc0072016-11-14 20:57:04 +00001637Error MachOObjectFile::checkSymbolTable() const {
1638 uint32_t Flags = 0;
1639 if (is64Bit()) {
1640 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1641 Flags = H_64.flags;
1642 } else {
1643 MachO::mach_header H = MachOObjectFile::getHeader();
1644 Flags = H.flags;
1645 }
1646 uint8_t NType = 0;
1647 uint8_t NSect = 0;
1648 uint16_t NDesc = 0;
1649 uint32_t NStrx = 0;
1650 uint64_t NValue = 0;
1651 uint32_t SymbolIndex = 0;
1652 MachO::symtab_command S = getSymtabLoadCommand();
1653 for (const SymbolRef &Symbol : symbols()) {
1654 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1655 if (is64Bit()) {
1656 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1657 NType = STE_64.n_type;
1658 NSect = STE_64.n_sect;
1659 NDesc = STE_64.n_desc;
1660 NStrx = STE_64.n_strx;
1661 NValue = STE_64.n_value;
1662 } else {
1663 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1664 NType = STE.n_type;
Kevin Enderby22fc0072016-11-14 20:57:04 +00001665 NSect = STE.n_sect;
1666 NDesc = STE.n_desc;
1667 NStrx = STE.n_strx;
1668 NValue = STE.n_value;
1669 }
Michael Trent7dcfac62019-02-23 06:19:56 +00001670 if ((NType & MachO::N_STAB) == 0) {
1671 if ((NType & MachO::N_TYPE) == MachO::N_SECT) {
1672 if (NSect == 0 || NSect > Sections.size())
1673 return malformedError("bad section index: " + Twine((int)NSect) +
1674 " for symbol at index " + Twine(SymbolIndex));
Kevin Enderby22fc0072016-11-14 20:57:04 +00001675 }
Michael Trent7dcfac62019-02-23 06:19:56 +00001676 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
1677 if (NValue >= S.strsize)
1678 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1679 "the end of string table, for N_INDR symbol at "
1680 "index " + Twine(SymbolIndex));
1681 }
1682 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1683 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1684 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1685 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1686 if (LibraryOrdinal != 0 &&
1687 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1688 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1689 LibraryOrdinal - 1 >= Libraries.size() ) {
1690 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1691 " for symbol at index " + Twine(SymbolIndex));
1692 }
1693 }
Kevin Enderby22fc0072016-11-14 20:57:04 +00001694 }
1695 if (NStrx >= S.strsize)
1696 return malformedError("bad string table index: " + Twine((int)NStrx) +
1697 " past the end of string table, for symbol at "
1698 "index " + Twine(SymbolIndex));
1699 SymbolIndex++;
1700 }
1701 return Error::success();
1702}
1703
Rafael Espindola5e812af2014-01-30 02:49:50 +00001704void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001705 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001706 sizeof(MachO::nlist_64) :
1707 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +00001708 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001709}
1710
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001711Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001712 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001713 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Michael Trentca309022018-01-03 23:28:32 +00001714 if (Entry.n_strx == 0)
1715 // A n_strx value of 0 indicates that no name is associated with a
1716 // particular symbol table entry.
1717 return StringRef();
Charles Davis8bdfafd2013-09-01 04:28:48 +00001718 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001719 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001720 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +00001721 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001722 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00001723 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001724}
1725
Rafael Espindola0e77a942014-12-10 20:46:55 +00001726unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1727 DataRefImpl DRI = Sec.getRawDataRefImpl();
Lang Hames697e7cd2016-12-04 01:56:10 +00001728 uint32_t Flags = getSectionFlags(*this, DRI);
Rafael Espindola0e77a942014-12-10 20:46:55 +00001729 return Flags & MachO::SECTION_TYPE;
1730}
1731
Rafael Espindola59128922015-06-24 18:14:41 +00001732uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1733 if (is64Bit()) {
1734 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1735 return Entry.n_value;
1736 }
1737 MachO::nlist Entry = getSymbolTableEntry(Sym);
1738 return Entry.n_value;
1739}
1740
Kevin Enderby980b2582014-06-05 21:21:57 +00001741// getIndirectName() returns the name of the alias'ed symbol who's string table
1742// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +00001743std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1744 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001745 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001746 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Rafael Espindola59128922015-06-24 18:14:41 +00001747 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1748 return object_error::parse_failed;
1749 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +00001750 if (NValue >= StringTable.size())
1751 return object_error::parse_failed;
1752 const char *Start = &StringTable.data()[NValue];
1753 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +00001754 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001755}
1756
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +00001757uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +00001758 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +00001759}
1760
Kevin Enderby931cb652016-06-24 18:24:42 +00001761Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +00001762 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001763}
1764
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001765uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +00001766 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001767 if (flags & SymbolRef::SF_Common) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001768 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001769 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001770 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001771 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001772}
1773
Rafael Espindolad7a32ea2015-06-24 10:20:30 +00001774uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001775 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001776}
1777
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001778Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001779MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001780 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001781 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001782
Rafael Espindola56f976f2013-04-18 18:08:55 +00001783 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001784 if (n_type & MachO::N_STAB)
1785 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001786
Charles Davis74ec8b02013-08-27 05:00:13 +00001787 switch (n_type & MachO::N_TYPE) {
1788 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001789 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +00001790 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001791 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001792 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001793 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001794 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +00001795 if (Sec->isData() || Sec->isBSS())
1796 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001797 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001798 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001799 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001800}
1801
Rafael Espindola20122a42014-01-31 20:57:12 +00001802uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001803 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001804
Charles Davis8bdfafd2013-09-01 04:28:48 +00001805 uint8_t MachOType = Entry.n_type;
1806 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001807
Rafael Espindola20122a42014-01-31 20:57:12 +00001808 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001809
Tim Northovereaef0742014-05-30 13:22:59 +00001810 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1811 Result |= SymbolRef::SF_Indirect;
1812
Rafael Espindolaa1356322013-11-02 05:03:24 +00001813 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001814 Result |= SymbolRef::SF_FormatSpecific;
1815
Charles Davis74ec8b02013-08-27 05:00:13 +00001816 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001817 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +00001818 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001819 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001820 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +00001821 else
1822 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001823 }
Lang Hames7e0692b2015-01-15 22:33:30 +00001824
1825 if (!(MachOType & MachO::N_PEXT))
1826 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001827 }
1828
Charles Davis74ec8b02013-08-27 05:00:13 +00001829 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +00001830 Result |= SymbolRef::SF_Weak;
1831
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001832 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1833 Result |= SymbolRef::SF_Thumb;
1834
Charles Davis74ec8b02013-08-27 05:00:13 +00001835 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001836 Result |= SymbolRef::SF_Absolute;
1837
Rafael Espindola20122a42014-01-31 20:57:12 +00001838 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001839}
1840
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001841Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +00001842MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001843 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001844 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001845
Rafael Espindola8bab8892015-08-07 23:27:14 +00001846 if (index == 0)
1847 return section_end();
1848 DataRefImpl DRI;
1849 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001850 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001851 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +00001852 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001853 }
Rafael Espindola8bab8892015-08-07 23:27:14 +00001854 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001855}
1856
Rafael Espindola6bf32212015-06-24 19:57:32 +00001857unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1858 MachO::nlist_base Entry =
Lang Hames697e7cd2016-12-04 01:56:10 +00001859 getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
Rafael Espindola6bf32212015-06-24 19:57:32 +00001860 return Entry.n_sect - 1;
1861}
1862
Rafael Espindola5e812af2014-01-30 02:49:50 +00001863void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001864 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001865}
1866
Fangrui Song8be28cd2019-05-02 10:32:03 +00001867Expected<StringRef> MachOObjectFile::getSectionName(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001868 ArrayRef<char> Raw = getSectionRawName(Sec);
Fangrui Song8be28cd2019-05-02 10:32:03 +00001869 return parseSegmentOrSectionName(Raw.data());
Rafael Espindola56f976f2013-04-18 18:08:55 +00001870}
1871
Rafael Espindola80291272014-10-08 15:28:58 +00001872uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1873 if (is64Bit())
1874 return getSection64(Sec).addr;
1875 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001876}
1877
George Rimara25d3292017-05-27 18:10:23 +00001878uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1879 return Sec.d.a;
1880}
1881
Rafael Espindola80291272014-10-08 15:28:58 +00001882uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +00001883 // In the case if a malformed Mach-O file where the section offset is past
1884 // the end of the file or some part of the section size is past the end of
1885 // the file return a size of zero or a size that covers the rest of the file
1886 // but does not extend past the end of the file.
1887 uint32_t SectOffset, SectType;
1888 uint64_t SectSize;
1889
1890 if (is64Bit()) {
1891 MachO::section_64 Sect = getSection64(Sec);
1892 SectOffset = Sect.offset;
1893 SectSize = Sect.size;
1894 SectType = Sect.flags & MachO::SECTION_TYPE;
1895 } else {
1896 MachO::section Sect = getSection(Sec);
1897 SectOffset = Sect.offset;
1898 SectSize = Sect.size;
1899 SectType = Sect.flags & MachO::SECTION_TYPE;
1900 }
1901 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1902 return SectSize;
1903 uint64_t FileSize = getData().size();
1904 if (SectOffset > FileSize)
1905 return 0;
1906 if (FileSize - SectOffset < SectSize)
1907 return FileSize - SectOffset;
1908 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001909}
1910
Fangrui Songe1cb2c02019-05-14 04:22:51 +00001911Expected<ArrayRef<uint8_t>>
1912MachOObjectFile::getSectionContents(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001913 uint32_t Offset;
1914 uint64_t Size;
1915
1916 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001917 MachO::section_64 Sect = getSection64(Sec);
1918 Offset = Sect.offset;
1919 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001920 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001921 MachO::section Sect = getSection(Sec);
1922 Offset = Sect.offset;
1923 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001924 }
1925
Fangrui Songe1cb2c02019-05-14 04:22:51 +00001926 return arrayRefFromStringRef(getData().substr(Offset, Size));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001927}
1928
Rafael Espindola80291272014-10-08 15:28:58 +00001929uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001930 uint32_t Align;
1931 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001932 MachO::section_64 Sect = getSection64(Sec);
1933 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001934 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001935 MachO::section Sect = getSection(Sec);
1936 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001937 }
1938
Rafael Espindola80291272014-10-08 15:28:58 +00001939 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001940}
1941
Paul Semelb98f5042018-07-11 10:00:29 +00001942Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
1943 if (SectionIndex < 1 || SectionIndex > Sections.size())
1944 return malformedError("bad section index: " + Twine((int)SectionIndex));
1945
1946 DataRefImpl DRI;
1947 DRI.d.a = SectionIndex - 1;
1948 return SectionRef(DRI, this);
1949}
1950
1951Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
1952 StringRef SecName;
1953 for (const SectionRef &Section : sections()) {
1954 if (std::error_code E = Section.getName(SecName))
1955 return errorCodeToError(E);
1956 if (SecName == SectionName) {
1957 return Section;
1958 }
1959 }
1960 return errorCodeToError(object_error::parse_failed);
1961}
1962
George Rimar401e4e52016-05-24 12:48:46 +00001963bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1964 return false;
1965}
1966
Rafael Espindola80291272014-10-08 15:28:58 +00001967bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001968 uint32_t Flags = getSectionFlags(*this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +00001969 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001970}
1971
Rafael Espindola80291272014-10-08 15:28:58 +00001972bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001973 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001974 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001975 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1976 !(SectionType == MachO::S_ZEROFILL ||
1977 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +00001978}
1979
Rafael Espindola80291272014-10-08 15:28:58 +00001980bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001981 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001982 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001983 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1984 (SectionType == MachO::S_ZEROFILL ||
1985 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +00001986}
1987
Rafael Espindola6bf32212015-06-24 19:57:32 +00001988unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1989 return Sec.getRawDataRefImpl().d.a;
1990}
1991
Rafael Espindola80291272014-10-08 15:28:58 +00001992bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Francis Visoiu Mistrih18346822018-04-19 17:02:57 +00001993 uint32_t Flags = getSectionFlags(*this, Sec);
1994 unsigned SectionType = Flags & MachO::SECTION_TYPE;
1995 return SectionType == MachO::S_ZEROFILL ||
1996 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindolac2413f52013-04-09 14:49:08 +00001997}
1998
Steven Wuf2fe0142016-02-29 19:40:10 +00001999bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
2000 StringRef SegmentName = getSectionFinalSegmentName(Sec);
Fangrui Song8be28cd2019-05-02 10:32:03 +00002001 if (Expected<StringRef> NameOrErr = getSectionName(Sec))
2002 return (SegmentName == "__LLVM" && *NameOrErr == "__bitcode");
Steven Wuf2fe0142016-02-29 19:40:10 +00002003 return false;
2004}
2005
Jonas Devlieghere8af23872017-09-26 14:22:35 +00002006bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
2007 if (is64Bit())
2008 return getSection64(Sec).offset == 0;
2009 return getSection(Sec).offset == 0;
2010}
2011
Rui Ueyamabc654b12013-09-27 21:47:05 +00002012relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00002013 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00002014 Ret.d.a = Sec.d.a;
2015 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +00002016 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +00002017}
Rafael Espindolac0406e12013-04-08 20:45:01 +00002018
Rafael Espindola56f976f2013-04-18 18:08:55 +00002019relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +00002020MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00002021 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002022 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002023 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002024 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002025 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002026 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002027 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002028 }
Eric Christopher7b015c72011-04-22 03:19:48 +00002029
Rafael Espindola56f976f2013-04-18 18:08:55 +00002030 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00002031 Ret.d.a = Sec.d.a;
2032 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002033 return relocation_iterator(RelocationRef(Ret, this));
2034}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00002035
Kevin Enderbyabf10f22017-06-22 17:41:22 +00002036relocation_iterator MachOObjectFile::extrel_begin() const {
2037 DataRefImpl Ret;
Michael Trenta1703b12017-12-15 17:57:40 +00002038 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
Kevin Enderbyabf10f22017-06-22 17:41:22 +00002039 Ret.d.a = 0; // Would normally be a section index.
2040 Ret.d.b = 0; // Index into the external relocations
2041 return relocation_iterator(RelocationRef(Ret, this));
2042}
2043
2044relocation_iterator MachOObjectFile::extrel_end() const {
2045 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2046 DataRefImpl Ret;
Michael Trenta1703b12017-12-15 17:57:40 +00002047 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
Kevin Enderbyabf10f22017-06-22 17:41:22 +00002048 Ret.d.a = 0; // Would normally be a section index.
2049 Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
2050 return relocation_iterator(RelocationRef(Ret, this));
2051}
2052
Michael Trenta1703b12017-12-15 17:57:40 +00002053relocation_iterator MachOObjectFile::locrel_begin() const {
2054 DataRefImpl Ret;
2055 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2056 Ret.d.a = 1; // Would normally be a section index.
2057 Ret.d.b = 0; // Index into the local relocations
2058 return relocation_iterator(RelocationRef(Ret, this));
2059}
2060
2061relocation_iterator MachOObjectFile::locrel_end() const {
2062 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2063 DataRefImpl Ret;
2064 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2065 Ret.d.a = 1; // Would normally be a section index.
2066 Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
2067 return relocation_iterator(RelocationRef(Ret, this));
2068}
2069
Rafael Espindola5e812af2014-01-30 02:49:50 +00002070void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002071 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00002072}
Owen Anderson171f4852011-10-24 23:20:07 +00002073
Rafael Espindola96d071c2015-06-29 23:29:12 +00002074uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Kevin Enderbyabf10f22017-06-22 17:41:22 +00002075 assert((getHeader().filetype == MachO::MH_OBJECT ||
2076 getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
2077 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002078 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +00002079 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +00002080}
2081
Rafael Espindola806f0062013-06-05 01:33:53 +00002082symbol_iterator
2083MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002084 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00002085 if (isRelocationScattered(RE))
2086 return symbol_end();
2087
Rafael Espindola56f976f2013-04-18 18:08:55 +00002088 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
2089 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00002090 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00002091 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00002092
Charles Davis8bdfafd2013-09-01 04:28:48 +00002093 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00002094 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002095 sizeof(MachO::nlist_64) :
2096 sizeof(MachO::nlist);
2097 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00002098 DataRefImpl Sym;
Lang Hames697e7cd2016-12-04 01:56:10 +00002099 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00002100 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002101}
2102
Keno Fischerc780e8e2015-05-21 21:24:32 +00002103section_iterator
2104MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2105 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2106}
2107
Rafael Espindola99c041b2015-06-30 01:53:01 +00002108uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002109 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00002110 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002111}
2112
Rafael Espindola41bb4322015-06-30 04:08:37 +00002113void MachOObjectFile::getRelocationTypeName(
2114 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002115 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00002116 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002117
2118 unsigned Arch = this->getArch();
2119
2120 switch (Arch) {
2121 case Triple::x86: {
2122 static const char *const Table[] = {
2123 "GENERIC_RELOC_VANILLA",
2124 "GENERIC_RELOC_PAIR",
2125 "GENERIC_RELOC_SECTDIFF",
2126 "GENERIC_RELOC_PB_LA_PTR",
2127 "GENERIC_RELOC_LOCAL_SECTDIFF",
2128 "GENERIC_RELOC_TLV" };
2129
Eric Christopher13250cb2013-12-06 02:33:38 +00002130 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002131 res = "Unknown";
2132 else
2133 res = Table[RType];
2134 break;
2135 }
2136 case Triple::x86_64: {
2137 static const char *const Table[] = {
2138 "X86_64_RELOC_UNSIGNED",
2139 "X86_64_RELOC_SIGNED",
2140 "X86_64_RELOC_BRANCH",
2141 "X86_64_RELOC_GOT_LOAD",
2142 "X86_64_RELOC_GOT",
2143 "X86_64_RELOC_SUBTRACTOR",
2144 "X86_64_RELOC_SIGNED_1",
2145 "X86_64_RELOC_SIGNED_2",
2146 "X86_64_RELOC_SIGNED_4",
2147 "X86_64_RELOC_TLV" };
2148
2149 if (RType > 9)
2150 res = "Unknown";
2151 else
2152 res = Table[RType];
2153 break;
2154 }
2155 case Triple::arm: {
2156 static const char *const Table[] = {
2157 "ARM_RELOC_VANILLA",
2158 "ARM_RELOC_PAIR",
2159 "ARM_RELOC_SECTDIFF",
2160 "ARM_RELOC_LOCAL_SECTDIFF",
2161 "ARM_RELOC_PB_LA_PTR",
2162 "ARM_RELOC_BR24",
2163 "ARM_THUMB_RELOC_BR22",
2164 "ARM_THUMB_32BIT_BRANCH",
2165 "ARM_RELOC_HALF",
2166 "ARM_RELOC_HALF_SECTDIFF" };
2167
2168 if (RType > 9)
2169 res = "Unknown";
2170 else
2171 res = Table[RType];
2172 break;
2173 }
Tim Northoverff6875a2019-05-14 11:25:44 +00002174 case Triple::aarch64:
2175 case Triple::aarch64_32: {
Tim Northover00ed9962014-03-29 10:18:08 +00002176 static const char *const Table[] = {
2177 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2178 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2179 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2180 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2181 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2182 "ARM64_RELOC_ADDEND"
2183 };
2184
2185 if (RType >= array_lengthof(Table))
2186 res = "Unknown";
2187 else
2188 res = Table[RType];
2189 break;
2190 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00002191 case Triple::ppc: {
2192 static const char *const Table[] = {
2193 "PPC_RELOC_VANILLA",
2194 "PPC_RELOC_PAIR",
2195 "PPC_RELOC_BR14",
2196 "PPC_RELOC_BR24",
2197 "PPC_RELOC_HI16",
2198 "PPC_RELOC_LO16",
2199 "PPC_RELOC_HA16",
2200 "PPC_RELOC_LO14",
2201 "PPC_RELOC_SECTDIFF",
2202 "PPC_RELOC_PB_LA_PTR",
2203 "PPC_RELOC_HI16_SECTDIFF",
2204 "PPC_RELOC_LO16_SECTDIFF",
2205 "PPC_RELOC_HA16_SECTDIFF",
2206 "PPC_RELOC_JBSR",
2207 "PPC_RELOC_LO14_SECTDIFF",
2208 "PPC_RELOC_LOCAL_SECTDIFF" };
2209
Eric Christopher13250cb2013-12-06 02:33:38 +00002210 if (RType > 15)
2211 res = "Unknown";
2212 else
2213 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00002214 break;
2215 }
2216 case Triple::UnknownArch:
2217 res = "Unknown";
2218 break;
2219 }
2220 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00002221}
2222
Keno Fischer281b6942015-05-30 19:44:53 +00002223uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2224 MachO::any_relocation_info RE = getRelocation(Rel);
2225 return getAnyRelocationLength(RE);
2226}
2227
Kevin Enderby980b2582014-06-05 21:21:57 +00002228//
2229// guessLibraryShortName() is passed a name of a dynamic library and returns a
2230// guess on what the short name is. Then name is returned as a substring of the
2231// StringRef Name passed in. The name of the dynamic library is recognized as
2232// a framework if it has one of the two following forms:
2233// Foo.framework/Versions/A/Foo
2234// Foo.framework/Foo
2235// Where A and Foo can be any string. And may contain a trailing suffix
2236// starting with an underbar. If the Name is recognized as a framework then
2237// isFramework is set to true else it is set to false. If the Name has a
2238// suffix then Suffix is set to the substring in Name that contains the suffix
2239// else it is set to a NULL StringRef.
2240//
2241// The Name of the dynamic library is recognized as a library name if it has
2242// one of the two following forms:
2243// libFoo.A.dylib
2244// libFoo.dylib
Michael Trentf4c902b2019-01-24 20:59:44 +00002245//
Kevin Enderby980b2582014-06-05 21:21:57 +00002246// The library may have a suffix trailing the name Foo of the form:
2247// libFoo_profile.A.dylib
2248// libFoo_profile.dylib
Michael Trentf4c902b2019-01-24 20:59:44 +00002249// These dyld image suffixes are separated from the short name by a '_'
2250// character. Because the '_' character is commonly used to separate words in
2251// filenames guessLibraryShortName() cannot reliably separate a dylib's short
2252// name from an arbitrary image suffix; imagine if both the short name and the
2253// suffix contains an '_' character! To better deal with this ambiguity,
2254// guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
2255// Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
2256// guessing incorrectly.
Kevin Enderby980b2582014-06-05 21:21:57 +00002257//
2258// The Name of the dynamic library is also recognized as a library name if it
2259// has the following form:
2260// Foo.qtx
2261//
2262// If the Name of the dynamic library is none of the forms above then a NULL
2263// StringRef is returned.
Kevin Enderby980b2582014-06-05 21:21:57 +00002264StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2265 bool &isFramework,
2266 StringRef &Suffix) {
2267 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2268 size_t a, b, c, d, Idx;
2269
2270 isFramework = false;
2271 Suffix = StringRef();
2272
2273 // Pull off the last component and make Foo point to it
2274 a = Name.rfind('/');
2275 if (a == Name.npos || a == 0)
2276 goto guess_library;
2277 Foo = Name.slice(a+1, Name.npos);
2278
2279 // Look for a suffix starting with a '_'
2280 Idx = Foo.rfind('_');
2281 if (Idx != Foo.npos && Foo.size() >= 2) {
2282 Suffix = Foo.slice(Idx, Foo.npos);
Michael Trentf4c902b2019-01-24 20:59:44 +00002283 if (Suffix != "_debug" && Suffix != "_profile")
2284 Suffix = StringRef();
2285 else
2286 Foo = Foo.slice(0, Idx);
Kevin Enderby980b2582014-06-05 21:21:57 +00002287 }
2288
2289 // First look for the form Foo.framework/Foo
2290 b = Name.rfind('/', a);
2291 if (b == Name.npos)
2292 Idx = 0;
2293 else
2294 Idx = b+1;
2295 F = Name.slice(Idx, Idx + Foo.size());
2296 DotFramework = Name.slice(Idx + Foo.size(),
2297 Idx + Foo.size() + sizeof(".framework/")-1);
2298 if (F == Foo && DotFramework == ".framework/") {
2299 isFramework = true;
2300 return Foo;
2301 }
2302
2303 // Next look for the form Foo.framework/Versions/A/Foo
2304 if (b == Name.npos)
2305 goto guess_library;
2306 c = Name.rfind('/', b);
2307 if (c == Name.npos || c == 0)
2308 goto guess_library;
2309 V = Name.slice(c+1, Name.npos);
2310 if (!V.startswith("Versions/"))
2311 goto guess_library;
2312 d = Name.rfind('/', c);
2313 if (d == Name.npos)
2314 Idx = 0;
2315 else
2316 Idx = d+1;
2317 F = Name.slice(Idx, Idx + Foo.size());
2318 DotFramework = Name.slice(Idx + Foo.size(),
2319 Idx + Foo.size() + sizeof(".framework/")-1);
2320 if (F == Foo && DotFramework == ".framework/") {
2321 isFramework = true;
2322 return Foo;
2323 }
2324
2325guess_library:
2326 // pull off the suffix after the "." and make a point to it
2327 a = Name.rfind('.');
2328 if (a == Name.npos || a == 0)
2329 return StringRef();
2330 Dylib = Name.slice(a, Name.npos);
2331 if (Dylib != ".dylib")
2332 goto guess_qtx;
2333
2334 // First pull off the version letter for the form Foo.A.dylib if any.
2335 if (a >= 3) {
2336 Dot = Name.slice(a-2, a-1);
2337 if (Dot == ".")
2338 a = a - 2;
2339 }
2340
2341 b = Name.rfind('/', a);
2342 if (b == Name.npos)
2343 b = 0;
2344 else
2345 b = b+1;
2346 // ignore any suffix after an underbar like Foo_profile.A.dylib
Michael Trentf4c902b2019-01-24 20:59:44 +00002347 Idx = Name.rfind('_');
Kevin Enderby980b2582014-06-05 21:21:57 +00002348 if (Idx != Name.npos && Idx != b) {
2349 Lib = Name.slice(b, Idx);
2350 Suffix = Name.slice(Idx, a);
Michael Trentf4c902b2019-01-24 20:59:44 +00002351 if (Suffix != "_debug" && Suffix != "_profile") {
2352 Suffix = StringRef();
2353 Lib = Name.slice(b, a);
2354 }
Kevin Enderby980b2582014-06-05 21:21:57 +00002355 }
2356 else
2357 Lib = Name.slice(b, a);
2358 // There are incorrect library names of the form:
2359 // libATS.A_profile.dylib so check for these.
2360 if (Lib.size() >= 3) {
2361 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2362 if (Dot == ".")
2363 Lib = Lib.slice(0, Lib.size()-2);
2364 }
2365 return Lib;
2366
2367guess_qtx:
2368 Qtx = Name.slice(a, Name.npos);
2369 if (Qtx != ".qtx")
2370 return StringRef();
2371 b = Name.rfind('/', a);
2372 if (b == Name.npos)
2373 Lib = Name.slice(0, a);
2374 else
2375 Lib = Name.slice(b+1, a);
2376 // There are library names of the form: QT.A.qtx so check for these.
2377 if (Lib.size() >= 3) {
2378 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2379 if (Dot == ".")
2380 Lib = Lib.slice(0, Lib.size()-2);
2381 }
2382 return Lib;
2383}
2384
2385// getLibraryShortNameByIndex() is used to get the short name of the library
2386// for an undefined symbol in a linked Mach-O binary that was linked with the
2387// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2388// It is passed the index (0 - based) of the library as translated from
2389// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00002390std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00002391 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00002392 if (Index >= Libraries.size())
2393 return object_error::parse_failed;
2394
Kevin Enderby980b2582014-06-05 21:21:57 +00002395 // If the cache of LibrariesShortNames is not built up do that first for
2396 // all the Libraries.
2397 if (LibrariesShortNames.size() == 0) {
2398 for (unsigned i = 0; i < Libraries.size(); i++) {
2399 MachO::dylib_command D =
Lang Hames697e7cd2016-12-04 01:56:10 +00002400 getStruct<MachO::dylib_command>(*this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00002401 if (D.dylib.name >= D.cmdsize)
2402 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00002403 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00002404 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00002405 if (D.dylib.name+Name.size() >= D.cmdsize)
2406 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00002407 StringRef Suffix;
2408 bool isFramework;
2409 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00002410 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00002411 LibrariesShortNames.push_back(Name);
2412 else
2413 LibrariesShortNames.push_back(shortName);
2414 }
2415 }
2416
2417 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00002418 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00002419}
2420
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00002421uint32_t MachOObjectFile::getLibraryCount() const {
2422 return Libraries.size();
2423}
2424
Rafael Espindola76ad2322015-07-06 14:55:37 +00002425section_iterator
2426MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2427 DataRefImpl Sec;
2428 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2429 return section_iterator(SectionRef(Sec, this));
2430}
2431
Peter Collingbourne435890a2016-11-22 03:38:40 +00002432basic_symbol_iterator MachOObjectFile::symbol_begin() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00002433 DataRefImpl DRI;
2434 MachO::symtab_command Symtab = getSymtabLoadCommand();
2435 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2436 return basic_symbol_iterator(SymbolRef(DRI, this));
2437
Lang Hames36072da2014-05-12 21:39:59 +00002438 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002439}
2440
Peter Collingbourne435890a2016-11-22 03:38:40 +00002441basic_symbol_iterator MachOObjectFile::symbol_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002442 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00002443 MachO::symtab_command Symtab = getSymtabLoadCommand();
2444 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002445 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00002446
Rafael Espindola75c30362013-04-24 19:47:55 +00002447 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002448 sizeof(MachO::nlist_64) :
2449 sizeof(MachO::nlist);
2450 unsigned Offset = Symtab.symoff +
2451 Symtab.nsyms * SymbolTableEntrySize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002452 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002453 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002454}
2455
Lang Hames46f0a972019-01-14 22:05:12 +00002456symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00002457 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00002458 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002459 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00002460 unsigned SymbolTableEntrySize =
2461 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00002462 DataRefImpl DRI;
Lang Hames697e7cd2016-12-04 01:56:10 +00002463 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Lang Hames36072da2014-05-12 21:39:59 +00002464 DRI.p += Index * SymbolTableEntrySize;
2465 return basic_symbol_iterator(SymbolRef(DRI, this));
2466}
2467
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002468uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2469 MachO::symtab_command Symtab = getSymtabLoadCommand();
2470 if (!SymtabLoadCmd)
2471 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2472 unsigned SymbolTableEntrySize =
2473 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2474 DataRefImpl DRIstart;
Lang Hames697e7cd2016-12-04 01:56:10 +00002475 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002476 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2477 return Index;
2478}
2479
Rafael Espindolab5155a52014-02-10 20:24:04 +00002480section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002481 DataRefImpl DRI;
2482 return section_iterator(SectionRef(DRI, this));
2483}
2484
Rafael Espindolab5155a52014-02-10 20:24:04 +00002485section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002486 DataRefImpl DRI;
2487 DRI.d.a = Sections.size();
2488 return section_iterator(SectionRef(DRI, this));
2489}
2490
Rafael Espindola56f976f2013-04-18 18:08:55 +00002491uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00002492 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00002493}
2494
Rafael Espindola56f976f2013-04-18 18:08:55 +00002495StringRef MachOObjectFile::getFileFormatName() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002496 unsigned CPUType = getCPUType(*this);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002497 if (!is64Bit()) {
2498 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002499 case MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002500 return "Mach-O 32-bit i386";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002501 case MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002502 return "Mach-O arm";
Tim Northoverff6875a2019-05-14 11:25:44 +00002503 case MachO::CPU_TYPE_ARM64_32:
2504 return "Mach-O arm64 (ILP32)";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002505 case MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002506 return "Mach-O 32-bit ppc";
2507 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002508 return "Mach-O 32-bit unknown";
2509 }
2510 }
2511
Rafael Espindola56f976f2013-04-18 18:08:55 +00002512 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002513 case MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002514 return "Mach-O 64-bit x86-64";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002515 case MachO::CPU_TYPE_ARM64:
Tim Northover00ed9962014-03-29 10:18:08 +00002516 return "Mach-O arm64";
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002517 case MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002518 return "Mach-O 64-bit ppc64";
2519 default:
2520 return "Mach-O 64-bit unknown";
2521 }
2522}
2523
Alexey Samsonove6388e62013-06-18 15:03:28 +00002524Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2525 switch (CPUType) {
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002526 case MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002527 return Triple::x86;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002528 case MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002529 return Triple::x86_64;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002530 case MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002531 return Triple::arm;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002532 case MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00002533 return Triple::aarch64;
Tim Northoverff6875a2019-05-14 11:25:44 +00002534 case MachO::CPU_TYPE_ARM64_32:
2535 return Triple::aarch64_32;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002536 case MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002537 return Triple::ppc;
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002538 case MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002539 return Triple::ppc64;
2540 default:
2541 return Triple::UnknownArch;
2542 }
2543}
2544
Tim Northover9e8eb412016-04-22 23:21:13 +00002545Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
Kevin Enderby59343a92016-12-16 22:54:02 +00002546 const char **McpuDefault,
2547 const char **ArchFlag) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002548 if (McpuDefault)
2549 *McpuDefault = nullptr;
Kevin Enderby59343a92016-12-16 22:54:02 +00002550 if (ArchFlag)
2551 *ArchFlag = nullptr;
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002552
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002553 switch (CPUType) {
2554 case MachO::CPU_TYPE_I386:
2555 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2556 case MachO::CPU_SUBTYPE_I386_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002557 if (ArchFlag)
2558 *ArchFlag = "i386";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002559 return Triple("i386-apple-darwin");
2560 default:
2561 return Triple();
2562 }
2563 case MachO::CPU_TYPE_X86_64:
2564 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2565 case MachO::CPU_SUBTYPE_X86_64_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002566 if (ArchFlag)
2567 *ArchFlag = "x86_64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002568 return Triple("x86_64-apple-darwin");
2569 case MachO::CPU_SUBTYPE_X86_64_H:
Kevin Enderby59343a92016-12-16 22:54:02 +00002570 if (ArchFlag)
2571 *ArchFlag = "x86_64h";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002572 return Triple("x86_64h-apple-darwin");
2573 default:
2574 return Triple();
2575 }
2576 case MachO::CPU_TYPE_ARM:
2577 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2578 case MachO::CPU_SUBTYPE_ARM_V4T:
Kevin Enderby59343a92016-12-16 22:54:02 +00002579 if (ArchFlag)
2580 *ArchFlag = "armv4t";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002581 return Triple("armv4t-apple-darwin");
2582 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
Kevin Enderby59343a92016-12-16 22:54:02 +00002583 if (ArchFlag)
2584 *ArchFlag = "armv5e";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002585 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002586 case MachO::CPU_SUBTYPE_ARM_XSCALE:
Kevin Enderby59343a92016-12-16 22:54:02 +00002587 if (ArchFlag)
2588 *ArchFlag = "xscale";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002589 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002590 case MachO::CPU_SUBTYPE_ARM_V6:
Kevin Enderby59343a92016-12-16 22:54:02 +00002591 if (ArchFlag)
2592 *ArchFlag = "armv6";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002593 return Triple("armv6-apple-darwin");
2594 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002595 if (McpuDefault)
2596 *McpuDefault = "cortex-m0";
Kevin Enderby59343a92016-12-16 22:54:02 +00002597 if (ArchFlag)
2598 *ArchFlag = "armv6m";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002599 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002600 case MachO::CPU_SUBTYPE_ARM_V7:
Kevin Enderby59343a92016-12-16 22:54:02 +00002601 if (ArchFlag)
2602 *ArchFlag = "armv7";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002603 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002604 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002605 if (McpuDefault)
2606 *McpuDefault = "cortex-m4";
Kevin Enderby59343a92016-12-16 22:54:02 +00002607 if (ArchFlag)
2608 *ArchFlag = "armv7em";
Tim Northover9e8eb412016-04-22 23:21:13 +00002609 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002610 case MachO::CPU_SUBTYPE_ARM_V7K:
Kevin Enderby7a165752017-01-24 23:41:04 +00002611 if (McpuDefault)
2612 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002613 if (ArchFlag)
2614 *ArchFlag = "armv7k";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002615 return Triple("armv7k-apple-darwin");
2616 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002617 if (McpuDefault)
2618 *McpuDefault = "cortex-m3";
Kevin Enderby59343a92016-12-16 22:54:02 +00002619 if (ArchFlag)
2620 *ArchFlag = "armv7m";
Tim Northover9e8eb412016-04-22 23:21:13 +00002621 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002622 case MachO::CPU_SUBTYPE_ARM_V7S:
Kevin Enderby7a165752017-01-24 23:41:04 +00002623 if (McpuDefault)
2624 *McpuDefault = "cortex-a7";
Kevin Enderby59343a92016-12-16 22:54:02 +00002625 if (ArchFlag)
2626 *ArchFlag = "armv7s";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002627 return Triple("armv7s-apple-darwin");
2628 default:
2629 return Triple();
2630 }
2631 case MachO::CPU_TYPE_ARM64:
2632 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2633 case MachO::CPU_SUBTYPE_ARM64_ALL:
Kevin Enderbydc412cc2017-02-10 19:27:10 +00002634 if (McpuDefault)
2635 *McpuDefault = "cyclone";
Kevin Enderby59343a92016-12-16 22:54:02 +00002636 if (ArchFlag)
2637 *ArchFlag = "arm64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002638 return Triple("arm64-apple-darwin");
2639 default:
2640 return Triple();
2641 }
Tim Northoverff6875a2019-05-14 11:25:44 +00002642 case MachO::CPU_TYPE_ARM64_32:
2643 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2644 case MachO::CPU_SUBTYPE_ARM64_32_V8:
2645 if (McpuDefault)
2646 *McpuDefault = "cyclone";
2647 if (ArchFlag)
2648 *ArchFlag = "arm64_32";
2649 return Triple("arm64_32-apple-darwin");
2650 default:
2651 return Triple();
2652 }
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002653 case MachO::CPU_TYPE_POWERPC:
2654 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2655 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002656 if (ArchFlag)
2657 *ArchFlag = "ppc";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002658 return Triple("ppc-apple-darwin");
2659 default:
2660 return Triple();
2661 }
2662 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00002663 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002664 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002665 if (ArchFlag)
2666 *ArchFlag = "ppc64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002667 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002668 default:
2669 return Triple();
2670 }
2671 default:
2672 return Triple();
2673 }
2674}
2675
2676Triple MachOObjectFile::getHostArch() {
2677 return Triple(sys::getDefaultTargetTriple());
2678}
2679
Rafael Espindola72318b42014-08-08 16:30:17 +00002680bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2681 return StringSwitch<bool>(ArchFlag)
2682 .Case("i386", true)
2683 .Case("x86_64", true)
2684 .Case("x86_64h", true)
2685 .Case("armv4t", true)
2686 .Case("arm", true)
2687 .Case("armv5e", true)
2688 .Case("armv6", true)
2689 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00002690 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002691 .Case("armv7em", true)
2692 .Case("armv7k", true)
2693 .Case("armv7m", true)
2694 .Case("armv7s", true)
2695 .Case("arm64", true)
Tim Northoverff6875a2019-05-14 11:25:44 +00002696 .Case("arm64_32", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002697 .Case("ppc", true)
2698 .Case("ppc64", true)
2699 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002700}
2701
Zachary Turner260fe3e2017-12-14 22:07:03 +00002702Triple::ArchType MachOObjectFile::getArch() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002703 return getArch(getCPUType(*this));
Alexey Samsonove6388e62013-06-18 15:03:28 +00002704}
2705
Tim Northover9e8eb412016-04-22 23:21:13 +00002706Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2707 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002708}
2709
Rui Ueyamabc654b12013-09-27 21:47:05 +00002710relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002711 DataRefImpl DRI;
2712 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002713 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002714}
2715
Rui Ueyamabc654b12013-09-27 21:47:05 +00002716relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002717 DataRefImpl DRI;
2718 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002719 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002720}
2721
Kevin Enderby273ae012013-06-06 17:20:50 +00002722dice_iterator MachOObjectFile::begin_dices() const {
2723 DataRefImpl DRI;
2724 if (!DataInCodeLoadCmd)
2725 return dice_iterator(DiceRef(DRI, this));
2726
Charles Davis8bdfafd2013-09-01 04:28:48 +00002727 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
Lang Hames697e7cd2016-12-04 01:56:10 +00002728 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00002729 return dice_iterator(DiceRef(DRI, this));
2730}
2731
2732dice_iterator MachOObjectFile::end_dices() const {
2733 DataRefImpl DRI;
2734 if (!DataInCodeLoadCmd)
2735 return dice_iterator(DiceRef(DRI, this));
2736
Charles Davis8bdfafd2013-09-01 04:28:48 +00002737 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2738 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002739 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Kevin Enderby273ae012013-06-06 17:20:50 +00002740 return dice_iterator(DiceRef(DRI, this));
2741}
2742
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002743ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
2744 ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002745
2746void ExportEntry::moveToFirst() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002747 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002748 pushNode(0);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002749 if (*E)
2750 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002751 pushDownUntilBottom();
2752}
2753
2754void ExportEntry::moveToEnd() {
2755 Stack.clear();
2756 Done = true;
2757}
2758
2759bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002760 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002761 if (Done || Other.Done)
2762 return (Done == Other.Done);
2763 // Not equal if different stack sizes.
2764 if (Stack.size() != Other.Stack.size())
2765 return false;
2766 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00002767 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00002768 return false;
2769 // Equal if all nodes in both stacks match.
2770 for (unsigned i=0; i < Stack.size(); ++i) {
2771 if (Stack[i].Start != Other.Stack[i].Start)
2772 return false;
2773 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002774 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002775}
2776
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002777uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002778 unsigned Count;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002779 uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002780 Ptr += Count;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002781 if (Ptr > Trie.end())
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002782 Ptr = Trie.end();
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002783 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002784}
2785
2786StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00002787 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002788}
2789
2790uint64_t ExportEntry::flags() const {
2791 return Stack.back().Flags;
2792}
2793
2794uint64_t ExportEntry::address() const {
2795 return Stack.back().Address;
2796}
2797
2798uint64_t ExportEntry::other() const {
2799 return Stack.back().Other;
2800}
2801
2802StringRef ExportEntry::otherName() const {
2803 const char* ImportName = Stack.back().ImportName;
2804 if (ImportName)
2805 return StringRef(ImportName);
2806 return StringRef();
2807}
2808
2809uint32_t ExportEntry::nodeOffset() const {
2810 return Stack.back().Start - Trie.begin();
2811}
2812
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002813ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00002814 : Start(Ptr), Current(Ptr) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002815
2816void ExportEntry::pushNode(uint64_t offset) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002817 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002818 const uint8_t *Ptr = Trie.begin() + offset;
2819 NodeState State(Ptr);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002820 const char *error;
2821 uint64_t ExportInfoSize = readULEB128(State.Current, &error);
2822 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002823 *E = malformedError("export info size " + Twine(error) +
2824 " in export trie data at node: 0x" +
2825 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002826 moveToEnd();
2827 return;
2828 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002829 State.IsExportNode = (ExportInfoSize != 0);
2830 const uint8_t* Children = State.Current + ExportInfoSize;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002831 if (Children > Trie.end()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002832 *E = malformedError(
2833 "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
2834 " in export trie data at node: 0x" + Twine::utohexstr(offset) +
2835 " too big and extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002836 moveToEnd();
2837 return;
2838 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002839 if (State.IsExportNode) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002840 const uint8_t *ExportStart = State.Current;
2841 State.Flags = readULEB128(State.Current, &error);
2842 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002843 *E = malformedError("flags " + Twine(error) +
2844 " in export trie data at node: 0x" +
2845 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002846 moveToEnd();
2847 return;
2848 }
2849 uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
2850 if (State.Flags != 0 &&
2851 (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
2852 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
2853 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002854 *E = malformedError(
2855 "unsupported exported symbol kind: " + Twine((int)Kind) +
2856 " in flags: 0x" + Twine::utohexstr(State.Flags) +
2857 " in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002858 moveToEnd();
2859 return;
2860 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002861 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2862 State.Address = 0;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002863 State.Other = readULEB128(State.Current, &error); // dylib ordinal
2864 if (error) {
2865 *E = malformedError("dylib ordinal of re-export " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002866 " in export trie data at node: 0x" +
2867 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002868 moveToEnd();
2869 return;
2870 }
2871 if (O != nullptr) {
2872 if (State.Other > O->getLibraryCount()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002873 *E = malformedError(
2874 "bad library ordinal: " + Twine((int)State.Other) + " (max " +
2875 Twine((int)O->getLibraryCount()) +
2876 ") in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002877 moveToEnd();
2878 return;
2879 }
2880 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002881 State.ImportName = reinterpret_cast<const char*>(State.Current);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002882 if (*State.ImportName == '\0') {
2883 State.Current++;
2884 } else {
2885 const uint8_t *End = State.Current + 1;
2886 if (End >= Trie.end()) {
2887 *E = malformedError("import name of re-export in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002888 "node: 0x" +
2889 Twine::utohexstr(offset) +
2890 " starts past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002891 moveToEnd();
2892 return;
2893 }
2894 while(*End != '\0' && End < Trie.end())
2895 End++;
2896 if (*End != '\0') {
2897 *E = malformedError("import name of re-export in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002898 "node: 0x" +
2899 Twine::utohexstr(offset) +
2900 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002901 moveToEnd();
2902 return;
2903 }
2904 State.Current = End + 1;
2905 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002906 } else {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002907 State.Address = readULEB128(State.Current, &error);
2908 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002909 *E = malformedError("address " + Twine(error) +
2910 " in export trie data at node: 0x" +
2911 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002912 moveToEnd();
2913 return;
2914 }
2915 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
2916 State.Other = readULEB128(State.Current, &error);
2917 if (error) {
2918 *E = malformedError("resolver of stub and resolver " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002919 " in export trie data at node: 0x" +
2920 Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002921 moveToEnd();
2922 return;
2923 }
2924 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002925 }
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002926 if(ExportStart + ExportInfoSize != State.Current) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002927 *E = malformedError(
2928 "inconsistant export info size: 0x" +
2929 Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
2930 Twine::utohexstr(State.Current - ExportStart) +
2931 " in export trie data at node: 0x" + Twine::utohexstr(offset));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002932 moveToEnd();
2933 return;
2934 }
2935 }
Kevin Enderby8100cde2017-07-24 20:33:41 +00002936 State.ChildCount = *Children;
2937 if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002938 *E = malformedError("byte for count of childern in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002939 "node: 0x" +
2940 Twine::utohexstr(offset) +
2941 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002942 moveToEnd();
2943 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002944 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002945 State.Current = Children + 1;
2946 State.NextChildIndex = 0;
2947 State.ParentStringLength = CumulativeString.size();
2948 Stack.push_back(State);
2949}
2950
2951void ExportEntry::pushDownUntilBottom() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002952 ErrorAsOutParameter ErrAsOutParam(E);
2953 const char *error;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002954 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2955 NodeState &Top = Stack.back();
2956 CumulativeString.resize(Top.ParentStringLength);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002957 for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002958 char C = *Top.Current;
2959 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002960 }
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002961 if (Top.Current >= Trie.end()) {
2962 *E = malformedError("edge sub-string in export trie data at node: 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002963 Twine::utohexstr(Top.Start - Trie.begin()) +
2964 " for child #" + Twine((int)Top.NextChildIndex) +
2965 " extends past end of trie data");
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002966 moveToEnd();
2967 return;
2968 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002969 Top.Current += 1;
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002970 uint64_t childNodeIndex = readULEB128(Top.Current, &error);
2971 if (error) {
2972 *E = malformedError("child node offset " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002973 " in export trie data at node: 0x" +
2974 Twine::utohexstr(Top.Start - Trie.begin()));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002975 moveToEnd();
2976 return;
2977 }
2978 for (const NodeState &node : nodes()) {
2979 if (node.Start == Trie.begin() + childNodeIndex){
2980 *E = malformedError("loop in childern in export trie data at node: 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002981 Twine::utohexstr(Top.Start - Trie.begin()) +
2982 " back to node: 0x" +
2983 Twine::utohexstr(childNodeIndex));
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002984 moveToEnd();
2985 return;
2986 }
2987 }
Nick Kledzikd04bc352014-08-30 00:20:14 +00002988 Top.NextChildIndex += 1;
2989 pushNode(childNodeIndex);
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002990 if (*E)
2991 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002992 }
2993 if (!Stack.back().IsExportNode) {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002994 *E = malformedError("node is not an export node in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00002995 "node: 0x" +
2996 Twine::utohexstr(Stack.back().Start - Trie.begin()));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002997 moveToEnd();
Kevin Enderby3e95bd22017-07-20 23:08:41 +00002998 return;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002999 }
3000}
3001
3002// We have a trie data structure and need a way to walk it that is compatible
3003// with the C++ iterator model. The solution is a non-recursive depth first
3004// traversal where the iterator contains a stack of parent nodes along with a
3005// string that is the accumulation of all edge strings along the parent chain
3006// to this point.
3007//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00003008// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00003009// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00003010// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00003011//
3012// The algorithm for moveNext() is to keep moving down the leftmost unvisited
3013// child until hitting a node with no children (which is an export node or
3014// else the trie is malformed). On the way down, each node is pushed on the
3015// stack ivar. If there is no more ways down, it pops up one and tries to go
3016// down a sibling path until a childless node is reached.
3017void ExportEntry::moveNext() {
Kevin Enderby3e95bd22017-07-20 23:08:41 +00003018 assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
3019 if (!Stack.back().IsExportNode) {
3020 *E = malformedError("node is not an export node in export trie data at "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003021 "node: 0x" +
3022 Twine::utohexstr(Stack.back().Start - Trie.begin()));
Nick Kledzikd04bc352014-08-30 00:20:14 +00003023 moveToEnd();
3024 return;
3025 }
3026
3027 Stack.pop_back();
3028 while (!Stack.empty()) {
3029 NodeState &Top = Stack.back();
3030 if (Top.NextChildIndex < Top.ChildCount) {
3031 pushDownUntilBottom();
3032 // Now at the next export node.
3033 return;
3034 } else {
3035 if (Top.IsExportNode) {
3036 // This node has no children but is itself an export node.
3037 CumulativeString.resize(Top.ParentStringLength);
3038 return;
3039 }
3040 Stack.pop_back();
3041 }
3042 }
3043 Done = true;
3044}
3045
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003046iterator_range<export_iterator>
Kevin Enderby3e95bd22017-07-20 23:08:41 +00003047MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
3048 const MachOObjectFile *O) {
3049 ExportEntry Start(&E, O, Trie);
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003050 if (Trie.empty())
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00003051 Start.moveToEnd();
3052 else
3053 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00003054
Kevin Enderby3e95bd22017-07-20 23:08:41 +00003055 ExportEntry Finish(&E, O, Trie);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003056 Finish.moveToEnd();
3057
Craig Topper15576e12015-12-06 05:08:07 +00003058 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00003059}
3060
Alexander Shaposhnikove5740342017-07-29 00:30:45 +00003061iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
3062 return exports(Err, getDyldInfoExportsTrie(), this);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003063}
3064
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003065MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
3066 ArrayRef<uint8_t> Bytes, bool is64Bit)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003067 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3068 PointerSize(is64Bit ? 8 : 4) {}
Nick Kledzikac431442014-09-12 21:34:15 +00003069
3070void MachORebaseEntry::moveToFirst() {
3071 Ptr = Opcodes.begin();
3072 moveNext();
3073}
3074
3075void MachORebaseEntry::moveToEnd() {
3076 Ptr = Opcodes.end();
3077 RemainingLoopCount = 0;
3078 Done = true;
3079}
3080
3081void MachORebaseEntry::moveNext() {
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003082 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzikac431442014-09-12 21:34:15 +00003083 // If in the middle of some loop, move to next rebasing in loop.
3084 SegmentOffset += AdvanceAmount;
3085 if (RemainingLoopCount) {
3086 --RemainingLoopCount;
3087 return;
3088 }
Juergen Ributzkacad12492017-03-30 19:56:50 +00003089 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3090 // pointer size. Therefore it is possible to reach the end without ever having
3091 // seen REBASE_OPCODE_DONE.
3092 if (Ptr == Opcodes.end()) {
Nick Kledzikac431442014-09-12 21:34:15 +00003093 Done = true;
3094 return;
3095 }
3096 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003097 while (More) {
Nick Kledzikac431442014-09-12 21:34:15 +00003098 // Parse next opcode and set up next loop.
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003099 const uint8_t *OpcodeStart = Ptr;
Nick Kledzikac431442014-09-12 21:34:15 +00003100 uint8_t Byte = *Ptr++;
3101 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
3102 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003103 uint32_t Count, Skip;
3104 const char *error = nullptr;
Nick Kledzikac431442014-09-12 21:34:15 +00003105 switch (Opcode) {
3106 case MachO::REBASE_OPCODE_DONE:
3107 More = false;
3108 Done = true;
3109 moveToEnd();
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003110 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003111 break;
3112 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
3113 RebaseType = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003114 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003115 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3116 Twine((int)RebaseType) + " for opcode at: 0x" +
3117 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3118 moveToEnd();
3119 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003120 }
Nick Kledzikac431442014-09-12 21:34:15 +00003121 DEBUG_WITH_TYPE(
3122 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003123 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3124 << "RebaseType=" << (int) RebaseType << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003125 break;
3126 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3127 SegmentIndex = ImmValue;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003128 SegmentOffset = readULEB128(&error);
3129 if (error) {
3130 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003131 Twine(error) + " for opcode at: 0x" +
3132 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003133 moveToEnd();
3134 return;
3135 }
Michael Trent02a2ce92019-03-20 23:21:16 +00003136 error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3137 PointerSize);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003138 if (error) {
3139 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003140 Twine(error) + " for opcode at: 0x" +
3141 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003142 moveToEnd();
3143 return;
3144 }
Nick Kledzikac431442014-09-12 21:34:15 +00003145 DEBUG_WITH_TYPE(
3146 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003147 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3148 << "SegmentIndex=" << SegmentIndex << ", "
3149 << format("SegmentOffset=0x%06X", SegmentOffset)
3150 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003151 break;
3152 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003153 SegmentOffset += readULEB128(&error);
3154 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003155 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3156 " for opcode at: 0x" +
3157 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003158 moveToEnd();
3159 return;
3160 }
Michael Trent02a2ce92019-03-20 23:21:16 +00003161 error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3162 PointerSize);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003163 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003164 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3165 " for opcode at: 0x" +
3166 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003167 moveToEnd();
3168 return;
3169 }
Nick Kledzikac431442014-09-12 21:34:15 +00003170 DEBUG_WITH_TYPE("mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003171 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3172 << format("SegmentOffset=0x%06X",
3173 SegmentOffset) << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003174 break;
3175 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
Michael Trent02a2ce92019-03-20 23:21:16 +00003176 error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3177 PointerSize);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003178 if (error) {
3179 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003180 Twine(error) + " for opcode at: 0x" +
3181 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003182 moveToEnd();
3183 return;
3184 }
Nick Kledzikac431442014-09-12 21:34:15 +00003185 SegmentOffset += ImmValue * PointerSize;
Michael Trent02a2ce92019-03-20 23:21:16 +00003186 error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3187 PointerSize);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003188 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003189 *E =
3190 malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3191 " (after adding immediate times the pointer size) " +
3192 Twine(error) + " for opcode at: 0x" +
3193 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003194 moveToEnd();
3195 return;
3196 }
Nick Kledzikac431442014-09-12 21:34:15 +00003197 DEBUG_WITH_TYPE("mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003198 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3199 << format("SegmentOffset=0x%06X",
3200 SegmentOffset) << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003201 break;
3202 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
3203 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003204 Skip = 0;
3205 Count = ImmValue;
3206 if (ImmValue != 0)
3207 RemainingLoopCount = ImmValue - 1;
3208 else
3209 RemainingLoopCount = 0;
Michael Trent02a2ce92019-03-20 23:21:16 +00003210 error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3211 PointerSize, Count, Skip);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003212 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003213 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3214 Twine(error) + " for opcode at: 0x" +
3215 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003216 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003217 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003218 }
Nick Kledzikac431442014-09-12 21:34:15 +00003219 DEBUG_WITH_TYPE(
3220 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003221 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3222 << format("SegmentOffset=0x%06X", SegmentOffset)
3223 << ", AdvanceAmount=" << AdvanceAmount
3224 << ", RemainingLoopCount=" << RemainingLoopCount
3225 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003226 return;
3227 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
3228 AdvanceAmount = PointerSize;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003229 Skip = 0;
3230 Count = readULEB128(&error);
3231 if (error) {
3232 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003233 Twine(error) + " for opcode at: 0x" +
3234 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003235 moveToEnd();
3236 return;
3237 }
3238 if (Count != 0)
3239 RemainingLoopCount = Count - 1;
3240 else
3241 RemainingLoopCount = 0;
Michael Trent02a2ce92019-03-20 23:21:16 +00003242 error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3243 PointerSize, Count, Skip);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003244 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003245 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3246 Twine(error) + " for opcode at: 0x" +
3247 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003248 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003249 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003250 }
Nick Kledzikac431442014-09-12 21:34:15 +00003251 DEBUG_WITH_TYPE(
3252 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003253 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3254 << format("SegmentOffset=0x%06X", SegmentOffset)
3255 << ", AdvanceAmount=" << AdvanceAmount
3256 << ", RemainingLoopCount=" << RemainingLoopCount
3257 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003258 return;
3259 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003260 Skip = readULEB128(&error);
3261 if (error) {
3262 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003263 Twine(error) + " for opcode at: 0x" +
3264 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003265 moveToEnd();
3266 return;
3267 }
3268 AdvanceAmount = Skip + PointerSize;
3269 Count = 1;
Nick Kledzikac431442014-09-12 21:34:15 +00003270 RemainingLoopCount = 0;
Michael Trent02a2ce92019-03-20 23:21:16 +00003271 error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3272 PointerSize, Count, Skip);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003273 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003274 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3275 Twine(error) + " for opcode at: 0x" +
3276 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003277 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003278 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003279 }
Nick Kledzikac431442014-09-12 21:34:15 +00003280 DEBUG_WITH_TYPE(
3281 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003282 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3283 << format("SegmentOffset=0x%06X", SegmentOffset)
3284 << ", AdvanceAmount=" << AdvanceAmount
3285 << ", RemainingLoopCount=" << RemainingLoopCount
3286 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003287 return;
3288 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003289 Count = readULEB128(&error);
3290 if (error) {
3291 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003292 "ULEB " +
3293 Twine(error) + " for opcode at: 0x" +
3294 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003295 moveToEnd();
3296 return;
3297 }
3298 if (Count != 0)
3299 RemainingLoopCount = Count - 1;
3300 else
3301 RemainingLoopCount = 0;
3302 Skip = readULEB128(&error);
3303 if (error) {
3304 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003305 "ULEB " +
3306 Twine(error) + " for opcode at: 0x" +
3307 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003308 moveToEnd();
3309 return;
3310 }
3311 AdvanceAmount = Skip + PointerSize;
3312
Michael Trent02a2ce92019-03-20 23:21:16 +00003313 error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3314 PointerSize, Count, Skip);
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003315 if (error) {
3316 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003317 "ULEB " +
3318 Twine(error) + " for opcode at: 0x" +
3319 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003320 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003321 return;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003322 }
Nick Kledzikac431442014-09-12 21:34:15 +00003323 DEBUG_WITH_TYPE(
3324 "mach-o-rebase",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003325 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3326 << format("SegmentOffset=0x%06X", SegmentOffset)
3327 << ", AdvanceAmount=" << AdvanceAmount
3328 << ", RemainingLoopCount=" << RemainingLoopCount
3329 << "\n");
Nick Kledzikac431442014-09-12 21:34:15 +00003330 return;
3331 default:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003332 *E = malformedError("bad rebase info (bad opcode value 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003333 Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3334 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003335 moveToEnd();
3336 return;
Nick Kledzikac431442014-09-12 21:34:15 +00003337 }
3338 }
3339}
3340
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003341uint64_t MachORebaseEntry::readULEB128(const char **error) {
Nick Kledzikac431442014-09-12 21:34:15 +00003342 unsigned Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003343 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzikac431442014-09-12 21:34:15 +00003344 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003345 if (Ptr > Opcodes.end())
Nick Kledzikac431442014-09-12 21:34:15 +00003346 Ptr = Opcodes.end();
Nick Kledzikac431442014-09-12 21:34:15 +00003347 return Result;
3348}
3349
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003350int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzikac431442014-09-12 21:34:15 +00003351
3352uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3353
3354StringRef MachORebaseEntry::typeName() const {
3355 switch (RebaseType) {
3356 case MachO::REBASE_TYPE_POINTER:
3357 return "pointer";
3358 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3359 return "text abs32";
3360 case MachO::REBASE_TYPE_TEXT_PCREL32:
3361 return "text rel32";
3362 }
3363 return "unknown";
3364}
3365
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003366// For use with the SegIndex of a checked Mach-O Rebase entry
3367// to get the segment name.
3368StringRef MachORebaseEntry::segmentName() const {
3369 return O->BindRebaseSegmentName(SegmentIndex);
3370}
3371
3372// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3373// to get the section name.
3374StringRef MachORebaseEntry::sectionName() const {
3375 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3376}
3377
3378// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3379// to get the address.
3380uint64_t MachORebaseEntry::address() const {
3381 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3382}
3383
Nick Kledzikac431442014-09-12 21:34:15 +00003384bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003385#ifdef EXPENSIVE_CHECKS
Nick Kledzikac431442014-09-12 21:34:15 +00003386 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003387#else
3388 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3389#endif
Nick Kledzikac431442014-09-12 21:34:15 +00003390 return (Ptr == Other.Ptr) &&
3391 (RemainingLoopCount == Other.RemainingLoopCount) &&
3392 (Done == Other.Done);
3393}
3394
3395iterator_range<rebase_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003396MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3397 ArrayRef<uint8_t> Opcodes, bool is64) {
3398 if (O->BindRebaseSectionTable == nullptr)
3399 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3400 MachORebaseEntry Start(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003401 Start.moveToFirst();
3402
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003403 MachORebaseEntry Finish(&Err, O, Opcodes, is64);
Nick Kledzikac431442014-09-12 21:34:15 +00003404 Finish.moveToEnd();
3405
Craig Topper15576e12015-12-06 05:08:07 +00003406 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00003407}
3408
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003409iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3410 return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
Nick Kledzikac431442014-09-12 21:34:15 +00003411}
3412
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003413MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3414 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003415 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3416 PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
Nick Kledzik56ebef42014-09-16 01:41:51 +00003417
3418void MachOBindEntry::moveToFirst() {
3419 Ptr = Opcodes.begin();
3420 moveNext();
3421}
3422
3423void MachOBindEntry::moveToEnd() {
3424 Ptr = Opcodes.end();
3425 RemainingLoopCount = 0;
3426 Done = true;
3427}
3428
3429void MachOBindEntry::moveNext() {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003430 ErrorAsOutParameter ErrAsOutParam(E);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003431 // If in the middle of some loop, move to next binding in loop.
3432 SegmentOffset += AdvanceAmount;
3433 if (RemainingLoopCount) {
3434 --RemainingLoopCount;
3435 return;
3436 }
Juergen Ributzkacad12492017-03-30 19:56:50 +00003437 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3438 // pointer size. Therefore it is possible to reach the end without ever having
3439 // seen BIND_OPCODE_DONE.
3440 if (Ptr == Opcodes.end()) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003441 Done = true;
3442 return;
3443 }
3444 bool More = true;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003445 while (More) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003446 // Parse next opcode and set up next loop.
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003447 const uint8_t *OpcodeStart = Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003448 uint8_t Byte = *Ptr++;
3449 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3450 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3451 int8_t SignExtended;
3452 const uint8_t *SymStart;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003453 uint32_t Count, Skip;
3454 const char *error = nullptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003455 switch (Opcode) {
3456 case MachO::BIND_OPCODE_DONE:
3457 if (TableKind == Kind::Lazy) {
3458 // Lazying bindings have a DONE opcode between entries. Need to ignore
3459 // it to advance to next entry. But need not if this is last entry.
3460 bool NotLastEntry = false;
3461 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3462 if (*P) {
3463 NotLastEntry = true;
3464 }
3465 }
3466 if (NotLastEntry)
3467 break;
3468 }
3469 More = false;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003470 moveToEnd();
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003471 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003472 break;
3473 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003474 if (TableKind == Kind::Weak) {
3475 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003476 "weak bind table for opcode at: 0x" +
3477 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003478 moveToEnd();
3479 return;
3480 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003481 Ordinal = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003482 LibraryOrdinalSet = true;
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003483 if (ImmValue > O->getLibraryCount()) {
3484 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003485 "library ordinal: " +
3486 Twine((int)ImmValue) + " (max " +
3487 Twine((int)O->getLibraryCount()) +
3488 ") for opcode at: 0x" +
3489 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00003490 moveToEnd();
3491 return;
3492 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003493 DEBUG_WITH_TYPE(
3494 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003495 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3496 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003497 break;
3498 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003499 if (TableKind == Kind::Weak) {
3500 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003501 "weak bind table for opcode at: 0x" +
3502 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003503 moveToEnd();
3504 return;
3505 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003506 Ordinal = readULEB128(&error);
3507 LibraryOrdinalSet = true;
3508 if (error) {
3509 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003510 Twine(error) + " for opcode at: 0x" +
3511 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003512 moveToEnd();
3513 return;
3514 }
3515 if (Ordinal > (int)O->getLibraryCount()) {
3516 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003517 "library ordinal: " +
3518 Twine((int)Ordinal) + " (max " +
3519 Twine((int)O->getLibraryCount()) +
3520 ") for opcode at: 0x" +
3521 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003522 moveToEnd();
3523 return;
3524 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003525 DEBUG_WITH_TYPE(
3526 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003527 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3528 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003529 break;
3530 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003531 if (TableKind == Kind::Weak) {
3532 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003533 "weak bind table for opcode at: 0x" +
3534 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003535 moveToEnd();
3536 return;
3537 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003538 if (ImmValue) {
3539 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3540 Ordinal = SignExtended;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003541 if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3542 *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003543 "special ordinal: " +
3544 Twine((int)Ordinal) + " for opcode at: 0x" +
3545 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003546 moveToEnd();
3547 return;
3548 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003549 } else
3550 Ordinal = 0;
Steven Wu97e2cf82017-05-31 22:17:43 +00003551 LibraryOrdinalSet = true;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003552 DEBUG_WITH_TYPE(
3553 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003554 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3555 << "Ordinal=" << Ordinal << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003556 break;
3557 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3558 Flags = ImmValue;
3559 SymStart = Ptr;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003560 while (*Ptr && (Ptr < Opcodes.end())) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003561 ++Ptr;
3562 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003563 if (Ptr == Opcodes.end()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003564 *E = malformedError(
3565 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3566 "symbol name extends past opcodes for opcode at: 0x" +
3567 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3568 moveToEnd();
3569 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003570 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003571 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3572 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00003573 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003574 DEBUG_WITH_TYPE(
3575 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003576 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3577 << "SymbolName=" << SymbolName << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003578 if (TableKind == Kind::Weak) {
3579 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3580 return;
3581 }
3582 break;
3583 case MachO::BIND_OPCODE_SET_TYPE_IMM:
3584 BindType = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003585 if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003586 *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3587 Twine((int)ImmValue) + " for opcode at: 0x" +
3588 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3589 moveToEnd();
3590 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003591 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003592 DEBUG_WITH_TYPE(
3593 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003594 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3595 << "BindType=" << (int)BindType << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003596 break;
3597 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003598 Addend = readSLEB128(&error);
3599 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003600 *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
3601 " for opcode at: 0x" +
3602 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003603 moveToEnd();
3604 return;
3605 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003606 DEBUG_WITH_TYPE(
3607 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003608 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3609 << "Addend=" << Addend << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003610 break;
3611 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3612 SegmentIndex = ImmValue;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003613 SegmentOffset = readULEB128(&error);
3614 if (error) {
3615 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003616 Twine(error) + " for opcode at: 0x" +
3617 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003618 moveToEnd();
3619 return;
3620 }
Michael Trent02a2ce92019-03-20 23:21:16 +00003621 error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3622 PointerSize);
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003623 if (error) {
3624 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003625 Twine(error) + " for opcode at: 0x" +
3626 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003627 moveToEnd();
3628 return;
3629 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003630 DEBUG_WITH_TYPE(
3631 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003632 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3633 << "SegmentIndex=" << SegmentIndex << ", "
3634 << format("SegmentOffset=0x%06X", SegmentOffset)
3635 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003636 break;
3637 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003638 SegmentOffset += readULEB128(&error);
3639 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003640 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3641 " for opcode at: 0x" +
3642 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003643 moveToEnd();
3644 return;
3645 }
Michael Trent02a2ce92019-03-20 23:21:16 +00003646 error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3647 PointerSize);
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003648 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003649 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3650 " for opcode at: 0x" +
3651 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003652 moveToEnd();
3653 return;
3654 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003655 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003656 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3657 << format("SegmentOffset=0x%06X",
3658 SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003659 break;
3660 case MachO::BIND_OPCODE_DO_BIND:
3661 AdvanceAmount = PointerSize;
3662 RemainingLoopCount = 0;
Michael Trent02a2ce92019-03-20 23:21:16 +00003663 error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3664 PointerSize);
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003665 if (error) {
3666 *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003667 " for opcode at: 0x" +
3668 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003669 moveToEnd();
3670 return;
3671 }
3672 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003673 *E = malformedError(
3674 "for BIND_OPCODE_DO_BIND missing preceding "
3675 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3676 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003677 moveToEnd();
3678 return;
3679 }
3680 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003681 *E =
3682 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3683 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3684 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003685 moveToEnd();
3686 return;
3687 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003688 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003689 dbgs() << "BIND_OPCODE_DO_BIND: "
3690 << format("SegmentOffset=0x%06X",
3691 SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003692 return;
3693 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003694 if (TableKind == Kind::Lazy) {
3695 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003696 "lazy bind table for opcode at: 0x" +
3697 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003698 moveToEnd();
3699 return;
3700 }
Michael Trent02a2ce92019-03-20 23:21:16 +00003701 error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3702 PointerSize);
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003703 if (error) {
3704 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003705 Twine(error) + " for opcode at: 0x" +
3706 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003707 moveToEnd();
3708 return;
3709 }
3710 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003711 *E = malformedError(
3712 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3713 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3714 "at: 0x" +
3715 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003716 moveToEnd();
3717 return;
3718 }
3719 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003720 *E = malformedError(
3721 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3722 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3723 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003724 moveToEnd();
3725 return;
3726 }
3727 AdvanceAmount = readULEB128(&error) + PointerSize;
3728 if (error) {
3729 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003730 Twine(error) + " for opcode at: 0x" +
3731 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003732 moveToEnd();
3733 return;
3734 }
3735 // Note, this is not really an error until the next bind but make no sense
3736 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3737 // bind operation.
Michael Trent02a2ce92019-03-20 23:21:16 +00003738 error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
3739 AdvanceAmount, PointerSize);
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003740 if (error) {
3741 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003742 "ULEB) " +
3743 Twine(error) + " for opcode at: 0x" +
3744 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003745 moveToEnd();
3746 return;
3747 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003748 RemainingLoopCount = 0;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003749 DEBUG_WITH_TYPE(
3750 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003751 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3752 << format("SegmentOffset=0x%06X", SegmentOffset)
3753 << ", AdvanceAmount=" << AdvanceAmount
3754 << ", RemainingLoopCount=" << RemainingLoopCount
3755 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003756 return;
3757 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003758 if (TableKind == Kind::Lazy) {
3759 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003760 "allowed in lazy bind table for opcode at: 0x" +
3761 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003762 moveToEnd();
3763 return;
3764 }
Michael Trent02a2ce92019-03-20 23:21:16 +00003765 error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3766 PointerSize);
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003767 if (error) {
3768 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003769 Twine(error) + " for opcode at: 0x" +
3770 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003771 moveToEnd();
3772 return;
3773 }
3774 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003775 *E = malformedError(
3776 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3777 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3778 "opcode at: 0x" +
3779 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003780 moveToEnd();
3781 return;
3782 }
3783 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003784 *E = malformedError(
3785 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3786 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3787 "at: 0x" +
3788 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003789 moveToEnd();
3790 return;
3791 }
Nick Kledzik3b2aa052014-10-18 01:21:02 +00003792 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003793 RemainingLoopCount = 0;
Michael Trent02a2ce92019-03-20 23:21:16 +00003794 error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
3795 AdvanceAmount, PointerSize);
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003796 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003797 *E =
3798 malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3799 " (after adding immediate times the pointer size) " +
3800 Twine(error) + " for opcode at: 0x" +
3801 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003802 moveToEnd();
3803 return;
3804 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003805 DEBUG_WITH_TYPE("mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003806 dbgs()
Nick Kledzik56ebef42014-09-16 01:41:51 +00003807 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003808 << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003809 return;
3810 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003811 if (TableKind == Kind::Lazy) {
3812 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003813 "allowed in lazy bind table for opcode at: 0x" +
3814 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003815 moveToEnd();
3816 return;
3817 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003818 Count = readULEB128(&error);
3819 if (Count != 0)
3820 RemainingLoopCount = Count - 1;
3821 else
3822 RemainingLoopCount = 0;
3823 if (error) {
3824 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003825 " (count value) " +
3826 Twine(error) + " for opcode at: 0x" +
3827 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003828 moveToEnd();
3829 return;
3830 }
3831 Skip = readULEB128(&error);
3832 AdvanceAmount = Skip + PointerSize;
3833 if (error) {
3834 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003835 " (skip value) " +
3836 Twine(error) + " for opcode at: 0x" +
3837 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003838 moveToEnd();
3839 return;
3840 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003841 if (SymbolName == StringRef()) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003842 *E = malformedError(
3843 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3844 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3845 "opcode at: 0x" +
3846 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003847 moveToEnd();
3848 return;
3849 }
3850 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003851 *E = malformedError(
3852 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3853 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3854 "at: 0x" +
3855 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003856 moveToEnd();
3857 return;
3858 }
Michael Trent02a2ce92019-03-20 23:21:16 +00003859 error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3860 PointerSize, Count, Skip);
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003861 if (error) {
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003862 *E =
3863 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3864 Twine(error) + " for opcode at: 0x" +
3865 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003866 moveToEnd();
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +00003867 return;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003868 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003869 DEBUG_WITH_TYPE(
3870 "mach-o-bind",
Eugene Zelenko9f5094d2017-04-21 22:03:05 +00003871 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3872 << format("SegmentOffset=0x%06X", SegmentOffset)
3873 << ", AdvanceAmount=" << AdvanceAmount
3874 << ", RemainingLoopCount=" << RemainingLoopCount
3875 << "\n");
Nick Kledzik56ebef42014-09-16 01:41:51 +00003876 return;
3877 default:
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003878 *E = malformedError("bad bind info (bad opcode value 0x" +
Benjamin Kramer760e00b2017-08-20 15:13:39 +00003879 Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3880 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003881 moveToEnd();
3882 return;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003883 }
3884 }
3885}
3886
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003887uint64_t MachOBindEntry::readULEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003888 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003889 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003890 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003891 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003892 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003893 return Result;
3894}
3895
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003896int64_t MachOBindEntry::readSLEB128(const char **error) {
Nick Kledzik56ebef42014-09-16 01:41:51 +00003897 unsigned Count;
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003898 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
Nick Kledzik56ebef42014-09-16 01:41:51 +00003899 Ptr += Count;
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003900 if (Ptr > Opcodes.end())
Nick Kledzik56ebef42014-09-16 01:41:51 +00003901 Ptr = Opcodes.end();
Nick Kledzik56ebef42014-09-16 01:41:51 +00003902 return Result;
3903}
3904
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003905int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
Nick Kledzik56ebef42014-09-16 01:41:51 +00003906
3907uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3908
3909StringRef MachOBindEntry::typeName() const {
3910 switch (BindType) {
3911 case MachO::BIND_TYPE_POINTER:
3912 return "pointer";
3913 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3914 return "text abs32";
3915 case MachO::BIND_TYPE_TEXT_PCREL32:
3916 return "text rel32";
3917 }
3918 return "unknown";
3919}
3920
3921StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3922
3923int64_t MachOBindEntry::addend() const { return Addend; }
3924
3925uint32_t MachOBindEntry::flags() const { return Flags; }
3926
3927int MachOBindEntry::ordinal() const { return Ordinal; }
3928
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003929// For use with the SegIndex of a checked Mach-O Bind entry
3930// to get the segment name.
3931StringRef MachOBindEntry::segmentName() const {
3932 return O->BindRebaseSegmentName(SegmentIndex);
3933}
3934
3935// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3936// to get the section name.
3937StringRef MachOBindEntry::sectionName() const {
3938 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3939}
3940
3941// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3942// to get the address.
3943uint64_t MachOBindEntry::address() const {
3944 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3945}
3946
Nick Kledzik56ebef42014-09-16 01:41:51 +00003947bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003948#ifdef EXPENSIVE_CHECKS
Nick Kledzik56ebef42014-09-16 01:41:51 +00003949 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
Saleem Abdulrasool1d84d9a2017-01-08 19:14:15 +00003950#else
3951 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3952#endif
Nick Kledzik56ebef42014-09-16 01:41:51 +00003953 return (Ptr == Other.Ptr) &&
3954 (RemainingLoopCount == Other.RemainingLoopCount) &&
3955 (Done == Other.Done);
3956}
3957
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003958// Build table of sections so SegIndex/SegOffset pairs can be translated.
3959BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
3960 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
3961 StringRef CurSegName;
3962 uint64_t CurSegAddress;
3963 for (const SectionRef &Section : Obj->sections()) {
3964 SectionInfo Info;
3965 Section.getName(Info.SectionName);
3966 Info.Address = Section.getAddress();
3967 Info.Size = Section.getSize();
3968 Info.SegmentName =
3969 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
3970 if (!Info.SegmentName.equals(CurSegName)) {
3971 ++CurSegIndex;
3972 CurSegName = Info.SegmentName;
3973 CurSegAddress = Info.Address;
3974 }
3975 Info.SegmentIndex = CurSegIndex - 1;
3976 Info.OffsetInSegment = Info.Address - CurSegAddress;
3977 Info.SegmentStartAddress = CurSegAddress;
3978 Sections.push_back(Info);
3979 }
3980 MaxSegIndex = CurSegIndex;
3981}
3982
Michael Trent02a2ce92019-03-20 23:21:16 +00003983// For use with a SegIndex, SegOffset, and PointerSize triple in
3984// MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
3985//
3986// Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
3987// that fully contains a pointer at that location. Multiple fixups in a bind
3988// (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
3989// be tested via the Count and Skip parameters.
3990const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
3991 uint64_t SegOffset,
3992 uint8_t PointerSize,
3993 uint32_t Count,
3994 uint32_t Skip) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003995 if (SegIndex == -1)
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00003996 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
Kevin Enderbya8d256c2017-03-20 19:46:55 +00003997 if (SegIndex >= MaxSegIndex)
3998 return "bad segIndex (too large)";
Michael Trent02a2ce92019-03-20 23:21:16 +00003999 for (uint32_t i = 0; i < Count; ++i) {
4000 uint32_t Start = SegOffset + i * (PointerSize + Skip);
4001 uint32_t End = Start + PointerSize;
4002 bool Found = false;
4003 for (const SectionInfo &SI : Sections) {
4004 if (SI.SegmentIndex != SegIndex)
4005 continue;
4006 if ((SI.OffsetInSegment<=Start) && (Start<(SI.OffsetInSegment+SI.Size))) {
4007 if (End <= SI.OffsetInSegment + SI.Size) {
4008 Found = true;
4009 break;
4010 }
4011 else
4012 return "bad offset, extends beyond section boundary";
4013 }
4014 }
4015 if (!Found)
4016 return "bad offset, not in section";
Kevin Enderby6c1d2b42017-03-27 20:09:23 +00004017 }
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004018 return nullptr;
4019}
4020
4021// For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4022// to get the segment name.
4023StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
4024 for (const SectionInfo &SI : Sections) {
4025 if (SI.SegmentIndex == SegIndex)
4026 return SI.SegmentName;
4027 }
4028 llvm_unreachable("invalid SegIndex");
4029}
4030
4031// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4032// to get the SectionInfo.
4033const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
4034 int32_t SegIndex, uint64_t SegOffset) {
4035 for (const SectionInfo &SI : Sections) {
4036 if (SI.SegmentIndex != SegIndex)
4037 continue;
4038 if (SI.OffsetInSegment > SegOffset)
4039 continue;
4040 if (SegOffset >= (SI.OffsetInSegment + SI.Size))
4041 continue;
4042 return SI;
4043 }
4044 llvm_unreachable("SegIndex and SegOffset not in any section");
4045}
4046
4047// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4048// entry to get the section name.
4049StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
4050 uint64_t SegOffset) {
4051 return findSection(SegIndex, SegOffset).SectionName;
4052}
4053
4054// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4055// entry to get the address.
4056uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
4057 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
4058 return SI.SegmentStartAddress + OffsetInSeg;
4059}
4060
Nick Kledzik56ebef42014-09-16 01:41:51 +00004061iterator_range<bind_iterator>
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004062MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004063 ArrayRef<uint8_t> Opcodes, bool is64,
Nick Kledzik56ebef42014-09-16 01:41:51 +00004064 MachOBindEntry::Kind BKind) {
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004065 if (O->BindRebaseSectionTable == nullptr)
4066 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004067 MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00004068 Start.moveToFirst();
4069
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004070 MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
Nick Kledzik56ebef42014-09-16 01:41:51 +00004071 Finish.moveToEnd();
4072
Craig Topper15576e12015-12-06 05:08:07 +00004073 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00004074}
4075
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004076iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004077 return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004078 MachOBindEntry::Kind::Regular);
4079}
4080
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004081iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004082 return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004083 MachOBindEntry::Kind::Lazy);
4084}
4085
Kevin Enderbya8d256c2017-03-20 19:46:55 +00004086iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
Kevin Enderbyfeb63b92017-02-28 21:47:07 +00004087 return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
Nick Kledzik56ebef42014-09-16 01:41:51 +00004088 MachOBindEntry::Kind::Weak);
4089}
4090
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00004091MachOObjectFile::load_command_iterator
4092MachOObjectFile::begin_load_commands() const {
4093 return LoadCommands.begin();
4094}
4095
4096MachOObjectFile::load_command_iterator
4097MachOObjectFile::end_load_commands() const {
4098 return LoadCommands.end();
4099}
4100
4101iterator_range<MachOObjectFile::load_command_iterator>
4102MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00004103 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00004104}
4105
Rafael Espindola56f976f2013-04-18 18:08:55 +00004106StringRef
4107MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
4108 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
4109 return parseSegmentOrSectionName(Raw.data());
4110}
4111
4112ArrayRef<char>
4113MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00004114 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00004115 const section_base *Base =
4116 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00004117 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004118}
4119
4120ArrayRef<char>
4121MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00004122 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00004123 const section_base *Base =
4124 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00004125 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004126}
4127
4128bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00004129MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00004130 const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004131 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00004132 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00004133 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004134}
4135
Eric Christopher1d62c252013-07-22 22:25:07 +00004136unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004137 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004138 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00004139 return RE.r_word1 & 0xffffff;
4140 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004141}
4142
Eric Christopher1d62c252013-07-22 22:25:07 +00004143bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004144 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004145 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00004146 return (RE.r_word1 >> 27) & 1;
4147 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004148}
4149
Eric Christopher1d62c252013-07-22 22:25:07 +00004150bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004151 const MachO::any_relocation_info &RE) const {
4152 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004153}
4154
Eric Christopher1d62c252013-07-22 22:25:07 +00004155uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004156 const MachO::any_relocation_info &RE) const {
4157 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004158}
4159
Kevin Enderby9907d0a2014-11-04 00:43:16 +00004160uint32_t MachOObjectFile::getScatteredRelocationType(
4161 const MachO::any_relocation_info &RE) const {
4162 return (RE.r_word0 >> 24) & 0xf;
4163}
4164
Eric Christopher1d62c252013-07-22 22:25:07 +00004165unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004166 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004167 if (isRelocationScattered(RE))
4168 return getScatteredRelocationAddress(RE);
4169 return getPlainRelocationAddress(RE);
4170}
4171
Charles Davis8bdfafd2013-09-01 04:28:48 +00004172unsigned MachOObjectFile::getAnyRelocationPCRel(
4173 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004174 if (isRelocationScattered(RE))
Lang Hames697e7cd2016-12-04 01:56:10 +00004175 return getScatteredRelocationPCRel(RE);
4176 return getPlainRelocationPCRel(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004177}
4178
Eric Christopher1d62c252013-07-22 22:25:07 +00004179unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004180 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004181 if (isRelocationScattered(RE))
4182 return getScatteredRelocationLength(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00004183 return getPlainRelocationLength(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004184}
4185
4186unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00004187MachOObjectFile::getAnyRelocationType(
4188 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00004189 if (isRelocationScattered(RE))
4190 return getScatteredRelocationType(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00004191 return getPlainRelocationType(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004192}
4193
Rafael Espindola52501032013-04-30 15:40:54 +00004194SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00004195MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00004196 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00004197 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00004198 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00004199 unsigned SecNum = getPlainRelocationSymbolNum(RE);
4200 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
4201 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00004202 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00004203 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00004204 return SectionRef(DRI, this);
4205}
4206
Charles Davis8bdfafd2013-09-01 04:28:48 +00004207MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00004208 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00004209 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004210}
4211
Charles Davis8bdfafd2013-09-01 04:28:48 +00004212MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00004213 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00004214 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004215}
4216
Charles Davis8bdfafd2013-09-01 04:28:48 +00004217MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00004218 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004219 const char *Sec = getSectionPtr(*this, L, Index);
4220 return getStruct<MachO::section>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004221}
4222
Charles Davis8bdfafd2013-09-01 04:28:48 +00004223MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4224 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004225 const char *Sec = getSectionPtr(*this, L, Index);
4226 return getStruct<MachO::section_64>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004227}
4228
Charles Davis8bdfafd2013-09-01 04:28:48 +00004229MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00004230MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00004231 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004232 return getStruct<MachO::nlist>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004233}
4234
Charles Davis8bdfafd2013-09-01 04:28:48 +00004235MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00004236MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00004237 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004238 return getStruct<MachO::nlist_64>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004239}
4240
Charles Davis8bdfafd2013-09-01 04:28:48 +00004241MachO::linkedit_data_command
4242MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004243 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004244}
4245
Charles Davis8bdfafd2013-09-01 04:28:48 +00004246MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00004247MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004248 return getStruct<MachO::segment_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004249}
4250
Charles Davis8bdfafd2013-09-01 04:28:48 +00004251MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00004252MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004253 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004254}
4255
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00004256MachO::linker_option_command
4257MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004258 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004259}
4260
Jim Grosbach448334a2014-03-18 22:09:05 +00004261MachO::version_min_command
4262MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004263 return getStruct<MachO::version_min_command>(*this, L.Ptr);
Jim Grosbach448334a2014-03-18 22:09:05 +00004264}
4265
Kevin Enderbya4579c42017-01-19 17:36:31 +00004266MachO::note_command
4267MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
4268 return getStruct<MachO::note_command>(*this, L.Ptr);
4269}
4270
Steven Wu5b54a422017-01-23 20:07:55 +00004271MachO::build_version_command
4272MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
4273 return getStruct<MachO::build_version_command>(*this, L.Ptr);
4274}
4275
4276MachO::build_tool_version
4277MachOObjectFile::getBuildToolVersion(unsigned index) const {
4278 return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
4279}
4280
Tim Northover8f9590b2014-06-30 14:40:57 +00004281MachO::dylib_command
4282MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004283 return getStruct<MachO::dylib_command>(*this, L.Ptr);
Tim Northover8f9590b2014-06-30 14:40:57 +00004284}
4285
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004286MachO::dyld_info_command
4287MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004288 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004289}
4290
4291MachO::dylinker_command
4292MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004293 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004294}
4295
4296MachO::uuid_command
4297MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004298 return getStruct<MachO::uuid_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004299}
4300
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004301MachO::rpath_command
4302MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004303 return getStruct<MachO::rpath_command>(*this, L.Ptr);
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00004304}
4305
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004306MachO::source_version_command
4307MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004308 return getStruct<MachO::source_version_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004309}
4310
4311MachO::entry_point_command
4312MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004313 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00004314}
4315
Kevin Enderby0804f4672014-12-16 23:25:52 +00004316MachO::encryption_info_command
4317MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004318 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
Kevin Enderby0804f4672014-12-16 23:25:52 +00004319}
4320
Kevin Enderby57538292014-12-17 01:01:30 +00004321MachO::encryption_info_command_64
4322MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004323 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
Kevin Enderby57538292014-12-17 01:01:30 +00004324}
4325
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004326MachO::sub_framework_command
4327MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004328 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
Kevin Enderbyb4b79312014-12-18 19:24:35 +00004329}
Tim Northover8f9590b2014-06-30 14:40:57 +00004330
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004331MachO::sub_umbrella_command
4332MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004333 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00004334}
4335
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004336MachO::sub_library_command
4337MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004338 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00004339}
4340
Kevin Enderby186eac32014-12-19 21:06:24 +00004341MachO::sub_client_command
4342MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004343 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
Kevin Enderby186eac32014-12-19 21:06:24 +00004344}
4345
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004346MachO::routines_command
4347MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004348 return getStruct<MachO::routines_command>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004349}
4350
4351MachO::routines_command_64
4352MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004353 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00004354}
4355
Kevin Enderby48ef5342014-12-23 22:56:39 +00004356MachO::thread_command
4357MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00004358 return getStruct<MachO::thread_command>(*this, L.Ptr);
Kevin Enderby48ef5342014-12-23 22:56:39 +00004359}
4360
Charles Davis8bdfafd2013-09-01 04:28:48 +00004361MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00004362MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00004363 uint32_t Offset;
Kevin Enderbyabf10f22017-06-22 17:41:22 +00004364 if (getHeader().filetype == MachO::MH_OBJECT) {
4365 DataRefImpl Sec;
4366 Sec.d.a = Rel.d.a;
4367 if (is64Bit()) {
4368 MachO::section_64 Sect = getSection64(Sec);
4369 Offset = Sect.reloff;
4370 } else {
4371 MachO::section Sect = getSection(Sec);
4372 Offset = Sect.reloff;
4373 }
Rafael Espindola128b8112014-04-03 23:51:28 +00004374 } else {
Kevin Enderbyabf10f22017-06-22 17:41:22 +00004375 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
Michael Trenta1703b12017-12-15 17:57:40 +00004376 if (Rel.d.a == 0)
4377 Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
4378 else
4379 Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
Rafael Espindola128b8112014-04-03 23:51:28 +00004380 }
4381
4382 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004383 getPtr(*this, Offset)) + Rel.d.b;
Rafael Espindola128b8112014-04-03 23:51:28 +00004384 return getStruct<MachO::any_relocation_info>(
Lang Hames697e7cd2016-12-04 01:56:10 +00004385 *this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00004386}
4387
Charles Davis8bdfafd2013-09-01 04:28:48 +00004388MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00004389MachOObjectFile::getDice(DataRefImpl Rel) const {
4390 const char *P = reinterpret_cast<const char *>(Rel.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00004391 return getStruct<MachO::data_in_code_entry>(*this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00004392}
4393
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004394const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00004395 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004396}
4397
Alexey Samsonov13415ed2015-06-04 19:22:03 +00004398const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4399 assert(is64Bit());
4400 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004401}
4402
Charles Davis8bdfafd2013-09-01 04:28:48 +00004403uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4404 const MachO::dysymtab_command &DLC,
4405 unsigned Index) const {
4406 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
Lang Hames697e7cd2016-12-04 01:56:10 +00004407 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004408}
4409
Charles Davis8bdfafd2013-09-01 04:28:48 +00004410MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00004411MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4412 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004413 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
Lang Hames697e7cd2016-12-04 01:56:10 +00004414 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00004415}
4416
Charles Davis8bdfafd2013-09-01 04:28:48 +00004417MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004418 if (SymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004419 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004420
4421 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4422 MachO::symtab_command Cmd;
4423 Cmd.cmd = MachO::LC_SYMTAB;
4424 Cmd.cmdsize = sizeof(MachO::symtab_command);
4425 Cmd.symoff = 0;
4426 Cmd.nsyms = 0;
4427 Cmd.stroff = 0;
4428 Cmd.strsize = 0;
4429 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00004430}
4431
Charles Davis8bdfafd2013-09-01 04:28:48 +00004432MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004433 if (DysymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004434 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00004435
4436 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4437 MachO::dysymtab_command Cmd;
4438 Cmd.cmd = MachO::LC_DYSYMTAB;
4439 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4440 Cmd.ilocalsym = 0;
4441 Cmd.nlocalsym = 0;
4442 Cmd.iextdefsym = 0;
4443 Cmd.nextdefsym = 0;
4444 Cmd.iundefsym = 0;
4445 Cmd.nundefsym = 0;
4446 Cmd.tocoff = 0;
4447 Cmd.ntoc = 0;
4448 Cmd.modtaboff = 0;
4449 Cmd.nmodtab = 0;
4450 Cmd.extrefsymoff = 0;
4451 Cmd.nextrefsyms = 0;
4452 Cmd.indirectsymoff = 0;
4453 Cmd.nindirectsyms = 0;
4454 Cmd.extreloff = 0;
4455 Cmd.nextrel = 0;
4456 Cmd.locreloff = 0;
4457 Cmd.nlocrel = 0;
4458 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00004459}
4460
Charles Davis8bdfafd2013-09-01 04:28:48 +00004461MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00004462MachOObjectFile::getDataInCodeLoadCommand() const {
4463 if (DataInCodeLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004464 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00004465
4466 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00004467 MachO::linkedit_data_command Cmd;
4468 Cmd.cmd = MachO::LC_DATA_IN_CODE;
4469 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4470 Cmd.dataoff = 0;
4471 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00004472 return Cmd;
4473}
4474
Kevin Enderby9a509442015-01-27 21:28:24 +00004475MachO::linkedit_data_command
4476MachOObjectFile::getLinkOptHintsLoadCommand() const {
4477 if (LinkOptHintsLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00004478 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
Kevin Enderby9a509442015-01-27 21:28:24 +00004479
4480 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4481 // fields.
4482 MachO::linkedit_data_command Cmd;
4483 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4484 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4485 Cmd.dataoff = 0;
4486 Cmd.datasize = 0;
4487 return Cmd;
4488}
4489
Nick Kledzikd04bc352014-08-30 00:20:14 +00004490ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004491 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004492 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004493
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004494 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004495 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004496 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004497 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00004498 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004499}
4500
4501ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004502 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004503 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004504
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004505 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004506 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004507 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004508 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004509 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004510}
4511
4512ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004513 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004514 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004515
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004516 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004517 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004518 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004519 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004520 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004521}
4522
4523ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004524 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004525 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004526
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004527 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004528 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004529 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004530 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00004531 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004532}
4533
4534ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00004535 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004536 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00004537
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004538 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00004539 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00004540 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00004541 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00004542 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00004543}
4544
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004545ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
4546 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00004547 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00004548 // Returning a pointer is fine as uuid doesn't need endian swapping.
4549 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00004550 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00004551}
Nick Kledzikd04bc352014-08-30 00:20:14 +00004552
Rafael Espindola6e040c02013-04-26 20:07:33 +00004553StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00004554 MachO::symtab_command S = getSymtabLoadCommand();
4555 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00004556}
4557
Rafael Espindola56f976f2013-04-18 18:08:55 +00004558bool MachOObjectFile::is64Bit() const {
4559 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00004560 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004561}
4562
4563void MachOObjectFile::ReadULEB128s(uint64_t Index,
4564 SmallVectorImpl<uint64_t> &Out) const {
4565 DataExtractor extractor(ObjectFile::getData(), true, 0);
4566
4567 uint32_t offset = Index;
4568 uint64_t data = 0;
4569 while (uint64_t delta = extractor.getULEB128(&offset)) {
4570 data += delta;
4571 Out.push_back(data);
4572 }
4573}
4574
Rafael Espindolac66d7612014-08-17 19:09:37 +00004575bool MachOObjectFile::isRelocatableObject() const {
4576 return getHeader().filetype == MachO::MH_OBJECT;
4577}
4578
Lang Hamesff044b12016-03-25 23:11:52 +00004579Expected<std::unique_ptr<MachOObjectFile>>
Kevin Enderby79d6c632016-10-24 21:15:11 +00004580ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4581 uint32_t UniversalCputype,
4582 uint32_t UniversalIndex) {
Rafael Espindola48af1c22014-08-19 18:44:46 +00004583 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00004584 if (Magic == "\xFE\xED\xFA\xCE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004585 return MachOObjectFile::create(Buffer, false, false,
4586 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004587 if (Magic == "\xCE\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004588 return MachOObjectFile::create(Buffer, true, false,
4589 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004590 if (Magic == "\xFE\xED\xFA\xCF")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004591 return MachOObjectFile::create(Buffer, false, true,
4592 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00004593 if (Magic == "\xCF\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00004594 return MachOObjectFile::create(Buffer, true, true,
4595 UniversalCputype, UniversalIndex);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00004596 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00004597 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00004598}
Wolfgang Pieb77d3e932017-06-06 01:22:34 +00004599
4600StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
4601 return StringSwitch<StringRef>(Name)
4602 .Case("debug_str_offs", "debug_str_offsets")
4603 .Default(Name);
4604}