blob: 40105000c56cad97d4560ab5cfde8a944e30f101 [file] [log] [blame]
Eric Christopher7b015c72011-04-22 03:19:48 +00001//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Owen Anderson27c579d2011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Tim Northover00ed9962014-03-29 10:18:08 +000016#include "llvm/ADT/STLExtras.h"
Rafael Espindola72318b42014-08-08 16:30:17 +000017#include "llvm/ADT/StringSwitch.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000018#include "llvm/ADT/Triple.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000019#include "llvm/Support/DataExtractor.h"
Nick Kledzikac431442014-09-12 21:34:15 +000020#include "llvm/Support/Debug.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000021#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000022#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000023#include "llvm/Support/LEB128.h"
24#include "llvm/Support/MachO.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000025#include "llvm/Support/MemoryBuffer.h"
Jakub Staszak84a0ae72013-08-21 01:20:11 +000026#include "llvm/Support/raw_ostream.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000027#include <cctype>
28#include <cstring>
29#include <limits>
Kevin Enderbyd5039402016-10-31 20:29:48 +000030#include <list>
Eric Christopher7b015c72011-04-22 03:19:48 +000031
32using namespace llvm;
33using namespace object;
34
Artyom Skrobov7d602f72014-07-20 12:08:28 +000035namespace {
36 struct section_base {
37 char sectname[16];
38 char segname[16];
39 };
40}
Rafael Espindola56f976f2013-04-18 18:08:55 +000041
Lang Hames9e964f32016-03-25 17:25:34 +000042static Error
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000043malformedError(Twine Msg) {
Kevin Enderby89134962016-05-05 23:41:05 +000044 std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")";
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000045 return make_error<GenericBinaryError>(std::move(StringMsg),
Kevin Enderby89134962016-05-05 23:41:05 +000046 object_error::parse_failed);
Lang Hames9e964f32016-03-25 17:25:34 +000047}
48
Alexey Samsonov9f336632015-06-04 19:45:22 +000049// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000050template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000051static T getStruct(const MachOObjectFile &O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000052 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000053 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Filipe Cabecinhas40139502015-01-15 22:52:38 +000054 report_fatal_error("Malformed MachO file.");
55
Rafael Espindola3cdeb172013-04-19 13:45:05 +000056 T Cmd;
57 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000058 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000059 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000060 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000061}
62
Alexey Samsonov9f336632015-06-04 19:45:22 +000063template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +000064static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000065 // Don't read before the beginning or past the end of the file
Lang Hames697e7cd2016-12-04 01:56:10 +000066 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
Kevin Enderbyd4e075b2016-05-06 20:16:28 +000067 return malformedError("Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000068
69 T Cmd;
70 memcpy(&Cmd, P, sizeof(T));
Lang Hames697e7cd2016-12-04 01:56:10 +000071 if (O.isLittleEndian() != sys::IsLittleEndianHost)
Alexey Samsonov9f336632015-06-04 19:45:22 +000072 MachO::swapStruct(Cmd);
73 return Cmd;
74}
75
Rafael Espindola6e040c02013-04-26 20:07:33 +000076static const char *
Lang Hames697e7cd2016-12-04 01:56:10 +000077getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
Rafael Espindola6e040c02013-04-26 20:07:33 +000078 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000079 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
80
Lang Hames697e7cd2016-12-04 01:56:10 +000081 bool Is64 = O.is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000082 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
83 sizeof(MachO::segment_command);
84 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
85 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000086
87 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000088 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000089}
90
Lang Hames697e7cd2016-12-04 01:56:10 +000091static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
92 return O.getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000093}
94
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000095static MachO::nlist_base
Lang Hames697e7cd2016-12-04 01:56:10 +000096getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000097 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000098 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000099}
100
Rafael Espindola56f976f2013-04-18 18:08:55 +0000101static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000102 if (P[15] == 0)
103 // Null terminated.
104 return P;
105 // Not null terminated, so this is a 16 char string.
106 return StringRef(P, 16);
107}
108
Rafael Espindola56f976f2013-04-18 18:08:55 +0000109// Helper to advance a section or symbol iterator multiple increments at a time.
110template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000111static void advance(T &it, size_t Val) {
112 while (Val--)
113 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000114}
115
Lang Hames697e7cd2016-12-04 01:56:10 +0000116static unsigned getCPUType(const MachOObjectFile &O) {
117 return O.getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000118}
119
Charles Davis8bdfafd2013-09-01 04:28:48 +0000120static uint32_t
121getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
122 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000123}
124
125static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000126getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
127 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000128}
129
Lang Hames697e7cd2016-12-04 01:56:10 +0000130static bool getPlainRelocationPCRel(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000131 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000132 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000133 return (RE.r_word1 >> 24) & 1;
134 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000135}
136
137static bool
Lang Hames697e7cd2016-12-04 01:56:10 +0000138getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000139 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000140}
141
Lang Hames697e7cd2016-12-04 01:56:10 +0000142static unsigned getPlainRelocationLength(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000143 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000144 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000145 return (RE.r_word1 >> 25) & 3;
146 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000147}
148
149static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000150getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
151 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152}
153
Lang Hames697e7cd2016-12-04 01:56:10 +0000154static unsigned getPlainRelocationType(const MachOObjectFile &O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000155 const MachO::any_relocation_info &RE) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000156 if (O.isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000157 return RE.r_word1 >> 28;
158 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000159}
160
Lang Hames697e7cd2016-12-04 01:56:10 +0000161static uint32_t getSectionFlags(const MachOObjectFile &O,
Rafael Espindola56f976f2013-04-18 18:08:55 +0000162 DataRefImpl Sec) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000163 if (O.is64Bit()) {
164 MachO::section_64 Sect = O.getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000165 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000166 }
Lang Hames697e7cd2016-12-04 01:56:10 +0000167 MachO::section Sect = O.getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000168 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000169}
170
Lang Hames9e964f32016-03-25 17:25:34 +0000171static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000172getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000173 uint32_t LoadCommandIndex) {
Lang Hames9e964f32016-03-25 17:25:34 +0000174 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
175 if (CmdOrErr->cmdsize < 8)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000176 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000177 " with size less than 8 bytes");
Lang Hames9e964f32016-03-25 17:25:34 +0000178 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
179 } else
180 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000181}
182
Lang Hames9e964f32016-03-25 17:25:34 +0000183static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000184getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
185 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
186 : sizeof(MachO::mach_header);
187 if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000188 return malformedError("load command 0 extends past the end all load "
Kevin Enderby89134962016-05-05 23:41:05 +0000189 "commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000190 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000191}
192
Lang Hames9e964f32016-03-25 17:25:34 +0000193static Expected<MachOObjectFile::LoadCommandInfo>
Lang Hames697e7cd2016-12-04 01:56:10 +0000194getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000195 const MachOObjectFile::LoadCommandInfo &L) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000196 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
197 : sizeof(MachO::mach_header);
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000198 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
Lang Hames697e7cd2016-12-04 01:56:10 +0000199 Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000200 return malformedError("load command " + Twine(LoadCommandIndex + 1) +
Kevin Enderby89134962016-05-05 23:41:05 +0000201 " extends past the end all load commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000202 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000203}
204
Alexey Samsonov9f336632015-06-04 19:45:22 +0000205template <typename T>
Lang Hames697e7cd2016-12-04 01:56:10 +0000206static void parseHeader(const MachOObjectFile &Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000207 Error &Err) {
Lang Hames697e7cd2016-12-04 01:56:10 +0000208 if (sizeof(T) > Obj.getData().size()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000209 Err = malformedError("the mach header extends past the end of the "
Kevin Enderby89134962016-05-05 23:41:05 +0000210 "file");
Kevin Enderby87025742016-04-13 21:17:58 +0000211 return;
212 }
Lang Hames9e964f32016-03-25 17:25:34 +0000213 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
214 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000215 else
Lang Hames9e964f32016-03-25 17:25:34 +0000216 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000217}
218
Kevin Enderbyd5039402016-10-31 20:29:48 +0000219// This is used to check for overlapping of Mach-O elements.
220struct MachOElement {
221 uint64_t Offset;
222 uint64_t Size;
223 const char *Name;
224};
225
226static Error checkOverlappingElement(std::list<MachOElement> &Elements,
227 uint64_t Offset, uint64_t Size,
228 const char *Name) {
229 if (Size == 0)
230 return Error::success();
231
232 for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
233 auto E = *it;
234 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
235 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
236 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
237 return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
238 " with a size of " + Twine(Size) + ", overlaps " +
239 E.Name + " at offset " + Twine(E.Offset) + " with "
240 "a size of " + Twine(E.Size));
241 auto nt = it;
242 nt++;
243 if (nt != Elements.end()) {
244 auto N = *nt;
245 if (Offset + Size <= N.Offset) {
246 Elements.insert(nt, {Offset, Size, Name});
247 return Error::success();
248 }
249 }
250 }
251 Elements.push_back({Offset, Size, Name});
252 return Error::success();
253}
254
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000255// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
256// sections to \param Sections, and optionally sets
257// \param IsPageZeroSegment to true.
Kevin Enderbyc614d282016-08-12 20:10:25 +0000258template <typename Segment, typename Section>
Lang Hames9e964f32016-03-25 17:25:34 +0000259static Error parseSegmentLoadCommand(
Lang Hames697e7cd2016-12-04 01:56:10 +0000260 const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000261 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000262 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
263 std::list<MachOElement> &Elements) {
Kevin Enderbyc614d282016-08-12 20:10:25 +0000264 const unsigned SegmentLoadSize = sizeof(Segment);
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000265 if (Load.C.cmdsize < SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000266 return malformedError("load command " + Twine(LoadCommandIndex) +
Kevin Enderby89134962016-05-05 23:41:05 +0000267 " " + CmdName + " cmdsize too small");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000268 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
269 Segment S = SegOrErr.get();
270 const unsigned SectionSize = sizeof(Section);
Lang Hames697e7cd2016-12-04 01:56:10 +0000271 uint64_t FileSize = Obj.getData().size();
Lang Hames9e964f32016-03-25 17:25:34 +0000272 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
273 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
Kevin Enderbyd4e075b2016-05-06 20:16:28 +0000274 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000275 " inconsistent cmdsize in " + CmdName +
Kevin Enderby89134962016-05-05 23:41:05 +0000276 " for the number of sections");
Lang Hames9e964f32016-03-25 17:25:34 +0000277 for (unsigned J = 0; J < S.nsects; ++J) {
278 const char *Sec = getSectionPtr(Obj, Load, J);
279 Sections.push_back(Sec);
Kevin Enderbyc614d282016-08-12 20:10:25 +0000280 Section s = getStruct<Section>(Obj, Sec);
Lang Hames697e7cd2016-12-04 01:56:10 +0000281 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
282 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000283 s.flags != MachO::S_ZEROFILL &&
284 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
285 s.offset > FileSize)
286 return malformedError("offset field of section " + Twine(J) + " in " +
287 CmdName + " command " + Twine(LoadCommandIndex) +
288 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000289 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
290 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000291 s.flags != MachO::S_ZEROFILL &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000292 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
293 s.offset < SizeOfHeaders && s.size != 0)
Kevin Enderbyc614d282016-08-12 20:10:25 +0000294 return malformedError("offset field of section " + Twine(J) + " in " +
295 CmdName + " command " + Twine(LoadCommandIndex) +
296 " not past the headers of the file");
297 uint64_t BigSize = s.offset;
298 BigSize += s.size;
Lang Hames697e7cd2016-12-04 01:56:10 +0000299 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
300 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000301 s.flags != MachO::S_ZEROFILL &&
302 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
303 BigSize > FileSize)
304 return malformedError("offset field plus size field of section " +
305 Twine(J) + " in " + CmdName + " command " +
306 Twine(LoadCommandIndex) +
307 " extends past the end of the file");
Lang Hames697e7cd2016-12-04 01:56:10 +0000308 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
309 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyc614d282016-08-12 20:10:25 +0000310 s.flags != MachO::S_ZEROFILL &&
311 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
312 s.size > S.filesize)
313 return malformedError("size field of section " +
314 Twine(J) + " in " + CmdName + " command " +
315 Twine(LoadCommandIndex) +
316 " greater than the segment");
Lang Hames697e7cd2016-12-04 01:56:10 +0000317 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
318 Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000319 s.addr < S.vmaddr)
320 return malformedError("addr field of section " + Twine(J) + " in " +
321 CmdName + " command " + Twine(LoadCommandIndex) +
322 " less than the segment's vmaddr");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000323 BigSize = s.addr;
324 BigSize += s.size;
325 uint64_t BigEnd = S.vmaddr;
326 BigEnd += S.vmsize;
327 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000328 return malformedError("addr field plus size of section " + Twine(J) +
329 " in " + CmdName + " command " +
330 Twine(LoadCommandIndex) +
331 " greater than than "
Kevin Enderbyc614d282016-08-12 20:10:25 +0000332 "the segment's vmaddr plus vmsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000333 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
334 Obj.getHeader().filetype != MachO::MH_DSYM &&
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000335 s.flags != MachO::S_ZEROFILL &&
336 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
337 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
338 "section contents"))
339 return Err;
Kevin Enderbyc614d282016-08-12 20:10:25 +0000340 if (s.reloff > FileSize)
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000341 return malformedError("reloff field of section " + Twine(J) + " in " +
342 CmdName + " command " + Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000343 " extends past the end of the file");
344 BigSize = s.nreloc;
345 BigSize *= sizeof(struct MachO::relocation_info);
346 BigSize += s.reloff;
347 if (BigSize > FileSize)
348 return malformedError("reloff field plus nreloc field times sizeof("
349 "struct relocation_info) of section " +
350 Twine(J) + " in " + CmdName + " command " +
NAKAMURA Takumi59a20642016-08-22 00:58:04 +0000351 Twine(LoadCommandIndex) +
Kevin Enderbyc614d282016-08-12 20:10:25 +0000352 " extends past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000353 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
354 sizeof(struct
355 MachO::relocation_info),
356 "section relocation entries"))
357 return Err;
Lang Hames9e964f32016-03-25 17:25:34 +0000358 }
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000359 if (S.fileoff > FileSize)
360 return malformedError("load command " + Twine(LoadCommandIndex) +
NAKAMURA Takumi9d0b5312016-08-22 00:58:47 +0000361 " fileoff field in " + CmdName +
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000362 " extends past the end of the file");
Kevin Enderbyc614d282016-08-12 20:10:25 +0000363 uint64_t BigSize = S.fileoff;
364 BigSize += S.filesize;
365 if (BigSize > FileSize)
366 return malformedError("load command " + Twine(LoadCommandIndex) +
367 " fileoff field plus filesize field in " +
368 CmdName + " extends past the end of the file");
369 if (S.vmsize != 0 && S.filesize > S.vmsize)
370 return malformedError("load command " + Twine(LoadCommandIndex) +
371 " fileoff field in " + CmdName +
372 " greater than vmsize field");
Lang Hames9e964f32016-03-25 17:25:34 +0000373 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
374 } else
375 return SegOrErr.takeError();
376
377 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000378}
379
Lang Hames697e7cd2016-12-04 01:56:10 +0000380static Error checkSymtabCommand(const MachOObjectFile &Obj,
Kevin Enderby0e52c922016-08-26 19:34:07 +0000381 const MachOObjectFile::LoadCommandInfo &Load,
382 uint32_t LoadCommandIndex,
Kevin Enderbyd5039402016-10-31 20:29:48 +0000383 const char **SymtabLoadCmd,
384 std::list<MachOElement> &Elements) {
Kevin Enderby0e52c922016-08-26 19:34:07 +0000385 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
386 return malformedError("load command " + Twine(LoadCommandIndex) +
387 " LC_SYMTAB cmdsize too small");
388 if (*SymtabLoadCmd != nullptr)
389 return malformedError("more than one LC_SYMTAB command");
390 MachO::symtab_command Symtab =
391 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
392 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
393 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
394 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000395 uint64_t FileSize = Obj.getData().size();
Kevin Enderby0e52c922016-08-26 19:34:07 +0000396 if (Symtab.symoff > FileSize)
397 return malformedError("symoff field of LC_SYMTAB command " +
398 Twine(LoadCommandIndex) + " extends past the end "
399 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000400 uint64_t SymtabSize = Symtab.nsyms;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000401 const char *struct_nlist_name;
Lang Hames697e7cd2016-12-04 01:56:10 +0000402 if (Obj.is64Bit()) {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000403 SymtabSize *= sizeof(MachO::nlist_64);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000404 struct_nlist_name = "struct nlist_64";
405 } else {
Kevin Enderbyd5039402016-10-31 20:29:48 +0000406 SymtabSize *= sizeof(MachO::nlist);
Kevin Enderby0e52c922016-08-26 19:34:07 +0000407 struct_nlist_name = "struct nlist";
408 }
Kevin Enderbyd5039402016-10-31 20:29:48 +0000409 uint64_t BigSize = SymtabSize;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000410 BigSize += Symtab.symoff;
411 if (BigSize > FileSize)
412 return malformedError("symoff field plus nsyms field times sizeof(" +
413 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
414 Twine(LoadCommandIndex) + " extends past the end "
415 "of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000416 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
417 "symbol table"))
418 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000419 if (Symtab.stroff > FileSize)
420 return malformedError("stroff field of LC_SYMTAB command " +
421 Twine(LoadCommandIndex) + " extends past the end "
422 "of the file");
423 BigSize = Symtab.stroff;
424 BigSize += Symtab.strsize;
425 if (BigSize > FileSize)
426 return malformedError("stroff field plus strsize field of LC_SYMTAB "
427 "command " + Twine(LoadCommandIndex) + " extends "
428 "past the end of the file");
Kevin Enderbyd5039402016-10-31 20:29:48 +0000429 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
430 Symtab.strsize, "string table"))
431 return Err;
Kevin Enderby0e52c922016-08-26 19:34:07 +0000432 *SymtabLoadCmd = Load.Ptr;
433 return Error::success();
434}
435
Lang Hames697e7cd2016-12-04 01:56:10 +0000436static Error checkDysymtabCommand(const MachOObjectFile &Obj,
437 const MachOObjectFile::LoadCommandInfo &Load,
438 uint32_t LoadCommandIndex,
439 const char **DysymtabLoadCmd,
440 std::list<MachOElement> &Elements) {
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000441 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
442 return malformedError("load command " + Twine(LoadCommandIndex) +
443 " LC_DYSYMTAB cmdsize too small");
444 if (*DysymtabLoadCmd != nullptr)
445 return malformedError("more than one LC_DYSYMTAB command");
446 MachO::dysymtab_command Dysymtab =
447 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
448 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
449 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
450 " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000451 uint64_t FileSize = Obj.getData().size();
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000452 if (Dysymtab.tocoff > FileSize)
453 return malformedError("tocoff field of LC_DYSYMTAB command " +
454 Twine(LoadCommandIndex) + " extends past the end of "
455 "the file");
456 uint64_t BigSize = Dysymtab.ntoc;
457 BigSize *= sizeof(MachO::dylib_table_of_contents);
458 BigSize += Dysymtab.tocoff;
459 if (BigSize > FileSize)
460 return malformedError("tocoff field plus ntoc field times sizeof(struct "
461 "dylib_table_of_contents) of LC_DYSYMTAB command " +
462 Twine(LoadCommandIndex) + " extends past the end of "
463 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000464 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
465 Dysymtab.ntoc * sizeof(struct
466 MachO::dylib_table_of_contents),
467 "table of contents"))
468 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000469 if (Dysymtab.modtaboff > FileSize)
470 return malformedError("modtaboff field of LC_DYSYMTAB command " +
471 Twine(LoadCommandIndex) + " extends past the end of "
472 "the file");
473 BigSize = Dysymtab.nmodtab;
474 const char *struct_dylib_module_name;
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000475 uint64_t sizeof_modtab;
Lang Hames697e7cd2016-12-04 01:56:10 +0000476 if (Obj.is64Bit()) {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000477 sizeof_modtab = sizeof(MachO::dylib_module_64);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000478 struct_dylib_module_name = "struct dylib_module_64";
479 } else {
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000480 sizeof_modtab = sizeof(MachO::dylib_module);
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000481 struct_dylib_module_name = "struct dylib_module";
482 }
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000483 BigSize *= sizeof_modtab;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000484 BigSize += Dysymtab.modtaboff;
485 if (BigSize > FileSize)
486 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
487 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
488 "command " + Twine(LoadCommandIndex) + " extends "
489 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000490 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
491 Dysymtab.nmodtab * sizeof_modtab,
492 "module table"))
493 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000494 if (Dysymtab.extrefsymoff > FileSize)
495 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
496 Twine(LoadCommandIndex) + " extends past the end of "
497 "the file");
498 BigSize = Dysymtab.nextrefsyms;
499 BigSize *= sizeof(MachO::dylib_reference);
500 BigSize += Dysymtab.extrefsymoff;
501 if (BigSize > FileSize)
502 return malformedError("extrefsymoff field plus nextrefsyms field times "
503 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
504 "command " + Twine(LoadCommandIndex) + " extends "
505 "past the end of the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000506 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
507 Dysymtab.nextrefsyms *
508 sizeof(MachO::dylib_reference),
509 "reference table"))
510 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000511 if (Dysymtab.indirectsymoff > FileSize)
512 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
513 Twine(LoadCommandIndex) + " extends past the end of "
514 "the file");
515 BigSize = Dysymtab.nindirectsyms;
516 BigSize *= sizeof(uint32_t);
517 BigSize += Dysymtab.indirectsymoff;
518 if (BigSize > FileSize)
519 return malformedError("indirectsymoff field plus nindirectsyms field times "
520 "sizeof(uint32_t) of LC_DYSYMTAB command " +
521 Twine(LoadCommandIndex) + " extends past the end of "
522 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000523 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
524 Dysymtab.nindirectsyms *
525 sizeof(uint32_t),
526 "indirect table"))
527 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000528 if (Dysymtab.extreloff > FileSize)
529 return malformedError("extreloff field of LC_DYSYMTAB command " +
530 Twine(LoadCommandIndex) + " extends past the end of "
531 "the file");
532 BigSize = Dysymtab.nextrel;
533 BigSize *= sizeof(MachO::relocation_info);
534 BigSize += Dysymtab.extreloff;
535 if (BigSize > FileSize)
536 return malformedError("extreloff field plus nextrel field times sizeof"
537 "(struct relocation_info) of LC_DYSYMTAB command " +
538 Twine(LoadCommandIndex) + " extends past the end of "
539 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000540 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
541 Dysymtab.nextrel *
542 sizeof(MachO::relocation_info),
543 "external relocation table"))
544 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000545 if (Dysymtab.locreloff > FileSize)
546 return malformedError("locreloff field of LC_DYSYMTAB command " +
547 Twine(LoadCommandIndex) + " extends past the end of "
548 "the file");
549 BigSize = Dysymtab.nlocrel;
550 BigSize *= sizeof(MachO::relocation_info);
551 BigSize += Dysymtab.locreloff;
552 if (BigSize > FileSize)
553 return malformedError("locreloff field plus nlocrel field times sizeof"
554 "(struct relocation_info) of LC_DYSYMTAB command " +
555 Twine(LoadCommandIndex) + " extends past the end of "
556 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000557 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
558 Dysymtab.nlocrel *
559 sizeof(MachO::relocation_info),
560 "local relocation table"))
561 return Err;
Kevin Enderbydcbc5042016-08-30 21:28:30 +0000562 *DysymtabLoadCmd = Load.Ptr;
563 return Error::success();
564}
565
Lang Hames697e7cd2016-12-04 01:56:10 +0000566static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000567 const MachOObjectFile::LoadCommandInfo &Load,
568 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000569 const char **LoadCmd, const char *CmdName,
570 std::list<MachOElement> &Elements,
571 const char *ElementName) {
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000572 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
573 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
574 CmdName + " cmdsize too small");
575 if (*LoadCmd != nullptr)
576 return malformedError("more than one " + Twine(CmdName) + " command");
577 MachO::linkedit_data_command LinkData =
578 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
579 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
580 return malformedError(Twine(CmdName) + " command " +
581 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000582 uint64_t FileSize = Obj.getData().size();
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000583 if (LinkData.dataoff > FileSize)
584 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
585 Twine(LoadCommandIndex) + " extends past the end of "
586 "the file");
587 uint64_t BigSize = LinkData.dataoff;
588 BigSize += LinkData.datasize;
589 if (BigSize > FileSize)
590 return malformedError("dataoff field plus datasize field of " +
591 Twine(CmdName) + " command " +
592 Twine(LoadCommandIndex) + " extends past the end of "
593 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000594 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
595 LinkData.datasize, ElementName))
596 return Err;
Kevin Enderby9d0c9452016-08-31 17:57:46 +0000597 *LoadCmd = Load.Ptr;
598 return Error::success();
599}
600
Lang Hames697e7cd2016-12-04 01:56:10 +0000601static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000602 const MachOObjectFile::LoadCommandInfo &Load,
603 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000604 const char **LoadCmd, const char *CmdName,
605 std::list<MachOElement> &Elements) {
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000606 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
607 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
608 CmdName + " cmdsize too small");
609 if (*LoadCmd != nullptr)
610 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
611 "command");
612 MachO::dyld_info_command DyldInfo =
613 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
614 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
615 return malformedError(Twine(CmdName) + " command " +
616 Twine(LoadCommandIndex) + " has incorrect cmdsize");
Lang Hames697e7cd2016-12-04 01:56:10 +0000617 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000618 if (DyldInfo.rebase_off > FileSize)
619 return malformedError("rebase_off field of " + Twine(CmdName) +
620 " command " + Twine(LoadCommandIndex) + " extends "
621 "past the end of the file");
622 uint64_t BigSize = DyldInfo.rebase_off;
623 BigSize += DyldInfo.rebase_size;
624 if (BigSize > FileSize)
625 return malformedError("rebase_off field plus rebase_size field of " +
626 Twine(CmdName) + " command " +
627 Twine(LoadCommandIndex) + " extends past the end of "
628 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000629 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
630 DyldInfo.rebase_size,
631 "dyld rebase info"))
632 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000633 if (DyldInfo.bind_off > FileSize)
634 return malformedError("bind_off field of " + Twine(CmdName) +
635 " command " + Twine(LoadCommandIndex) + " extends "
636 "past the end of the file");
637 BigSize = DyldInfo.bind_off;
638 BigSize += DyldInfo.bind_size;
639 if (BigSize > FileSize)
640 return malformedError("bind_off field plus bind_size field of " +
641 Twine(CmdName) + " command " +
642 Twine(LoadCommandIndex) + " extends past the end of "
643 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000644 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
645 DyldInfo.bind_size,
646 "dyld bind info"))
647 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000648 if (DyldInfo.weak_bind_off > FileSize)
649 return malformedError("weak_bind_off field of " + Twine(CmdName) +
650 " command " + Twine(LoadCommandIndex) + " extends "
651 "past the end of the file");
652 BigSize = DyldInfo.weak_bind_off;
653 BigSize += DyldInfo.weak_bind_size;
654 if (BigSize > FileSize)
655 return malformedError("weak_bind_off field plus weak_bind_size field of " +
656 Twine(CmdName) + " command " +
657 Twine(LoadCommandIndex) + " extends past the end of "
658 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000659 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
660 DyldInfo.weak_bind_size,
661 "dyld weak bind info"))
662 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000663 if (DyldInfo.lazy_bind_off > FileSize)
664 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
665 " command " + Twine(LoadCommandIndex) + " extends "
666 "past the end of the file");
667 BigSize = DyldInfo.lazy_bind_off;
668 BigSize += DyldInfo.lazy_bind_size;
669 if (BigSize > FileSize)
670 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
671 Twine(CmdName) + " command " +
672 Twine(LoadCommandIndex) + " extends past the end of "
673 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000674 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
675 DyldInfo.lazy_bind_size,
676 "dyld lazy bind info"))
677 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000678 if (DyldInfo.export_off > FileSize)
679 return malformedError("export_off field of " + Twine(CmdName) +
680 " command " + Twine(LoadCommandIndex) + " extends "
681 "past the end of the file");
682 BigSize = DyldInfo.export_off;
683 BigSize += DyldInfo.export_size;
684 if (BigSize > FileSize)
685 return malformedError("export_off field plus export_size field of " +
686 Twine(CmdName) + " command " +
687 Twine(LoadCommandIndex) + " extends past the end of "
688 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +0000689 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
690 DyldInfo.export_size,
691 "dyld export info"))
692 return Err;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +0000693 *LoadCmd = Load.Ptr;
694 return Error::success();
695}
696
Lang Hames697e7cd2016-12-04 01:56:10 +0000697static Error checkDylibCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000698 const MachOObjectFile::LoadCommandInfo &Load,
699 uint32_t LoadCommandIndex, const char *CmdName) {
700 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
701 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
702 CmdName + " cmdsize too small");
703 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
704 if (D.dylib.name < sizeof(MachO::dylib_command))
705 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
706 CmdName + " name.offset field too small, not past "
707 "the end of the dylib_command struct");
708 if (D.dylib.name >= D.cmdsize)
709 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
710 CmdName + " name.offset field extends past the end "
711 "of the load command");
712 // Make sure there is a null between the starting offset of the name and
713 // the end of the load command.
714 uint32_t i;
715 const char *P = (const char *)Load.Ptr;
716 for (i = D.dylib.name; i < D.cmdsize; i++)
717 if (P[i] == '\0')
718 break;
719 if (i >= D.cmdsize)
720 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
721 CmdName + " library name extends past the end of the "
722 "load command");
723 return Error::success();
724}
725
Lang Hames697e7cd2016-12-04 01:56:10 +0000726static Error checkDylibIdCommand(const MachOObjectFile &Obj,
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000727 const MachOObjectFile::LoadCommandInfo &Load,
728 uint32_t LoadCommandIndex,
729 const char **LoadCmd) {
730 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
731 "LC_ID_DYLIB"))
732 return Err;
733 if (*LoadCmd != nullptr)
734 return malformedError("more than one LC_ID_DYLIB command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000735 if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
736 Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
Kevin Enderbyfc0929a2016-09-20 20:14:14 +0000737 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
738 "file type");
739 *LoadCmd = Load.Ptr;
740 return Error::success();
741}
742
Lang Hames697e7cd2016-12-04 01:56:10 +0000743static Error checkDyldCommand(const MachOObjectFile &Obj,
Kevin Enderby3e490ef2016-09-27 23:24:13 +0000744 const MachOObjectFile::LoadCommandInfo &Load,
745 uint32_t LoadCommandIndex, const char *CmdName) {
746 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
747 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
748 CmdName + " cmdsize too small");
749 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
750 if (D.name < sizeof(MachO::dylinker_command))
751 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
752 CmdName + " name.offset field too small, not past "
753 "the end of the dylinker_command struct");
754 if (D.name >= D.cmdsize)
755 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
756 CmdName + " name.offset field extends past the end "
757 "of the load command");
758 // Make sure there is a null between the starting offset of the name and
759 // the end of the load command.
760 uint32_t i;
761 const char *P = (const char *)Load.Ptr;
762 for (i = D.name; i < D.cmdsize; i++)
763 if (P[i] == '\0')
764 break;
765 if (i >= D.cmdsize)
766 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
767 CmdName + " dyld name extends past the end of the "
768 "load command");
769 return Error::success();
770}
771
Lang Hames697e7cd2016-12-04 01:56:10 +0000772static Error checkVersCommand(const MachOObjectFile &Obj,
Kevin Enderby32359db2016-09-28 21:20:45 +0000773 const MachOObjectFile::LoadCommandInfo &Load,
774 uint32_t LoadCommandIndex,
775 const char **LoadCmd, const char *CmdName) {
776 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
777 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
778 CmdName + " has incorrect cmdsize");
779 if (*LoadCmd != nullptr)
780 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
781 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
782 "LC_VERSION_MIN_WATCHOS command");
783 *LoadCmd = Load.Ptr;
784 return Error::success();
785}
786
Lang Hames697e7cd2016-12-04 01:56:10 +0000787static Error checkRpathCommand(const MachOObjectFile &Obj,
Kevin Enderby76966bf2016-09-28 23:16:01 +0000788 const MachOObjectFile::LoadCommandInfo &Load,
789 uint32_t LoadCommandIndex) {
790 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
791 return malformedError("load command " + Twine(LoadCommandIndex) +
792 " LC_RPATH cmdsize too small");
793 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
794 if (R.path < sizeof(MachO::rpath_command))
795 return malformedError("load command " + Twine(LoadCommandIndex) +
796 " LC_RPATH path.offset field too small, not past "
797 "the end of the rpath_command struct");
798 if (R.path >= R.cmdsize)
799 return malformedError("load command " + Twine(LoadCommandIndex) +
800 " LC_RPATH path.offset field extends past the end "
801 "of the load command");
802 // Make sure there is a null between the starting offset of the path and
803 // the end of the load command.
804 uint32_t i;
805 const char *P = (const char *)Load.Ptr;
806 for (i = R.path; i < R.cmdsize; i++)
807 if (P[i] == '\0')
808 break;
809 if (i >= R.cmdsize)
810 return malformedError("load command " + Twine(LoadCommandIndex) +
811 " LC_RPATH library name extends past the end of the "
812 "load command");
813 return Error::success();
814}
815
Lang Hames697e7cd2016-12-04 01:56:10 +0000816static Error checkEncryptCommand(const MachOObjectFile &Obj,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000817 const MachOObjectFile::LoadCommandInfo &Load,
818 uint32_t LoadCommandIndex,
819 uint64_t cryptoff, uint64_t cryptsize,
820 const char **LoadCmd, const char *CmdName) {
821 if (*LoadCmd != nullptr)
822 return malformedError("more than one LC_ENCRYPTION_INFO and or "
823 "LC_ENCRYPTION_INFO_64 command");
Lang Hames697e7cd2016-12-04 01:56:10 +0000824 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyf993d6e2016-10-04 20:37:43 +0000825 if (cryptoff > FileSize)
826 return malformedError("cryptoff field of " + Twine(CmdName) +
827 " command " + Twine(LoadCommandIndex) + " extends "
828 "past the end of the file");
829 uint64_t BigSize = cryptoff;
830 BigSize += cryptsize;
831 if (BigSize > FileSize)
832 return malformedError("cryptoff field plus cryptsize field of " +
833 Twine(CmdName) + " command " +
834 Twine(LoadCommandIndex) + " extends past the end of "
835 "the file");
836 *LoadCmd = Load.Ptr;
837 return Error::success();
838}
839
Lang Hames697e7cd2016-12-04 01:56:10 +0000840static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
Kevin Enderby68fffa82016-10-11 21:04:39 +0000841 const MachOObjectFile::LoadCommandInfo &Load,
842 uint32_t LoadCommandIndex) {
843 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
844 return malformedError("load command " + Twine(LoadCommandIndex) +
845 " LC_LINKER_OPTION cmdsize too small");
846 MachO::linker_option_command L =
847 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
848 // Make sure the count of strings is correct.
849 const char *string = (const char *)Load.Ptr +
850 sizeof(struct MachO::linker_option_command);
851 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
852 uint32_t i = 0;
853 while (left > 0) {
854 while (*string == '\0' && left > 0) {
855 string++;
856 left--;
857 }
858 if (left > 0) {
859 i++;
860 uint32_t NullPos = StringRef(string, left).find('\0');
861 uint32_t len = std::min(NullPos, left) + 1;
862 string += len;
863 left -= len;
864 }
865 }
866 if (L.count != i)
867 return malformedError("load command " + Twine(LoadCommandIndex) +
868 " LC_LINKER_OPTION string count " + Twine(L.count) +
869 " does not match number of strings");
870 return Error::success();
871}
872
Lang Hames697e7cd2016-12-04 01:56:10 +0000873static Error checkSubCommand(const MachOObjectFile &Obj,
Kevin Enderby2490de02016-10-17 22:09:25 +0000874 const MachOObjectFile::LoadCommandInfo &Load,
875 uint32_t LoadCommandIndex, const char *CmdName,
876 size_t SizeOfCmd, const char *CmdStructName,
877 uint32_t PathOffset, const char *PathFieldName) {
878 if (PathOffset < SizeOfCmd)
879 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
880 CmdName + " " + PathFieldName + ".offset field too "
881 "small, not past the end of the " + CmdStructName);
882 if (PathOffset >= Load.C.cmdsize)
883 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
884 CmdName + " " + PathFieldName + ".offset field "
885 "extends past the end of the load command");
886 // Make sure there is a null between the starting offset of the path and
887 // the end of the load command.
888 uint32_t i;
889 const char *P = (const char *)Load.Ptr;
890 for (i = PathOffset; i < Load.C.cmdsize; i++)
891 if (P[i] == '\0')
892 break;
893 if (i >= Load.C.cmdsize)
894 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
895 CmdName + " " + PathFieldName + " name extends past "
896 "the end of the load command");
897 return Error::success();
898}
899
Lang Hames697e7cd2016-12-04 01:56:10 +0000900static Error checkThreadCommand(const MachOObjectFile &Obj,
Kevin Enderby210030b2016-10-19 23:44:34 +0000901 const MachOObjectFile::LoadCommandInfo &Load,
902 uint32_t LoadCommandIndex,
903 const char *CmdName) {
904 if (Load.C.cmdsize < sizeof(MachO::thread_command))
905 return malformedError("load command " + Twine(LoadCommandIndex) +
906 CmdName + " cmdsize too small");
907 MachO::thread_command T =
908 getStruct<MachO::thread_command>(Obj, Load.Ptr);
909 const char *state = Load.Ptr + sizeof(MachO::thread_command);
910 const char *end = Load.Ptr + T.cmdsize;
911 uint32_t nflavor = 0;
912 uint32_t cputype = getCPUType(Obj);
913 while (state < end) {
914 if(state + sizeof(uint32_t) > end)
915 return malformedError("load command " + Twine(LoadCommandIndex) +
916 "flavor in " + CmdName + " extends past end of "
917 "command");
918 uint32_t flavor;
919 memcpy(&flavor, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000920 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000921 sys::swapByteOrder(flavor);
922 state += sizeof(uint32_t);
923
924 if(state + sizeof(uint32_t) > end)
925 return malformedError("load command " + Twine(LoadCommandIndex) +
926 " count in " + CmdName + " extends past end of "
927 "command");
928 uint32_t count;
929 memcpy(&count, state, sizeof(uint32_t));
Lang Hames697e7cd2016-12-04 01:56:10 +0000930 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
Kevin Enderby210030b2016-10-19 23:44:34 +0000931 sys::swapByteOrder(count);
932 state += sizeof(uint32_t);
933
934 if (cputype == MachO::CPU_TYPE_X86_64) {
935 if (flavor == MachO::x86_THREAD_STATE64) {
936 if (count != MachO::x86_THREAD_STATE64_COUNT)
937 return malformedError("load command " + Twine(LoadCommandIndex) +
938 " count not x86_THREAD_STATE64_COUNT for "
939 "flavor number " + Twine(nflavor) + " which is "
940 "a x86_THREAD_STATE64 flavor in " + CmdName +
941 " command");
942 if (state + sizeof(MachO::x86_thread_state64_t) > end)
943 return malformedError("load command " + Twine(LoadCommandIndex) +
944 " x86_THREAD_STATE64 extends past end of "
945 "command in " + CmdName + " command");
946 state += sizeof(MachO::x86_thread_state64_t);
947 } else {
948 return malformedError("load command " + Twine(LoadCommandIndex) +
949 " unknown flavor (" + Twine(flavor) + ") for "
950 "flavor number " + Twine(nflavor) + " in " +
951 CmdName + " command");
952 }
953 } else if (cputype == MachO::CPU_TYPE_ARM) {
954 if (flavor == MachO::ARM_THREAD_STATE) {
955 if (count != MachO::ARM_THREAD_STATE_COUNT)
956 return malformedError("load command " + Twine(LoadCommandIndex) +
957 " count not ARM_THREAD_STATE_COUNT for "
958 "flavor number " + Twine(nflavor) + " which is "
959 "a ARM_THREAD_STATE flavor in " + CmdName +
960 " command");
961 if (state + sizeof(MachO::arm_thread_state32_t) > end)
962 return malformedError("load command " + Twine(LoadCommandIndex) +
963 " ARM_THREAD_STATE extends past end of "
964 "command in " + CmdName + " command");
965 state += sizeof(MachO::arm_thread_state32_t);
966 } else {
967 return malformedError("load command " + Twine(LoadCommandIndex) +
968 " unknown flavor (" + Twine(flavor) + ") for "
969 "flavor number " + Twine(nflavor) + " in " +
970 CmdName + " command");
971 }
Kevin Enderby7747cb52016-11-03 20:51:28 +0000972 } else if (cputype == MachO::CPU_TYPE_ARM64) {
973 if (flavor == MachO::ARM_THREAD_STATE64) {
974 if (count != MachO::ARM_THREAD_STATE64_COUNT)
975 return malformedError("load command " + Twine(LoadCommandIndex) +
976 " count not ARM_THREAD_STATE64_COUNT for "
977 "flavor number " + Twine(nflavor) + " which is "
978 "a ARM_THREAD_STATE64 flavor in " + CmdName +
979 " command");
980 if (state + sizeof(MachO::arm_thread_state64_t) > end)
981 return malformedError("load command " + Twine(LoadCommandIndex) +
982 " ARM_THREAD_STATE64 extends past end of "
983 "command in " + CmdName + " command");
984 state += sizeof(MachO::arm_thread_state64_t);
985 } else {
986 return malformedError("load command " + Twine(LoadCommandIndex) +
987 " unknown flavor (" + Twine(flavor) + ") for "
988 "flavor number " + Twine(nflavor) + " in " +
989 CmdName + " command");
990 }
Kevin Enderby210030b2016-10-19 23:44:34 +0000991 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
992 if (flavor == MachO::PPC_THREAD_STATE) {
993 if (count != MachO::PPC_THREAD_STATE_COUNT)
994 return malformedError("load command " + Twine(LoadCommandIndex) +
995 " count not PPC_THREAD_STATE_COUNT for "
996 "flavor number " + Twine(nflavor) + " which is "
997 "a PPC_THREAD_STATE flavor in " + CmdName +
998 " command");
999 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1000 return malformedError("load command " + Twine(LoadCommandIndex) +
1001 " PPC_THREAD_STATE extends past end of "
1002 "command in " + CmdName + " command");
1003 state += sizeof(MachO::ppc_thread_state32_t);
1004 } else {
1005 return malformedError("load command " + Twine(LoadCommandIndex) +
1006 " unknown flavor (" + Twine(flavor) + ") for "
1007 "flavor number " + Twine(nflavor) + " in " +
1008 CmdName + " command");
1009 }
1010 } else {
1011 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1012 "command " + Twine(LoadCommandIndex) + " for " +
1013 CmdName + " command can't be checked");
1014 }
1015 nflavor++;
1016 }
1017 return Error::success();
1018}
1019
Lang Hames697e7cd2016-12-04 01:56:10 +00001020static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001021 const MachOObjectFile::LoadCommandInfo
1022 &Load,
1023 uint32_t LoadCommandIndex,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001024 const char **LoadCmd,
1025 std::list<MachOElement> &Elements) {
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001026 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1027 return malformedError("load command " + Twine(LoadCommandIndex) +
1028 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1029 if (*LoadCmd != nullptr)
1030 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1031 MachO::twolevel_hints_command Hints =
1032 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
Lang Hames697e7cd2016-12-04 01:56:10 +00001033 uint64_t FileSize = Obj.getData().size();
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001034 if (Hints.offset > FileSize)
1035 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1036 Twine(LoadCommandIndex) + " extends past the end of "
1037 "the file");
1038 uint64_t BigSize = Hints.nhints;
1039 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint);
1040 BigSize += Hints.offset;
1041 if (BigSize > FileSize)
1042 return malformedError("offset field plus nhints times sizeof(struct "
1043 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1044 Twine(LoadCommandIndex) + " extends past the end of "
1045 "the file");
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001046 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1047 sizeof(MachO::twolevel_hint),
1048 "two level hints"))
1049 return Err;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001050 *LoadCmd = Load.Ptr;
1051 return Error::success();
1052}
1053
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001054// Returns true if the libObject code does not support the load command and its
1055// contents. The cmd value it is treated as an unknown load command but with
1056// an error message that says the cmd value is obsolete.
1057static bool isLoadCommandObsolete(uint32_t cmd) {
1058 if (cmd == MachO::LC_SYMSEG ||
1059 cmd == MachO::LC_LOADFVMLIB ||
1060 cmd == MachO::LC_IDFVMLIB ||
1061 cmd == MachO::LC_IDENT ||
1062 cmd == MachO::LC_FVMFILE ||
1063 cmd == MachO::LC_PREPAGE ||
1064 cmd == MachO::LC_PREBOUND_DYLIB ||
1065 cmd == MachO::LC_TWOLEVEL_HINTS ||
1066 cmd == MachO::LC_PREBIND_CKSUM)
1067 return true;
1068 return false;
1069}
1070
Lang Hames82627642016-03-25 21:59:14 +00001071Expected<std::unique_ptr<MachOObjectFile>>
1072MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001073 bool Is64Bits, uint32_t UniversalCputype,
1074 uint32_t UniversalIndex) {
Mehdi Amini41af4302016-11-11 04:28:40 +00001075 Error Err = Error::success();
Lang Hames82627642016-03-25 21:59:14 +00001076 std::unique_ptr<MachOObjectFile> Obj(
1077 new MachOObjectFile(std::move(Object), IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001078 Is64Bits, Err, UniversalCputype,
1079 UniversalIndex));
Lang Hames82627642016-03-25 21:59:14 +00001080 if (Err)
1081 return std::move(Err);
1082 return std::move(Obj);
1083}
1084
Rafael Espindola48af1c22014-08-19 18:44:46 +00001085MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Kevin Enderby79d6c632016-10-24 21:15:11 +00001086 bool Is64bits, Error &Err,
1087 uint32_t UniversalCputype,
1088 uint32_t UniversalIndex)
Rafael Espindola48af1c22014-08-19 18:44:46 +00001089 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +00001090 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +00001091 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
1092 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
1093 HasPageZeroSegment(false) {
Lang Hames5e51a2e2016-07-22 16:11:25 +00001094 ErrorAsOutParameter ErrAsOutParam(&Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001095 uint64_t SizeOfHeaders;
Kevin Enderby79d6c632016-10-24 21:15:11 +00001096 uint32_t cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001097 if (is64Bit()) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001098 parseHeader(*this, Header64, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001099 SizeOfHeaders = sizeof(MachO::mach_header_64);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001100 cputype = Header64.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001101 } else {
Lang Hames697e7cd2016-12-04 01:56:10 +00001102 parseHeader(*this, Header, Err);
Kevin Enderbyc614d282016-08-12 20:10:25 +00001103 SizeOfHeaders = sizeof(MachO::mach_header);
Kevin Enderby79d6c632016-10-24 21:15:11 +00001104 cputype = Header.cputype;
Kevin Enderby87025742016-04-13 21:17:58 +00001105 }
Lang Hames9e964f32016-03-25 17:25:34 +00001106 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +00001107 return;
Kevin Enderbyc614d282016-08-12 20:10:25 +00001108 SizeOfHeaders += getHeader().sizeofcmds;
1109 if (getData().data() + SizeOfHeaders > getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001110 Err = malformedError("load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +00001111 return;
1112 }
Kevin Enderby79d6c632016-10-24 21:15:11 +00001113 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1114 Err = malformedError("universal header architecture: " +
1115 Twine(UniversalIndex) + "'s cputype does not match "
1116 "object file's mach header");
1117 return;
1118 }
Kevin Enderbyd5039402016-10-31 20:29:48 +00001119 std::list<MachOElement> Elements;
1120 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001121
1122 uint32_t LoadCommandCount = getHeader().ncmds;
Lang Hames9e964f32016-03-25 17:25:34 +00001123 LoadCommandInfo Load;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001124 if (LoadCommandCount != 0) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001125 if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001126 Load = *LoadOrErr;
1127 else {
1128 Err = LoadOrErr.takeError();
1129 return;
1130 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001131 }
Lang Hames9e964f32016-03-25 17:25:34 +00001132
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001133 const char *DyldIdLoadCmd = nullptr;
Kevin Enderby90986e62016-09-26 21:11:03 +00001134 const char *FuncStartsLoadCmd = nullptr;
1135 const char *SplitInfoLoadCmd = nullptr;
1136 const char *CodeSignDrsLoadCmd = nullptr;
Kevin Enderby89baf992016-10-18 20:24:12 +00001137 const char *CodeSignLoadCmd = nullptr;
Kevin Enderby32359db2016-09-28 21:20:45 +00001138 const char *VersLoadCmd = nullptr;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001139 const char *SourceLoadCmd = nullptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001140 const char *EntryPointLoadCmd = nullptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001141 const char *EncryptLoadCmd = nullptr;
Kevin Enderby6f695822016-10-18 17:54:17 +00001142 const char *RoutinesLoadCmd = nullptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001143 const char *UnixThreadLoadCmd = nullptr;
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001144 const char *TwoLevelHintsLoadCmd = nullptr;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001145 for (unsigned I = 0; I < LoadCommandCount; ++I) {
Kevin Enderby1851a822016-07-07 22:11:42 +00001146 if (is64Bit()) {
1147 if (Load.C.cmdsize % 8 != 0) {
1148 // We have a hack here to allow 64-bit Mach-O core files to have
1149 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1150 // allowed since the macOS kernel produces them.
1151 if (getHeader().filetype != MachO::MH_CORE ||
1152 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1153 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1154 "multiple of 8");
1155 return;
1156 }
1157 }
1158 } else {
1159 if (Load.C.cmdsize % 4 != 0) {
1160 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1161 "multiple of 4");
1162 return;
1163 }
1164 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001165 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001166 if (Load.C.cmd == MachO::LC_SYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001167 if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001168 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001169 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001170 if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001171 Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001172 return;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001173 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001174 if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001175 "LC_DATA_IN_CODE", Elements,
1176 "data in code info")))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001177 return;
Kevin Enderby9a509442015-01-27 21:28:24 +00001178 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001179 if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001180 "LC_LINKER_OPTIMIZATION_HINT",
1181 Elements, "linker optimization "
1182 "hints")))
Kevin Enderby9a509442015-01-27 21:28:24 +00001183 return;
Kevin Enderby90986e62016-09-26 21:11:03 +00001184 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001185 if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001186 "LC_FUNCTION_STARTS", Elements,
1187 "function starts data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001188 return;
1189 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001190 if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001191 "LC_SEGMENT_SPLIT_INFO", Elements,
1192 "split info data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001193 return;
1194 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001195 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001196 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1197 "code signing RDs data")))
Kevin Enderby90986e62016-09-26 21:11:03 +00001198 return;
Kevin Enderby89baf992016-10-18 20:24:12 +00001199 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001200 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001201 "LC_CODE_SIGNATURE", Elements,
1202 "code signature data")))
Kevin Enderby89baf992016-10-18 20:24:12 +00001203 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001204 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001205 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001206 "LC_DYLD_INFO", Elements)))
David Majnemer73cc6ff2014-11-13 19:48:56 +00001207 return;
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001208 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001209 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001210 "LC_DYLD_INFO_ONLY", Elements)))
Kevin Enderbyf76b56c2016-09-13 21:42:28 +00001211 return;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001212 } else if (Load.C.cmd == MachO::LC_UUID) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001213 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1214 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1215 "cmdsize");
1216 return;
1217 }
David Majnemer73cc6ff2014-11-13 19:48:56 +00001218 if (UuidLoadCmd) {
Kevin Enderbye71e13c2016-09-21 20:03:09 +00001219 Err = malformedError("more than one LC_UUID command");
David Majnemer73cc6ff2014-11-13 19:48:56 +00001220 return;
1221 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00001222 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001223 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001224 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1225 MachO::section_64>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001226 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001227 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001228 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +00001229 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderbyc614d282016-08-12 20:10:25 +00001230 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1231 MachO::section>(
Lang Hames697e7cd2016-12-04 01:56:10 +00001232 *this, Load, Sections, HasPageZeroSegment, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001233 "LC_SEGMENT", SizeOfHeaders, Elements)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +00001234 return;
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001235 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001236 if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001237 return;
1238 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001239 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001240 return;
1241 Libraries.push_back(Load.Ptr);
1242 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001243 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001244 return;
1245 Libraries.push_back(Load.Ptr);
1246 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001247 if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001248 return;
1249 Libraries.push_back(Load.Ptr);
1250 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001251 if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001252 return;
1253 Libraries.push_back(Load.Ptr);
1254 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001255 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001256 return;
Kevin Enderby980b2582014-06-05 21:21:57 +00001257 Libraries.push_back(Load.Ptr);
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001258 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001259 if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001260 return;
1261 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001262 if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001263 return;
1264 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001265 if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
Kevin Enderby3e490ef2016-09-27 23:24:13 +00001266 return;
Kevin Enderby32359db2016-09-28 21:20:45 +00001267 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001268 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001269 "LC_VERSION_MIN_MACOSX")))
1270 return;
1271 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001272 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001273 "LC_VERSION_MIN_IPHONEOS")))
1274 return;
1275 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001276 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001277 "LC_VERSION_MIN_TVOS")))
1278 return;
1279 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001280 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
Kevin Enderby32359db2016-09-28 21:20:45 +00001281 "LC_VERSION_MIN_WATCHOS")))
1282 return;
Kevin Enderby76966bf2016-09-28 23:16:01 +00001283 } else if (Load.C.cmd == MachO::LC_RPATH) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001284 if ((Err = checkRpathCommand(*this, Load, I)))
Kevin Enderby76966bf2016-09-28 23:16:01 +00001285 return;
Kevin Enderby245be3e2016-09-29 17:45:23 +00001286 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1287 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1288 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1289 " has incorrect cmdsize");
1290 return;
1291 }
1292 if (SourceLoadCmd) {
1293 Err = malformedError("more than one LC_SOURCE_VERSION command");
1294 return;
1295 }
1296 SourceLoadCmd = Load.Ptr;
Kevin Enderby4f229d82016-09-29 21:07:29 +00001297 } else if (Load.C.cmd == MachO::LC_MAIN) {
1298 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1299 Err = malformedError("LC_MAIN command " + Twine(I) +
1300 " has incorrect cmdsize");
1301 return;
1302 }
1303 if (EntryPointLoadCmd) {
1304 Err = malformedError("more than one LC_MAIN command");
1305 return;
1306 }
1307 EntryPointLoadCmd = Load.Ptr;
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001308 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1309 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1310 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1311 " has incorrect cmdsize");
1312 return;
1313 }
1314 MachO::encryption_info_command E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001315 getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1316 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001317 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1318 return;
1319 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1320 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1321 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1322 " has incorrect cmdsize");
1323 return;
1324 }
1325 MachO::encryption_info_command_64 E =
Lang Hames697e7cd2016-12-04 01:56:10 +00001326 getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1327 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
Kevin Enderbyf993d6e2016-10-04 20:37:43 +00001328 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1329 return;
Kevin Enderby68fffa82016-10-11 21:04:39 +00001330 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001331 if ((Err = checkLinkerOptCommand(*this, Load, I)))
Kevin Enderby68fffa82016-10-11 21:04:39 +00001332 return;
Kevin Enderby2490de02016-10-17 22:09:25 +00001333 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1334 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1335 Err = malformedError("load command " + Twine(I) +
1336 " LC_SUB_FRAMEWORK cmdsize too small");
1337 return;
1338 }
1339 MachO::sub_framework_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001340 getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1341 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
Kevin Enderby2490de02016-10-17 22:09:25 +00001342 sizeof(MachO::sub_framework_command),
1343 "sub_framework_command", S.umbrella,
1344 "umbrella")))
1345 return;
1346 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1347 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1348 Err = malformedError("load command " + Twine(I) +
1349 " LC_SUB_UMBRELLA cmdsize too small");
1350 return;
1351 }
1352 MachO::sub_umbrella_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001353 getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1354 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
Kevin Enderby2490de02016-10-17 22:09:25 +00001355 sizeof(MachO::sub_umbrella_command),
1356 "sub_umbrella_command", S.sub_umbrella,
1357 "sub_umbrella")))
1358 return;
1359 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1360 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1361 Err = malformedError("load command " + Twine(I) +
1362 " LC_SUB_LIBRARY cmdsize too small");
1363 return;
1364 }
1365 MachO::sub_library_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001366 getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1367 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
Kevin Enderby2490de02016-10-17 22:09:25 +00001368 sizeof(MachO::sub_library_command),
1369 "sub_library_command", S.sub_library,
1370 "sub_library")))
1371 return;
1372 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1373 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1374 Err = malformedError("load command " + Twine(I) +
1375 " LC_SUB_CLIENT cmdsize too small");
1376 return;
1377 }
1378 MachO::sub_client_command S =
Lang Hames697e7cd2016-12-04 01:56:10 +00001379 getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1380 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
Kevin Enderby2490de02016-10-17 22:09:25 +00001381 sizeof(MachO::sub_client_command),
1382 "sub_client_command", S.client, "client")))
1383 return;
Kevin Enderby6f695822016-10-18 17:54:17 +00001384 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1385 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1386 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1387 " has incorrect cmdsize");
1388 return;
1389 }
1390 if (RoutinesLoadCmd) {
1391 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1392 "command");
1393 return;
1394 }
1395 RoutinesLoadCmd = Load.Ptr;
1396 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1397 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1398 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1399 " has incorrect cmdsize");
1400 return;
1401 }
1402 if (RoutinesLoadCmd) {
1403 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1404 "command");
1405 return;
1406 }
1407 RoutinesLoadCmd = Load.Ptr;
Kevin Enderby210030b2016-10-19 23:44:34 +00001408 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001409 if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001410 return;
1411 if (UnixThreadLoadCmd) {
1412 Err = malformedError("more than one LC_UNIXTHREAD command");
1413 return;
1414 }
1415 UnixThreadLoadCmd = Load.Ptr;
1416 } else if (Load.C.cmd == MachO::LC_THREAD) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001417 if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
Kevin Enderby210030b2016-10-19 23:44:34 +00001418 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001419 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001420 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001421 if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
Kevin Enderbyfbebe162016-11-02 21:08:39 +00001422 &TwoLevelHintsLoadCmd, Elements)))
Kevin Enderbyc8bb4222016-10-20 20:10:30 +00001423 return;
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001424 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1425 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1426 Twine(Load.C.cmd) + " is obsolete and not "
1427 "supported");
1428 return;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001429 }
Kevin Enderbybc5c29a2016-10-27 20:59:10 +00001430 // TODO: generate a error for unknown load commands by default. But still
1431 // need work out an approach to allow or not allow unknown values like this
1432 // as an option for some uses like lldb.
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001433 if (I < LoadCommandCount - 1) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001434 if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +00001435 Load = *LoadOrErr;
1436 else {
1437 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001438 return;
1439 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +00001440 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001441 }
Kevin Enderby1829c682016-01-22 22:49:55 +00001442 if (!SymtabLoadCmd) {
1443 if (DysymtabLoadCmd) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001444 Err = malformedError("contains LC_DYSYMTAB load command without a "
Kevin Enderby89134962016-05-05 23:41:05 +00001445 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +00001446 return;
1447 }
1448 } else if (DysymtabLoadCmd) {
1449 MachO::symtab_command Symtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001450 getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001451 MachO::dysymtab_command Dysymtab =
Lang Hames697e7cd2016-12-04 01:56:10 +00001452 getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby1829c682016-01-22 22:49:55 +00001453 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001454 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001455 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001456 return;
1457 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001458 uint64_t BigSize = Dysymtab.ilocalsym;
1459 BigSize += Dysymtab.nlocalsym;
1460 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001461 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001462 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001463 return;
1464 }
1465 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001466 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001467 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001468 return;
1469 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001470 BigSize = Dysymtab.iextdefsym;
1471 BigSize += Dysymtab.nextdefsym;
1472 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001473 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
Kevin Enderby89134962016-05-05 23:41:05 +00001474 "load command extends past the end of the symbol "
1475 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001476 return;
1477 }
1478 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001479 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
Kevin Enderby89134962016-05-05 23:41:05 +00001480 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001481 return;
1482 }
Kevin Enderby5e55d172016-04-21 20:29:49 +00001483 BigSize = Dysymtab.iundefsym;
1484 BigSize += Dysymtab.nundefsym;
1485 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001486 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
Kevin Enderby89134962016-05-05 23:41:05 +00001487 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +00001488 return;
1489 }
1490 }
Kevin Enderbyfc0929a2016-09-20 20:14:14 +00001491 if ((getHeader().filetype == MachO::MH_DYLIB ||
1492 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1493 DyldIdLoadCmd == nullptr) {
1494 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1495 "filetype");
1496 return;
1497 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001498 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +00001499
1500 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001501}
1502
Kevin Enderby22fc0072016-11-14 20:57:04 +00001503Error MachOObjectFile::checkSymbolTable() const {
1504 uint32_t Flags = 0;
1505 if (is64Bit()) {
1506 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1507 Flags = H_64.flags;
1508 } else {
1509 MachO::mach_header H = MachOObjectFile::getHeader();
1510 Flags = H.flags;
1511 }
1512 uint8_t NType = 0;
1513 uint8_t NSect = 0;
1514 uint16_t NDesc = 0;
1515 uint32_t NStrx = 0;
1516 uint64_t NValue = 0;
1517 uint32_t SymbolIndex = 0;
1518 MachO::symtab_command S = getSymtabLoadCommand();
1519 for (const SymbolRef &Symbol : symbols()) {
1520 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1521 if (is64Bit()) {
1522 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1523 NType = STE_64.n_type;
1524 NSect = STE_64.n_sect;
1525 NDesc = STE_64.n_desc;
1526 NStrx = STE_64.n_strx;
1527 NValue = STE_64.n_value;
1528 } else {
1529 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1530 NType = STE.n_type;
1531 NType = STE.n_type;
1532 NSect = STE.n_sect;
1533 NDesc = STE.n_desc;
1534 NStrx = STE.n_strx;
1535 NValue = STE.n_value;
1536 }
1537 if ((NType & MachO::N_STAB) == 0 &&
1538 (NType & MachO::N_TYPE) == MachO::N_SECT) {
1539 if (NSect == 0 || NSect > Sections.size())
1540 return malformedError("bad section index: " + Twine((int)NSect) +
1541 " for symbol at index " + Twine(SymbolIndex));
1542 }
1543 if ((NType & MachO::N_STAB) == 0 &&
1544 (NType & MachO::N_TYPE) == MachO::N_INDR) {
1545 if (NValue >= S.strsize)
1546 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1547 "the end of string table, for N_INDR symbol at "
1548 "index " + Twine(SymbolIndex));
1549 }
1550 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1551 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1552 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1553 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1554 if (LibraryOrdinal != 0 &&
1555 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1556 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1557 LibraryOrdinal - 1 >= Libraries.size() ) {
1558 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1559 " for symbol at index " + Twine(SymbolIndex));
1560 }
1561 }
1562 if (NStrx >= S.strsize)
1563 return malformedError("bad string table index: " + Twine((int)NStrx) +
1564 " past the end of string table, for symbol at "
1565 "index " + Twine(SymbolIndex));
1566 SymbolIndex++;
1567 }
1568 return Error::success();
1569}
1570
Rafael Espindola5e812af2014-01-30 02:49:50 +00001571void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00001572 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001573 sizeof(MachO::nlist_64) :
1574 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +00001575 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001576}
1577
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001578Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001579 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001580 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001581 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001582 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001583 return malformedError("bad string index: " + Twine(Entry.n_strx) +
Kevin Enderby89134962016-05-05 23:41:05 +00001584 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001585 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00001586 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001587}
1588
Rafael Espindola0e77a942014-12-10 20:46:55 +00001589unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1590 DataRefImpl DRI = Sec.getRawDataRefImpl();
Lang Hames697e7cd2016-12-04 01:56:10 +00001591 uint32_t Flags = getSectionFlags(*this, DRI);
Rafael Espindola0e77a942014-12-10 20:46:55 +00001592 return Flags & MachO::SECTION_TYPE;
1593}
1594
Rafael Espindola59128922015-06-24 18:14:41 +00001595uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1596 if (is64Bit()) {
1597 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1598 return Entry.n_value;
1599 }
1600 MachO::nlist Entry = getSymbolTableEntry(Sym);
1601 return Entry.n_value;
1602}
1603
Kevin Enderby980b2582014-06-05 21:21:57 +00001604// getIndirectName() returns the name of the alias'ed symbol who's string table
1605// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +00001606std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1607 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001608 StringRef StringTable = getStringTableData();
Lang Hames697e7cd2016-12-04 01:56:10 +00001609 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Rafael Espindola59128922015-06-24 18:14:41 +00001610 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1611 return object_error::parse_failed;
1612 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +00001613 if (NValue >= StringTable.size())
1614 return object_error::parse_failed;
1615 const char *Start = &StringTable.data()[NValue];
1616 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +00001617 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001618}
1619
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +00001620uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +00001621 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +00001622}
1623
Kevin Enderby931cb652016-06-24 18:24:42 +00001624Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
Rafael Espindolaed067c42015-07-03 18:19:00 +00001625 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001626}
1627
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001628uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +00001629 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001630 if (flags & SymbolRef::SF_Common) {
Lang Hames697e7cd2016-12-04 01:56:10 +00001631 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001632 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001633 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +00001634 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001635}
1636
Rafael Espindolad7a32ea2015-06-24 10:20:30 +00001637uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001638 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001639}
1640
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001641Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001642MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001643 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001644 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001645
Rafael Espindola56f976f2013-04-18 18:08:55 +00001646 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001647 if (n_type & MachO::N_STAB)
1648 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001649
Charles Davis74ec8b02013-08-27 05:00:13 +00001650 switch (n_type & MachO::N_TYPE) {
1651 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001652 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +00001653 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001654 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001655 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001656 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001657 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +00001658 if (Sec->isData() || Sec->isBSS())
1659 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001660 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001661 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +00001662 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001663}
1664
Rafael Espindola20122a42014-01-31 20:57:12 +00001665uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001666 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001667
Charles Davis8bdfafd2013-09-01 04:28:48 +00001668 uint8_t MachOType = Entry.n_type;
1669 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001670
Rafael Espindola20122a42014-01-31 20:57:12 +00001671 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001672
Tim Northovereaef0742014-05-30 13:22:59 +00001673 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1674 Result |= SymbolRef::SF_Indirect;
1675
Rafael Espindolaa1356322013-11-02 05:03:24 +00001676 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001677 Result |= SymbolRef::SF_FormatSpecific;
1678
Charles Davis74ec8b02013-08-27 05:00:13 +00001679 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001680 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +00001681 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +00001682 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001683 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +00001684 else
1685 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +00001686 }
Lang Hames7e0692b2015-01-15 22:33:30 +00001687
1688 if (!(MachOType & MachO::N_PEXT))
1689 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001690 }
1691
Charles Davis74ec8b02013-08-27 05:00:13 +00001692 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +00001693 Result |= SymbolRef::SF_Weak;
1694
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001695 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1696 Result |= SymbolRef::SF_Thumb;
1697
Charles Davis74ec8b02013-08-27 05:00:13 +00001698 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001699 Result |= SymbolRef::SF_Absolute;
1700
Rafael Espindola20122a42014-01-31 20:57:12 +00001701 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001702}
1703
Kevin Enderby7bd8d992016-05-02 20:28:12 +00001704Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +00001705MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001706 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001707 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001708
Rafael Espindola8bab8892015-08-07 23:27:14 +00001709 if (index == 0)
1710 return section_end();
1711 DataRefImpl DRI;
1712 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001713 if (DRI.d.a >= Sections.size()){
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00001714 return malformedError("bad section index: " + Twine((int)index) +
Kevin Enderby89134962016-05-05 23:41:05 +00001715 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +00001716 }
Rafael Espindola8bab8892015-08-07 23:27:14 +00001717 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001718}
1719
Rafael Espindola6bf32212015-06-24 19:57:32 +00001720unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1721 MachO::nlist_base Entry =
Lang Hames697e7cd2016-12-04 01:56:10 +00001722 getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
Rafael Espindola6bf32212015-06-24 19:57:32 +00001723 return Entry.n_sect - 1;
1724}
1725
Rafael Espindola5e812af2014-01-30 02:49:50 +00001726void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001727 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001728}
1729
Rafael Espindola3acea392014-06-12 21:46:39 +00001730std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1731 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001732 ArrayRef<char> Raw = getSectionRawName(Sec);
1733 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +00001734 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001735}
1736
Rafael Espindola80291272014-10-08 15:28:58 +00001737uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1738 if (is64Bit())
1739 return getSection64(Sec).addr;
1740 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001741}
1742
Rafael Espindola80291272014-10-08 15:28:58 +00001743uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +00001744 // In the case if a malformed Mach-O file where the section offset is past
1745 // the end of the file or some part of the section size is past the end of
1746 // the file return a size of zero or a size that covers the rest of the file
1747 // but does not extend past the end of the file.
1748 uint32_t SectOffset, SectType;
1749 uint64_t SectSize;
1750
1751 if (is64Bit()) {
1752 MachO::section_64 Sect = getSection64(Sec);
1753 SectOffset = Sect.offset;
1754 SectSize = Sect.size;
1755 SectType = Sect.flags & MachO::SECTION_TYPE;
1756 } else {
1757 MachO::section Sect = getSection(Sec);
1758 SectOffset = Sect.offset;
1759 SectSize = Sect.size;
1760 SectType = Sect.flags & MachO::SECTION_TYPE;
1761 }
1762 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1763 return SectSize;
1764 uint64_t FileSize = getData().size();
1765 if (SectOffset > FileSize)
1766 return 0;
1767 if (FileSize - SectOffset < SectSize)
1768 return FileSize - SectOffset;
1769 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001770}
1771
Rafael Espindola3acea392014-06-12 21:46:39 +00001772std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1773 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001774 uint32_t Offset;
1775 uint64_t Size;
1776
1777 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001778 MachO::section_64 Sect = getSection64(Sec);
1779 Offset = Sect.offset;
1780 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001781 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001782 MachO::section Sect = getSection(Sec);
1783 Offset = Sect.offset;
1784 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001785 }
1786
1787 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +00001788 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +00001789}
1790
Rafael Espindola80291272014-10-08 15:28:58 +00001791uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001792 uint32_t Align;
1793 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001794 MachO::section_64 Sect = getSection64(Sec);
1795 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001796 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001797 MachO::section Sect = getSection(Sec);
1798 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001799 }
1800
Rafael Espindola80291272014-10-08 15:28:58 +00001801 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001802}
1803
George Rimar401e4e52016-05-24 12:48:46 +00001804bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1805 return false;
1806}
1807
Rafael Espindola80291272014-10-08 15:28:58 +00001808bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001809 uint32_t Flags = getSectionFlags(*this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +00001810 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001811}
1812
Rafael Espindola80291272014-10-08 15:28:58 +00001813bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001814 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001815 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001816 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1817 !(SectionType == MachO::S_ZEROFILL ||
1818 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +00001819}
1820
Rafael Espindola80291272014-10-08 15:28:58 +00001821bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00001822 uint32_t Flags = getSectionFlags(*this, Sec);
Kevin Enderby403258f2014-05-19 20:36:02 +00001823 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +00001824 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1825 (SectionType == MachO::S_ZEROFILL ||
1826 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +00001827}
1828
Rafael Espindola6bf32212015-06-24 19:57:32 +00001829unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1830 return Sec.getRawDataRefImpl().d.a;
1831}
1832
Rafael Espindola80291272014-10-08 15:28:58 +00001833bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +00001834 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +00001835 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +00001836}
1837
Steven Wuf2fe0142016-02-29 19:40:10 +00001838bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1839 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1840 StringRef SectName;
1841 if (!getSectionName(Sec, SectName))
1842 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1843 return false;
1844}
1845
Rui Ueyamabc654b12013-09-27 21:47:05 +00001846relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001847 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001848 Ret.d.a = Sec.d.a;
1849 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +00001850 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +00001851}
Rafael Espindolac0406e12013-04-08 20:45:01 +00001852
Rafael Espindola56f976f2013-04-18 18:08:55 +00001853relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +00001854MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +00001855 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001856 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001857 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001858 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001859 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001860 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +00001861 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001862 }
Eric Christopher7b015c72011-04-22 03:19:48 +00001863
Rafael Espindola56f976f2013-04-18 18:08:55 +00001864 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +00001865 Ret.d.a = Sec.d.a;
1866 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001867 return relocation_iterator(RelocationRef(Ret, this));
1868}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001869
Rafael Espindola5e812af2014-01-30 02:49:50 +00001870void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00001871 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +00001872}
Owen Anderson171f4852011-10-24 23:20:07 +00001873
Rafael Espindola96d071c2015-06-29 23:29:12 +00001874uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +00001875 assert(getHeader().filetype == MachO::MH_OBJECT &&
1876 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001877 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +00001878 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +00001879}
1880
Rafael Espindola806f0062013-06-05 01:33:53 +00001881symbol_iterator
1882MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001883 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +00001884 if (isRelocationScattered(RE))
1885 return symbol_end();
1886
Rafael Espindola56f976f2013-04-18 18:08:55 +00001887 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
1888 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +00001889 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +00001890 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +00001891
Charles Davis8bdfafd2013-09-01 04:28:48 +00001892 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +00001893 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001894 sizeof(MachO::nlist_64) :
1895 sizeof(MachO::nlist);
1896 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001897 DataRefImpl Sym;
Lang Hames697e7cd2016-12-04 01:56:10 +00001898 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +00001899 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001900}
1901
Keno Fischerc780e8e2015-05-21 21:24:32 +00001902section_iterator
1903MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
1904 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
1905}
1906
Rafael Espindola99c041b2015-06-30 01:53:01 +00001907uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001908 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +00001909 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001910}
1911
Rafael Espindola41bb4322015-06-30 04:08:37 +00001912void MachOObjectFile::getRelocationTypeName(
1913 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001914 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +00001915 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001916
1917 unsigned Arch = this->getArch();
1918
1919 switch (Arch) {
1920 case Triple::x86: {
1921 static const char *const Table[] = {
1922 "GENERIC_RELOC_VANILLA",
1923 "GENERIC_RELOC_PAIR",
1924 "GENERIC_RELOC_SECTDIFF",
1925 "GENERIC_RELOC_PB_LA_PTR",
1926 "GENERIC_RELOC_LOCAL_SECTDIFF",
1927 "GENERIC_RELOC_TLV" };
1928
Eric Christopher13250cb2013-12-06 02:33:38 +00001929 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001930 res = "Unknown";
1931 else
1932 res = Table[RType];
1933 break;
1934 }
1935 case Triple::x86_64: {
1936 static const char *const Table[] = {
1937 "X86_64_RELOC_UNSIGNED",
1938 "X86_64_RELOC_SIGNED",
1939 "X86_64_RELOC_BRANCH",
1940 "X86_64_RELOC_GOT_LOAD",
1941 "X86_64_RELOC_GOT",
1942 "X86_64_RELOC_SUBTRACTOR",
1943 "X86_64_RELOC_SIGNED_1",
1944 "X86_64_RELOC_SIGNED_2",
1945 "X86_64_RELOC_SIGNED_4",
1946 "X86_64_RELOC_TLV" };
1947
1948 if (RType > 9)
1949 res = "Unknown";
1950 else
1951 res = Table[RType];
1952 break;
1953 }
1954 case Triple::arm: {
1955 static const char *const Table[] = {
1956 "ARM_RELOC_VANILLA",
1957 "ARM_RELOC_PAIR",
1958 "ARM_RELOC_SECTDIFF",
1959 "ARM_RELOC_LOCAL_SECTDIFF",
1960 "ARM_RELOC_PB_LA_PTR",
1961 "ARM_RELOC_BR24",
1962 "ARM_THUMB_RELOC_BR22",
1963 "ARM_THUMB_32BIT_BRANCH",
1964 "ARM_RELOC_HALF",
1965 "ARM_RELOC_HALF_SECTDIFF" };
1966
1967 if (RType > 9)
1968 res = "Unknown";
1969 else
1970 res = Table[RType];
1971 break;
1972 }
Tim Northover00ed9962014-03-29 10:18:08 +00001973 case Triple::aarch64: {
1974 static const char *const Table[] = {
1975 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
1976 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
1977 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
1978 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
1979 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
1980 "ARM64_RELOC_ADDEND"
1981 };
1982
1983 if (RType >= array_lengthof(Table))
1984 res = "Unknown";
1985 else
1986 res = Table[RType];
1987 break;
1988 }
Rafael Espindola56f976f2013-04-18 18:08:55 +00001989 case Triple::ppc: {
1990 static const char *const Table[] = {
1991 "PPC_RELOC_VANILLA",
1992 "PPC_RELOC_PAIR",
1993 "PPC_RELOC_BR14",
1994 "PPC_RELOC_BR24",
1995 "PPC_RELOC_HI16",
1996 "PPC_RELOC_LO16",
1997 "PPC_RELOC_HA16",
1998 "PPC_RELOC_LO14",
1999 "PPC_RELOC_SECTDIFF",
2000 "PPC_RELOC_PB_LA_PTR",
2001 "PPC_RELOC_HI16_SECTDIFF",
2002 "PPC_RELOC_LO16_SECTDIFF",
2003 "PPC_RELOC_HA16_SECTDIFF",
2004 "PPC_RELOC_JBSR",
2005 "PPC_RELOC_LO14_SECTDIFF",
2006 "PPC_RELOC_LOCAL_SECTDIFF" };
2007
Eric Christopher13250cb2013-12-06 02:33:38 +00002008 if (RType > 15)
2009 res = "Unknown";
2010 else
2011 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +00002012 break;
2013 }
2014 case Triple::UnknownArch:
2015 res = "Unknown";
2016 break;
2017 }
2018 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +00002019}
2020
Keno Fischer281b6942015-05-30 19:44:53 +00002021uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2022 MachO::any_relocation_info RE = getRelocation(Rel);
2023 return getAnyRelocationLength(RE);
2024}
2025
Kevin Enderby980b2582014-06-05 21:21:57 +00002026//
2027// guessLibraryShortName() is passed a name of a dynamic library and returns a
2028// guess on what the short name is. Then name is returned as a substring of the
2029// StringRef Name passed in. The name of the dynamic library is recognized as
2030// a framework if it has one of the two following forms:
2031// Foo.framework/Versions/A/Foo
2032// Foo.framework/Foo
2033// Where A and Foo can be any string. And may contain a trailing suffix
2034// starting with an underbar. If the Name is recognized as a framework then
2035// isFramework is set to true else it is set to false. If the Name has a
2036// suffix then Suffix is set to the substring in Name that contains the suffix
2037// else it is set to a NULL StringRef.
2038//
2039// The Name of the dynamic library is recognized as a library name if it has
2040// one of the two following forms:
2041// libFoo.A.dylib
2042// libFoo.dylib
2043// The library may have a suffix trailing the name Foo of the form:
2044// libFoo_profile.A.dylib
2045// libFoo_profile.dylib
2046//
2047// The Name of the dynamic library is also recognized as a library name if it
2048// has the following form:
2049// Foo.qtx
2050//
2051// If the Name of the dynamic library is none of the forms above then a NULL
2052// StringRef is returned.
2053//
2054StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2055 bool &isFramework,
2056 StringRef &Suffix) {
2057 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2058 size_t a, b, c, d, Idx;
2059
2060 isFramework = false;
2061 Suffix = StringRef();
2062
2063 // Pull off the last component and make Foo point to it
2064 a = Name.rfind('/');
2065 if (a == Name.npos || a == 0)
2066 goto guess_library;
2067 Foo = Name.slice(a+1, Name.npos);
2068
2069 // Look for a suffix starting with a '_'
2070 Idx = Foo.rfind('_');
2071 if (Idx != Foo.npos && Foo.size() >= 2) {
2072 Suffix = Foo.slice(Idx, Foo.npos);
2073 Foo = Foo.slice(0, Idx);
2074 }
2075
2076 // First look for the form Foo.framework/Foo
2077 b = Name.rfind('/', a);
2078 if (b == Name.npos)
2079 Idx = 0;
2080 else
2081 Idx = b+1;
2082 F = Name.slice(Idx, Idx + Foo.size());
2083 DotFramework = Name.slice(Idx + Foo.size(),
2084 Idx + Foo.size() + sizeof(".framework/")-1);
2085 if (F == Foo && DotFramework == ".framework/") {
2086 isFramework = true;
2087 return Foo;
2088 }
2089
2090 // Next look for the form Foo.framework/Versions/A/Foo
2091 if (b == Name.npos)
2092 goto guess_library;
2093 c = Name.rfind('/', b);
2094 if (c == Name.npos || c == 0)
2095 goto guess_library;
2096 V = Name.slice(c+1, Name.npos);
2097 if (!V.startswith("Versions/"))
2098 goto guess_library;
2099 d = Name.rfind('/', c);
2100 if (d == Name.npos)
2101 Idx = 0;
2102 else
2103 Idx = d+1;
2104 F = Name.slice(Idx, Idx + Foo.size());
2105 DotFramework = Name.slice(Idx + Foo.size(),
2106 Idx + Foo.size() + sizeof(".framework/")-1);
2107 if (F == Foo && DotFramework == ".framework/") {
2108 isFramework = true;
2109 return Foo;
2110 }
2111
2112guess_library:
2113 // pull off the suffix after the "." and make a point to it
2114 a = Name.rfind('.');
2115 if (a == Name.npos || a == 0)
2116 return StringRef();
2117 Dylib = Name.slice(a, Name.npos);
2118 if (Dylib != ".dylib")
2119 goto guess_qtx;
2120
2121 // First pull off the version letter for the form Foo.A.dylib if any.
2122 if (a >= 3) {
2123 Dot = Name.slice(a-2, a-1);
2124 if (Dot == ".")
2125 a = a - 2;
2126 }
2127
2128 b = Name.rfind('/', a);
2129 if (b == Name.npos)
2130 b = 0;
2131 else
2132 b = b+1;
2133 // ignore any suffix after an underbar like Foo_profile.A.dylib
2134 Idx = Name.find('_', b);
2135 if (Idx != Name.npos && Idx != b) {
2136 Lib = Name.slice(b, Idx);
2137 Suffix = Name.slice(Idx, a);
2138 }
2139 else
2140 Lib = Name.slice(b, a);
2141 // There are incorrect library names of the form:
2142 // libATS.A_profile.dylib so check for these.
2143 if (Lib.size() >= 3) {
2144 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2145 if (Dot == ".")
2146 Lib = Lib.slice(0, Lib.size()-2);
2147 }
2148 return Lib;
2149
2150guess_qtx:
2151 Qtx = Name.slice(a, Name.npos);
2152 if (Qtx != ".qtx")
2153 return StringRef();
2154 b = Name.rfind('/', a);
2155 if (b == Name.npos)
2156 Lib = Name.slice(0, a);
2157 else
2158 Lib = Name.slice(b+1, a);
2159 // There are library names of the form: QT.A.qtx so check for these.
2160 if (Lib.size() >= 3) {
2161 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2162 if (Dot == ".")
2163 Lib = Lib.slice(0, Lib.size()-2);
2164 }
2165 return Lib;
2166}
2167
2168// getLibraryShortNameByIndex() is used to get the short name of the library
2169// for an undefined symbol in a linked Mach-O binary that was linked with the
2170// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2171// It is passed the index (0 - based) of the library as translated from
2172// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00002173std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00002174 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00002175 if (Index >= Libraries.size())
2176 return object_error::parse_failed;
2177
Kevin Enderby980b2582014-06-05 21:21:57 +00002178 // If the cache of LibrariesShortNames is not built up do that first for
2179 // all the Libraries.
2180 if (LibrariesShortNames.size() == 0) {
2181 for (unsigned i = 0; i < Libraries.size(); i++) {
2182 MachO::dylib_command D =
Lang Hames697e7cd2016-12-04 01:56:10 +00002183 getStruct<MachO::dylib_command>(*this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00002184 if (D.dylib.name >= D.cmdsize)
2185 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00002186 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00002187 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00002188 if (D.dylib.name+Name.size() >= D.cmdsize)
2189 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00002190 StringRef Suffix;
2191 bool isFramework;
2192 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00002193 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00002194 LibrariesShortNames.push_back(Name);
2195 else
2196 LibrariesShortNames.push_back(shortName);
2197 }
2198 }
2199
2200 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00002201 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00002202}
2203
Rafael Espindola76ad2322015-07-06 14:55:37 +00002204section_iterator
2205MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2206 DataRefImpl Sec;
2207 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2208 return section_iterator(SectionRef(Sec, this));
2209}
2210
Peter Collingbourne435890a2016-11-22 03:38:40 +00002211basic_symbol_iterator MachOObjectFile::symbol_begin() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00002212 DataRefImpl DRI;
2213 MachO::symtab_command Symtab = getSymtabLoadCommand();
2214 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2215 return basic_symbol_iterator(SymbolRef(DRI, this));
2216
Lang Hames36072da2014-05-12 21:39:59 +00002217 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002218}
2219
Peter Collingbourne435890a2016-11-22 03:38:40 +00002220basic_symbol_iterator MachOObjectFile::symbol_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002221 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00002222 MachO::symtab_command Symtab = getSymtabLoadCommand();
2223 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002224 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00002225
Rafael Espindola75c30362013-04-24 19:47:55 +00002226 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00002227 sizeof(MachO::nlist_64) :
2228 sizeof(MachO::nlist);
2229 unsigned Offset = Symtab.symoff +
2230 Symtab.nsyms * SymbolTableEntrySize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002231 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00002232 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002233}
2234
Lang Hames36072da2014-05-12 21:39:59 +00002235basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00002236 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00002237 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00002238 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00002239 unsigned SymbolTableEntrySize =
2240 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00002241 DataRefImpl DRI;
Lang Hames697e7cd2016-12-04 01:56:10 +00002242 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Lang Hames36072da2014-05-12 21:39:59 +00002243 DRI.p += Index * SymbolTableEntrySize;
2244 return basic_symbol_iterator(SymbolRef(DRI, this));
2245}
2246
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002247uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2248 MachO::symtab_command Symtab = getSymtabLoadCommand();
2249 if (!SymtabLoadCmd)
2250 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2251 unsigned SymbolTableEntrySize =
2252 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2253 DataRefImpl DRIstart;
Lang Hames697e7cd2016-12-04 01:56:10 +00002254 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00002255 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2256 return Index;
2257}
2258
Rafael Espindolab5155a52014-02-10 20:24:04 +00002259section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002260 DataRefImpl DRI;
2261 return section_iterator(SectionRef(DRI, this));
2262}
2263
Rafael Espindolab5155a52014-02-10 20:24:04 +00002264section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002265 DataRefImpl DRI;
2266 DRI.d.a = Sections.size();
2267 return section_iterator(SectionRef(DRI, this));
2268}
2269
Rafael Espindola56f976f2013-04-18 18:08:55 +00002270uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00002271 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00002272}
2273
Rafael Espindola56f976f2013-04-18 18:08:55 +00002274StringRef MachOObjectFile::getFileFormatName() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002275 unsigned CPUType = getCPUType(*this);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002276 if (!is64Bit()) {
2277 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002278 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002279 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00002280 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002281 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00002282 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002283 return "Mach-O 32-bit ppc";
2284 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002285 return "Mach-O 32-bit unknown";
2286 }
2287 }
2288
Rafael Espindola56f976f2013-04-18 18:08:55 +00002289 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002290 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002291 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00002292 case llvm::MachO::CPU_TYPE_ARM64:
2293 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00002294 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002295 return "Mach-O 64-bit ppc64";
2296 default:
2297 return "Mach-O 64-bit unknown";
2298 }
2299}
2300
Alexey Samsonove6388e62013-06-18 15:03:28 +00002301Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2302 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00002303 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002304 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00002305 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002306 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00002307 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002308 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00002309 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00002310 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00002311 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002312 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00002313 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00002314 return Triple::ppc64;
2315 default:
2316 return Triple::UnknownArch;
2317 }
2318}
2319
Tim Northover9e8eb412016-04-22 23:21:13 +00002320Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
Kevin Enderby59343a92016-12-16 22:54:02 +00002321 const char **McpuDefault,
2322 const char **ArchFlag) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002323 if (McpuDefault)
2324 *McpuDefault = nullptr;
Kevin Enderby59343a92016-12-16 22:54:02 +00002325 if (ArchFlag)
2326 *ArchFlag = nullptr;
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002327
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002328 switch (CPUType) {
2329 case MachO::CPU_TYPE_I386:
2330 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2331 case MachO::CPU_SUBTYPE_I386_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002332 if (ArchFlag)
2333 *ArchFlag = "i386";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002334 return Triple("i386-apple-darwin");
2335 default:
2336 return Triple();
2337 }
2338 case MachO::CPU_TYPE_X86_64:
2339 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2340 case MachO::CPU_SUBTYPE_X86_64_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002341 if (ArchFlag)
2342 *ArchFlag = "x86_64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002343 return Triple("x86_64-apple-darwin");
2344 case MachO::CPU_SUBTYPE_X86_64_H:
Kevin Enderby59343a92016-12-16 22:54:02 +00002345 if (ArchFlag)
2346 *ArchFlag = "x86_64h";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002347 return Triple("x86_64h-apple-darwin");
2348 default:
2349 return Triple();
2350 }
2351 case MachO::CPU_TYPE_ARM:
2352 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2353 case MachO::CPU_SUBTYPE_ARM_V4T:
Kevin Enderby59343a92016-12-16 22:54:02 +00002354 if (ArchFlag)
2355 *ArchFlag = "armv4t";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002356 return Triple("armv4t-apple-darwin");
2357 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
Kevin Enderby59343a92016-12-16 22:54:02 +00002358 if (ArchFlag)
2359 *ArchFlag = "armv5e";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002360 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002361 case MachO::CPU_SUBTYPE_ARM_XSCALE:
Kevin Enderby59343a92016-12-16 22:54:02 +00002362 if (ArchFlag)
2363 *ArchFlag = "xscale";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002364 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002365 case MachO::CPU_SUBTYPE_ARM_V6:
Kevin Enderby59343a92016-12-16 22:54:02 +00002366 if (ArchFlag)
2367 *ArchFlag = "armv6";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002368 return Triple("armv6-apple-darwin");
2369 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002370 if (McpuDefault)
2371 *McpuDefault = "cortex-m0";
Kevin Enderby59343a92016-12-16 22:54:02 +00002372 if (ArchFlag)
2373 *ArchFlag = "armv6m";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002374 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002375 case MachO::CPU_SUBTYPE_ARM_V7:
Kevin Enderby59343a92016-12-16 22:54:02 +00002376 if (ArchFlag)
2377 *ArchFlag = "armv7";
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00002378 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002379 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002380 if (McpuDefault)
2381 *McpuDefault = "cortex-m4";
Kevin Enderby59343a92016-12-16 22:54:02 +00002382 if (ArchFlag)
2383 *ArchFlag = "armv7em";
Tim Northover9e8eb412016-04-22 23:21:13 +00002384 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002385 case MachO::CPU_SUBTYPE_ARM_V7K:
Kevin Enderby59343a92016-12-16 22:54:02 +00002386 if (ArchFlag)
2387 *ArchFlag = "armv7k";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002388 return Triple("armv7k-apple-darwin");
2389 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002390 if (McpuDefault)
2391 *McpuDefault = "cortex-m3";
Kevin Enderby59343a92016-12-16 22:54:02 +00002392 if (ArchFlag)
2393 *ArchFlag = "armv7m";
Tim Northover9e8eb412016-04-22 23:21:13 +00002394 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002395 case MachO::CPU_SUBTYPE_ARM_V7S:
Kevin Enderby59343a92016-12-16 22:54:02 +00002396 if (ArchFlag)
2397 *ArchFlag = "armv7s";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002398 return Triple("armv7s-apple-darwin");
2399 default:
2400 return Triple();
2401 }
2402 case MachO::CPU_TYPE_ARM64:
2403 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2404 case MachO::CPU_SUBTYPE_ARM64_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002405 if (ArchFlag)
2406 *ArchFlag = "arm64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002407 return Triple("arm64-apple-darwin");
2408 default:
2409 return Triple();
2410 }
2411 case MachO::CPU_TYPE_POWERPC:
2412 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2413 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002414 if (ArchFlag)
2415 *ArchFlag = "ppc";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002416 return Triple("ppc-apple-darwin");
2417 default:
2418 return Triple();
2419 }
2420 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00002421 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002422 case MachO::CPU_SUBTYPE_POWERPC_ALL:
Kevin Enderby59343a92016-12-16 22:54:02 +00002423 if (ArchFlag)
2424 *ArchFlag = "ppc64";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002425 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002426 default:
2427 return Triple();
2428 }
2429 default:
2430 return Triple();
2431 }
2432}
2433
2434Triple MachOObjectFile::getHostArch() {
2435 return Triple(sys::getDefaultTargetTriple());
2436}
2437
Rafael Espindola72318b42014-08-08 16:30:17 +00002438bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2439 return StringSwitch<bool>(ArchFlag)
2440 .Case("i386", true)
2441 .Case("x86_64", true)
2442 .Case("x86_64h", true)
2443 .Case("armv4t", true)
2444 .Case("arm", true)
2445 .Case("armv5e", true)
2446 .Case("armv6", true)
2447 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00002448 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00002449 .Case("armv7em", true)
2450 .Case("armv7k", true)
2451 .Case("armv7m", true)
2452 .Case("armv7s", true)
2453 .Case("arm64", true)
2454 .Case("ppc", true)
2455 .Case("ppc64", true)
2456 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00002457}
2458
Alexey Samsonove6388e62013-06-18 15:03:28 +00002459unsigned MachOObjectFile::getArch() const {
Lang Hames697e7cd2016-12-04 01:56:10 +00002460 return getArch(getCPUType(*this));
Alexey Samsonove6388e62013-06-18 15:03:28 +00002461}
2462
Tim Northover9e8eb412016-04-22 23:21:13 +00002463Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2464 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00002465}
2466
Rui Ueyamabc654b12013-09-27 21:47:05 +00002467relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002468 DataRefImpl DRI;
2469 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002470 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002471}
2472
Rui Ueyamabc654b12013-09-27 21:47:05 +00002473relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002474 DataRefImpl DRI;
2475 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00002476 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002477}
2478
Kevin Enderby273ae012013-06-06 17:20:50 +00002479dice_iterator MachOObjectFile::begin_dices() const {
2480 DataRefImpl DRI;
2481 if (!DataInCodeLoadCmd)
2482 return dice_iterator(DiceRef(DRI, this));
2483
Charles Davis8bdfafd2013-09-01 04:28:48 +00002484 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
Lang Hames697e7cd2016-12-04 01:56:10 +00002485 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00002486 return dice_iterator(DiceRef(DRI, this));
2487}
2488
2489dice_iterator MachOObjectFile::end_dices() const {
2490 DataRefImpl DRI;
2491 if (!DataInCodeLoadCmd)
2492 return dice_iterator(DiceRef(DRI, this));
2493
Charles Davis8bdfafd2013-09-01 04:28:48 +00002494 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2495 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Lang Hames697e7cd2016-12-04 01:56:10 +00002496 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
Kevin Enderby273ae012013-06-06 17:20:50 +00002497 return dice_iterator(DiceRef(DRI, this));
2498}
2499
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002500ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
2501 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002502
2503void ExportEntry::moveToFirst() {
2504 pushNode(0);
2505 pushDownUntilBottom();
2506}
2507
2508void ExportEntry::moveToEnd() {
2509 Stack.clear();
2510 Done = true;
2511}
2512
2513bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002514 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002515 if (Done || Other.Done)
2516 return (Done == Other.Done);
2517 // Not equal if different stack sizes.
2518 if (Stack.size() != Other.Stack.size())
2519 return false;
2520 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00002521 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00002522 return false;
2523 // Equal if all nodes in both stacks match.
2524 for (unsigned i=0; i < Stack.size(); ++i) {
2525 if (Stack[i].Start != Other.Stack[i].Start)
2526 return false;
2527 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002528 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002529}
2530
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002531uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
2532 unsigned Count;
2533 uint64_t Result = decodeULEB128(Ptr, &Count);
2534 Ptr += Count;
2535 if (Ptr > Trie.end()) {
2536 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002537 Malformed = true;
2538 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002539 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002540}
2541
2542StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00002543 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002544}
2545
2546uint64_t ExportEntry::flags() const {
2547 return Stack.back().Flags;
2548}
2549
2550uint64_t ExportEntry::address() const {
2551 return Stack.back().Address;
2552}
2553
2554uint64_t ExportEntry::other() const {
2555 return Stack.back().Other;
2556}
2557
2558StringRef ExportEntry::otherName() const {
2559 const char* ImportName = Stack.back().ImportName;
2560 if (ImportName)
2561 return StringRef(ImportName);
2562 return StringRef();
2563}
2564
2565uint32_t ExportEntry::nodeOffset() const {
2566 return Stack.back().Start - Trie.begin();
2567}
2568
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002569ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2570 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
2571 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
2572 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002573
2574void ExportEntry::pushNode(uint64_t offset) {
2575 const uint8_t *Ptr = Trie.begin() + offset;
2576 NodeState State(Ptr);
2577 uint64_t ExportInfoSize = readULEB128(State.Current);
2578 State.IsExportNode = (ExportInfoSize != 0);
2579 const uint8_t* Children = State.Current + ExportInfoSize;
2580 if (State.IsExportNode) {
2581 State.Flags = readULEB128(State.Current);
2582 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2583 State.Address = 0;
2584 State.Other = readULEB128(State.Current); // dylib ordinal
2585 State.ImportName = reinterpret_cast<const char*>(State.Current);
2586 } else {
2587 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00002588 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002589 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002590 }
2591 }
2592 State.ChildCount = *Children;
2593 State.Current = Children + 1;
2594 State.NextChildIndex = 0;
2595 State.ParentStringLength = CumulativeString.size();
2596 Stack.push_back(State);
2597}
2598
2599void ExportEntry::pushDownUntilBottom() {
2600 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2601 NodeState &Top = Stack.back();
2602 CumulativeString.resize(Top.ParentStringLength);
2603 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00002604 char C = *Top.Current;
2605 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002606 }
2607 Top.Current += 1;
2608 uint64_t childNodeIndex = readULEB128(Top.Current);
2609 Top.NextChildIndex += 1;
2610 pushNode(childNodeIndex);
2611 }
2612 if (!Stack.back().IsExportNode) {
2613 Malformed = true;
2614 moveToEnd();
2615 }
2616}
2617
2618// We have a trie data structure and need a way to walk it that is compatible
2619// with the C++ iterator model. The solution is a non-recursive depth first
2620// traversal where the iterator contains a stack of parent nodes along with a
2621// string that is the accumulation of all edge strings along the parent chain
2622// to this point.
2623//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00002624// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00002625// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00002626// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00002627//
2628// The algorithm for moveNext() is to keep moving down the leftmost unvisited
2629// child until hitting a node with no children (which is an export node or
2630// else the trie is malformed). On the way down, each node is pushed on the
2631// stack ivar. If there is no more ways down, it pops up one and tries to go
2632// down a sibling path until a childless node is reached.
2633void ExportEntry::moveNext() {
2634 if (Stack.empty() || !Stack.back().IsExportNode) {
2635 Malformed = true;
2636 moveToEnd();
2637 return;
2638 }
2639
2640 Stack.pop_back();
2641 while (!Stack.empty()) {
2642 NodeState &Top = Stack.back();
2643 if (Top.NextChildIndex < Top.ChildCount) {
2644 pushDownUntilBottom();
2645 // Now at the next export node.
2646 return;
2647 } else {
2648 if (Top.IsExportNode) {
2649 // This node has no children but is itself an export node.
2650 CumulativeString.resize(Top.ParentStringLength);
2651 return;
2652 }
2653 Stack.pop_back();
2654 }
2655 }
2656 Done = true;
2657}
2658
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002659iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00002660MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
2661 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00002662 if (Trie.size() == 0)
2663 Start.moveToEnd();
2664 else
2665 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00002666
2667 ExportEntry Finish(Trie);
2668 Finish.moveToEnd();
2669
Craig Topper15576e12015-12-06 05:08:07 +00002670 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00002671}
2672
2673iterator_range<export_iterator> MachOObjectFile::exports() const {
2674 return exports(getDyldInfoExportsTrie());
2675}
2676
Nick Kledzikac431442014-09-12 21:34:15 +00002677MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
2678 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2679 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
2680 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
2681
2682void MachORebaseEntry::moveToFirst() {
2683 Ptr = Opcodes.begin();
2684 moveNext();
2685}
2686
2687void MachORebaseEntry::moveToEnd() {
2688 Ptr = Opcodes.end();
2689 RemainingLoopCount = 0;
2690 Done = true;
2691}
2692
2693void MachORebaseEntry::moveNext() {
2694 // If in the middle of some loop, move to next rebasing in loop.
2695 SegmentOffset += AdvanceAmount;
2696 if (RemainingLoopCount) {
2697 --RemainingLoopCount;
2698 return;
2699 }
2700 if (Ptr == Opcodes.end()) {
2701 Done = true;
2702 return;
2703 }
2704 bool More = true;
2705 while (More && !Malformed) {
2706 // Parse next opcode and set up next loop.
2707 uint8_t Byte = *Ptr++;
2708 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
2709 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
2710 switch (Opcode) {
2711 case MachO::REBASE_OPCODE_DONE:
2712 More = false;
2713 Done = true;
2714 moveToEnd();
2715 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
2716 break;
2717 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
2718 RebaseType = ImmValue;
2719 DEBUG_WITH_TYPE(
2720 "mach-o-rebase",
2721 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
2722 << "RebaseType=" << (int) RebaseType << "\n");
2723 break;
2724 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2725 SegmentIndex = ImmValue;
2726 SegmentOffset = readULEB128();
2727 DEBUG_WITH_TYPE(
2728 "mach-o-rebase",
2729 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2730 << "SegmentIndex=" << SegmentIndex << ", "
2731 << format("SegmentOffset=0x%06X", SegmentOffset)
2732 << "\n");
2733 break;
2734 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
2735 SegmentOffset += readULEB128();
2736 DEBUG_WITH_TYPE("mach-o-rebase",
2737 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
2738 << format("SegmentOffset=0x%06X",
2739 SegmentOffset) << "\n");
2740 break;
2741 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
2742 SegmentOffset += ImmValue * PointerSize;
2743 DEBUG_WITH_TYPE("mach-o-rebase",
2744 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
2745 << format("SegmentOffset=0x%06X",
2746 SegmentOffset) << "\n");
2747 break;
2748 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
2749 AdvanceAmount = PointerSize;
2750 RemainingLoopCount = ImmValue - 1;
2751 DEBUG_WITH_TYPE(
2752 "mach-o-rebase",
2753 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
2754 << format("SegmentOffset=0x%06X", SegmentOffset)
2755 << ", AdvanceAmount=" << AdvanceAmount
2756 << ", RemainingLoopCount=" << RemainingLoopCount
2757 << "\n");
2758 return;
2759 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
2760 AdvanceAmount = PointerSize;
2761 RemainingLoopCount = readULEB128() - 1;
2762 DEBUG_WITH_TYPE(
2763 "mach-o-rebase",
2764 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
2765 << format("SegmentOffset=0x%06X", SegmentOffset)
2766 << ", AdvanceAmount=" << AdvanceAmount
2767 << ", RemainingLoopCount=" << RemainingLoopCount
2768 << "\n");
2769 return;
2770 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
2771 AdvanceAmount = readULEB128() + PointerSize;
2772 RemainingLoopCount = 0;
2773 DEBUG_WITH_TYPE(
2774 "mach-o-rebase",
2775 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
2776 << format("SegmentOffset=0x%06X", SegmentOffset)
2777 << ", AdvanceAmount=" << AdvanceAmount
2778 << ", RemainingLoopCount=" << RemainingLoopCount
2779 << "\n");
2780 return;
2781 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
2782 RemainingLoopCount = readULEB128() - 1;
2783 AdvanceAmount = readULEB128() + PointerSize;
2784 DEBUG_WITH_TYPE(
2785 "mach-o-rebase",
2786 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
2787 << format("SegmentOffset=0x%06X", SegmentOffset)
2788 << ", AdvanceAmount=" << AdvanceAmount
2789 << ", RemainingLoopCount=" << RemainingLoopCount
2790 << "\n");
2791 return;
2792 default:
2793 Malformed = true;
2794 }
2795 }
2796}
2797
2798uint64_t MachORebaseEntry::readULEB128() {
2799 unsigned Count;
2800 uint64_t Result = decodeULEB128(Ptr, &Count);
2801 Ptr += Count;
2802 if (Ptr > Opcodes.end()) {
2803 Ptr = Opcodes.end();
2804 Malformed = true;
2805 }
2806 return Result;
2807}
2808
2809uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
2810
2811uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
2812
2813StringRef MachORebaseEntry::typeName() const {
2814 switch (RebaseType) {
2815 case MachO::REBASE_TYPE_POINTER:
2816 return "pointer";
2817 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
2818 return "text abs32";
2819 case MachO::REBASE_TYPE_TEXT_PCREL32:
2820 return "text rel32";
2821 }
2822 return "unknown";
2823}
2824
2825bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
2826 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2827 return (Ptr == Other.Ptr) &&
2828 (RemainingLoopCount == Other.RemainingLoopCount) &&
2829 (Done == Other.Done);
2830}
2831
2832iterator_range<rebase_iterator>
2833MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
2834 MachORebaseEntry Start(Opcodes, is64);
2835 Start.moveToFirst();
2836
2837 MachORebaseEntry Finish(Opcodes, is64);
2838 Finish.moveToEnd();
2839
Craig Topper15576e12015-12-06 05:08:07 +00002840 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00002841}
2842
2843iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
2844 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
2845}
2846
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002847MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00002848 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2849 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
2850 BindType(0), PointerSize(is64Bit ? 8 : 4),
2851 TableKind(BK), Malformed(false), Done(false) {}
2852
2853void MachOBindEntry::moveToFirst() {
2854 Ptr = Opcodes.begin();
2855 moveNext();
2856}
2857
2858void MachOBindEntry::moveToEnd() {
2859 Ptr = Opcodes.end();
2860 RemainingLoopCount = 0;
2861 Done = true;
2862}
2863
2864void MachOBindEntry::moveNext() {
2865 // If in the middle of some loop, move to next binding in loop.
2866 SegmentOffset += AdvanceAmount;
2867 if (RemainingLoopCount) {
2868 --RemainingLoopCount;
2869 return;
2870 }
2871 if (Ptr == Opcodes.end()) {
2872 Done = true;
2873 return;
2874 }
2875 bool More = true;
2876 while (More && !Malformed) {
2877 // Parse next opcode and set up next loop.
2878 uint8_t Byte = *Ptr++;
2879 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
2880 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
2881 int8_t SignExtended;
2882 const uint8_t *SymStart;
2883 switch (Opcode) {
2884 case MachO::BIND_OPCODE_DONE:
2885 if (TableKind == Kind::Lazy) {
2886 // Lazying bindings have a DONE opcode between entries. Need to ignore
2887 // it to advance to next entry. But need not if this is last entry.
2888 bool NotLastEntry = false;
2889 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
2890 if (*P) {
2891 NotLastEntry = true;
2892 }
2893 }
2894 if (NotLastEntry)
2895 break;
2896 }
2897 More = false;
2898 Done = true;
2899 moveToEnd();
2900 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
2901 break;
2902 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
2903 Ordinal = ImmValue;
2904 DEBUG_WITH_TYPE(
2905 "mach-o-bind",
2906 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
2907 << "Ordinal=" << Ordinal << "\n");
2908 break;
2909 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
2910 Ordinal = readULEB128();
2911 DEBUG_WITH_TYPE(
2912 "mach-o-bind",
2913 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
2914 << "Ordinal=" << Ordinal << "\n");
2915 break;
2916 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
2917 if (ImmValue) {
2918 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
2919 Ordinal = SignExtended;
2920 } else
2921 Ordinal = 0;
2922 DEBUG_WITH_TYPE(
2923 "mach-o-bind",
2924 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
2925 << "Ordinal=" << Ordinal << "\n");
2926 break;
2927 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
2928 Flags = ImmValue;
2929 SymStart = Ptr;
2930 while (*Ptr) {
2931 ++Ptr;
2932 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00002933 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
2934 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00002935 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002936 DEBUG_WITH_TYPE(
2937 "mach-o-bind",
2938 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
2939 << "SymbolName=" << SymbolName << "\n");
2940 if (TableKind == Kind::Weak) {
2941 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
2942 return;
2943 }
2944 break;
2945 case MachO::BIND_OPCODE_SET_TYPE_IMM:
2946 BindType = ImmValue;
2947 DEBUG_WITH_TYPE(
2948 "mach-o-bind",
2949 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
2950 << "BindType=" << (int)BindType << "\n");
2951 break;
2952 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
2953 Addend = readSLEB128();
2954 if (TableKind == Kind::Lazy)
2955 Malformed = true;
2956 DEBUG_WITH_TYPE(
2957 "mach-o-bind",
2958 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
2959 << "Addend=" << Addend << "\n");
2960 break;
2961 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2962 SegmentIndex = ImmValue;
2963 SegmentOffset = readULEB128();
2964 DEBUG_WITH_TYPE(
2965 "mach-o-bind",
2966 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2967 << "SegmentIndex=" << SegmentIndex << ", "
2968 << format("SegmentOffset=0x%06X", SegmentOffset)
2969 << "\n");
2970 break;
2971 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
2972 SegmentOffset += readULEB128();
2973 DEBUG_WITH_TYPE("mach-o-bind",
2974 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2975 << format("SegmentOffset=0x%06X",
2976 SegmentOffset) << "\n");
2977 break;
2978 case MachO::BIND_OPCODE_DO_BIND:
2979 AdvanceAmount = PointerSize;
2980 RemainingLoopCount = 0;
2981 DEBUG_WITH_TYPE("mach-o-bind",
2982 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2983 << format("SegmentOffset=0x%06X",
2984 SegmentOffset) << "\n");
2985 return;
2986 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002987 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00002988 RemainingLoopCount = 0;
2989 if (TableKind == Kind::Lazy)
2990 Malformed = true;
2991 DEBUG_WITH_TYPE(
2992 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00002993 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00002994 << format("SegmentOffset=0x%06X", SegmentOffset)
2995 << ", AdvanceAmount=" << AdvanceAmount
2996 << ", RemainingLoopCount=" << RemainingLoopCount
2997 << "\n");
2998 return;
2999 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00003000 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00003001 RemainingLoopCount = 0;
3002 if (TableKind == Kind::Lazy)
3003 Malformed = true;
3004 DEBUG_WITH_TYPE("mach-o-bind",
3005 llvm::dbgs()
3006 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3007 << format("SegmentOffset=0x%06X",
3008 SegmentOffset) << "\n");
3009 return;
3010 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
3011 RemainingLoopCount = readULEB128() - 1;
3012 AdvanceAmount = readULEB128() + PointerSize;
3013 if (TableKind == Kind::Lazy)
3014 Malformed = true;
3015 DEBUG_WITH_TYPE(
3016 "mach-o-bind",
3017 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3018 << format("SegmentOffset=0x%06X", SegmentOffset)
3019 << ", AdvanceAmount=" << AdvanceAmount
3020 << ", RemainingLoopCount=" << RemainingLoopCount
3021 << "\n");
3022 return;
3023 default:
3024 Malformed = true;
3025 }
3026 }
3027}
3028
3029uint64_t MachOBindEntry::readULEB128() {
3030 unsigned Count;
3031 uint64_t Result = decodeULEB128(Ptr, &Count);
3032 Ptr += Count;
3033 if (Ptr > Opcodes.end()) {
3034 Ptr = Opcodes.end();
3035 Malformed = true;
3036 }
3037 return Result;
3038}
3039
3040int64_t MachOBindEntry::readSLEB128() {
3041 unsigned Count;
3042 int64_t Result = decodeSLEB128(Ptr, &Count);
3043 Ptr += Count;
3044 if (Ptr > Opcodes.end()) {
3045 Ptr = Opcodes.end();
3046 Malformed = true;
3047 }
3048 return Result;
3049}
3050
Nick Kledzik56ebef42014-09-16 01:41:51 +00003051uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
3052
3053uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3054
3055StringRef MachOBindEntry::typeName() const {
3056 switch (BindType) {
3057 case MachO::BIND_TYPE_POINTER:
3058 return "pointer";
3059 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3060 return "text abs32";
3061 case MachO::BIND_TYPE_TEXT_PCREL32:
3062 return "text rel32";
3063 }
3064 return "unknown";
3065}
3066
3067StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3068
3069int64_t MachOBindEntry::addend() const { return Addend; }
3070
3071uint32_t MachOBindEntry::flags() const { return Flags; }
3072
3073int MachOBindEntry::ordinal() const { return Ordinal; }
3074
3075bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
3076 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3077 return (Ptr == Other.Ptr) &&
3078 (RemainingLoopCount == Other.RemainingLoopCount) &&
3079 (Done == Other.Done);
3080}
3081
3082iterator_range<bind_iterator>
3083MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
3084 MachOBindEntry::Kind BKind) {
3085 MachOBindEntry Start(Opcodes, is64, BKind);
3086 Start.moveToFirst();
3087
3088 MachOBindEntry Finish(Opcodes, is64, BKind);
3089 Finish.moveToEnd();
3090
Craig Topper15576e12015-12-06 05:08:07 +00003091 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00003092}
3093
3094iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
3095 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
3096 MachOBindEntry::Kind::Regular);
3097}
3098
3099iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
3100 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
3101 MachOBindEntry::Kind::Lazy);
3102}
3103
3104iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
3105 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
3106 MachOBindEntry::Kind::Weak);
3107}
3108
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00003109MachOObjectFile::load_command_iterator
3110MachOObjectFile::begin_load_commands() const {
3111 return LoadCommands.begin();
3112}
3113
3114MachOObjectFile::load_command_iterator
3115MachOObjectFile::end_load_commands() const {
3116 return LoadCommands.end();
3117}
3118
3119iterator_range<MachOObjectFile::load_command_iterator>
3120MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00003121 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00003122}
3123
Rafael Espindola56f976f2013-04-18 18:08:55 +00003124StringRef
3125MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
3126 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
3127 return parseSegmentOrSectionName(Raw.data());
3128}
3129
3130ArrayRef<char>
3131MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00003132 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003133 const section_base *Base =
3134 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00003135 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003136}
3137
3138ArrayRef<char>
3139MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00003140 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00003141 const section_base *Base =
3142 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00003143 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003144}
3145
3146bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00003147MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00003148 const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003149 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00003150 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00003151 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003152}
3153
Eric Christopher1d62c252013-07-22 22:25:07 +00003154unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003155 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003156 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00003157 return RE.r_word1 & 0xffffff;
3158 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003159}
3160
Eric Christopher1d62c252013-07-22 22:25:07 +00003161bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003162 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003163 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00003164 return (RE.r_word1 >> 27) & 1;
3165 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003166}
3167
Eric Christopher1d62c252013-07-22 22:25:07 +00003168bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003169 const MachO::any_relocation_info &RE) const {
3170 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003171}
3172
Eric Christopher1d62c252013-07-22 22:25:07 +00003173uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003174 const MachO::any_relocation_info &RE) const {
3175 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003176}
3177
Kevin Enderby9907d0a2014-11-04 00:43:16 +00003178uint32_t MachOObjectFile::getScatteredRelocationType(
3179 const MachO::any_relocation_info &RE) const {
3180 return (RE.r_word0 >> 24) & 0xf;
3181}
3182
Eric Christopher1d62c252013-07-22 22:25:07 +00003183unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003184 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003185 if (isRelocationScattered(RE))
3186 return getScatteredRelocationAddress(RE);
3187 return getPlainRelocationAddress(RE);
3188}
3189
Charles Davis8bdfafd2013-09-01 04:28:48 +00003190unsigned MachOObjectFile::getAnyRelocationPCRel(
3191 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003192 if (isRelocationScattered(RE))
Lang Hames697e7cd2016-12-04 01:56:10 +00003193 return getScatteredRelocationPCRel(RE);
3194 return getPlainRelocationPCRel(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003195}
3196
Eric Christopher1d62c252013-07-22 22:25:07 +00003197unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003198 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003199 if (isRelocationScattered(RE))
3200 return getScatteredRelocationLength(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00003201 return getPlainRelocationLength(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003202}
3203
3204unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00003205MachOObjectFile::getAnyRelocationType(
3206 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00003207 if (isRelocationScattered(RE))
3208 return getScatteredRelocationType(RE);
Lang Hames697e7cd2016-12-04 01:56:10 +00003209 return getPlainRelocationType(*this, RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003210}
3211
Rafael Espindola52501032013-04-30 15:40:54 +00003212SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00003213MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00003214 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00003215 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00003216 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00003217 unsigned SecNum = getPlainRelocationSymbolNum(RE);
3218 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
3219 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00003220 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00003221 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00003222 return SectionRef(DRI, this);
3223}
3224
Charles Davis8bdfafd2013-09-01 04:28:48 +00003225MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00003226 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00003227 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003228}
3229
Charles Davis8bdfafd2013-09-01 04:28:48 +00003230MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00003231 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Lang Hames697e7cd2016-12-04 01:56:10 +00003232 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003233}
3234
Charles Davis8bdfafd2013-09-01 04:28:48 +00003235MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00003236 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003237 const char *Sec = getSectionPtr(*this, L, Index);
3238 return getStruct<MachO::section>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003239}
3240
Charles Davis8bdfafd2013-09-01 04:28:48 +00003241MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
3242 unsigned Index) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003243 const char *Sec = getSectionPtr(*this, L, Index);
3244 return getStruct<MachO::section_64>(*this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003245}
3246
Charles Davis8bdfafd2013-09-01 04:28:48 +00003247MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00003248MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00003249 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00003250 return getStruct<MachO::nlist>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003251}
3252
Charles Davis8bdfafd2013-09-01 04:28:48 +00003253MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00003254MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00003255 const char *P = reinterpret_cast<const char *>(DRI.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00003256 return getStruct<MachO::nlist_64>(*this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003257}
3258
Charles Davis8bdfafd2013-09-01 04:28:48 +00003259MachO::linkedit_data_command
3260MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003261 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003262}
3263
Charles Davis8bdfafd2013-09-01 04:28:48 +00003264MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00003265MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003266 return getStruct<MachO::segment_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003267}
3268
Charles Davis8bdfafd2013-09-01 04:28:48 +00003269MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00003270MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003271 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003272}
3273
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00003274MachO::linker_option_command
3275MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003276 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003277}
3278
Jim Grosbach448334a2014-03-18 22:09:05 +00003279MachO::version_min_command
3280MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003281 return getStruct<MachO::version_min_command>(*this, L.Ptr);
Jim Grosbach448334a2014-03-18 22:09:05 +00003282}
3283
Tim Northover8f9590b2014-06-30 14:40:57 +00003284MachO::dylib_command
3285MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003286 return getStruct<MachO::dylib_command>(*this, L.Ptr);
Tim Northover8f9590b2014-06-30 14:40:57 +00003287}
3288
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003289MachO::dyld_info_command
3290MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003291 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003292}
3293
3294MachO::dylinker_command
3295MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003296 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003297}
3298
3299MachO::uuid_command
3300MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003301 return getStruct<MachO::uuid_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003302}
3303
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00003304MachO::rpath_command
3305MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003306 return getStruct<MachO::rpath_command>(*this, L.Ptr);
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00003307}
3308
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003309MachO::source_version_command
3310MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003311 return getStruct<MachO::source_version_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003312}
3313
3314MachO::entry_point_command
3315MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003316 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
Kevin Enderby8ae63c12014-09-04 16:54:47 +00003317}
3318
Kevin Enderby0804f4672014-12-16 23:25:52 +00003319MachO::encryption_info_command
3320MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003321 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
Kevin Enderby0804f4672014-12-16 23:25:52 +00003322}
3323
Kevin Enderby57538292014-12-17 01:01:30 +00003324MachO::encryption_info_command_64
3325MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003326 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
Kevin Enderby57538292014-12-17 01:01:30 +00003327}
3328
Kevin Enderbyb4b79312014-12-18 19:24:35 +00003329MachO::sub_framework_command
3330MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003331 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
Kevin Enderbyb4b79312014-12-18 19:24:35 +00003332}
Tim Northover8f9590b2014-06-30 14:40:57 +00003333
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00003334MachO::sub_umbrella_command
3335MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003336 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00003337}
3338
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00003339MachO::sub_library_command
3340MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003341 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00003342}
3343
Kevin Enderby186eac32014-12-19 21:06:24 +00003344MachO::sub_client_command
3345MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003346 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
Kevin Enderby186eac32014-12-19 21:06:24 +00003347}
3348
Kevin Enderby52e4ce42014-12-19 22:25:22 +00003349MachO::routines_command
3350MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003351 return getStruct<MachO::routines_command>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00003352}
3353
3354MachO::routines_command_64
3355MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003356 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
Kevin Enderby52e4ce42014-12-19 22:25:22 +00003357}
3358
Kevin Enderby48ef5342014-12-23 22:56:39 +00003359MachO::thread_command
3360MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
Lang Hames697e7cd2016-12-04 01:56:10 +00003361 return getStruct<MachO::thread_command>(*this, L.Ptr);
Kevin Enderby48ef5342014-12-23 22:56:39 +00003362}
3363
Charles Davis8bdfafd2013-09-01 04:28:48 +00003364MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00003365MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00003366 DataRefImpl Sec;
3367 Sec.d.a = Rel.d.a;
3368 uint32_t Offset;
3369 if (is64Bit()) {
3370 MachO::section_64 Sect = getSection64(Sec);
3371 Offset = Sect.reloff;
3372 } else {
3373 MachO::section Sect = getSection(Sec);
3374 Offset = Sect.reloff;
3375 }
3376
3377 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
Lang Hames697e7cd2016-12-04 01:56:10 +00003378 getPtr(*this, Offset)) + Rel.d.b;
Rafael Espindola128b8112014-04-03 23:51:28 +00003379 return getStruct<MachO::any_relocation_info>(
Lang Hames697e7cd2016-12-04 01:56:10 +00003380 *this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00003381}
3382
Charles Davis8bdfafd2013-09-01 04:28:48 +00003383MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00003384MachOObjectFile::getDice(DataRefImpl Rel) const {
3385 const char *P = reinterpret_cast<const char *>(Rel.p);
Lang Hames697e7cd2016-12-04 01:56:10 +00003386 return getStruct<MachO::data_in_code_entry>(*this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00003387}
3388
Alexey Samsonov13415ed2015-06-04 19:22:03 +00003389const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00003390 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003391}
3392
Alexey Samsonov13415ed2015-06-04 19:22:03 +00003393const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
3394 assert(is64Bit());
3395 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00003396}
3397
Charles Davis8bdfafd2013-09-01 04:28:48 +00003398uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
3399 const MachO::dysymtab_command &DLC,
3400 unsigned Index) const {
3401 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
Lang Hames697e7cd2016-12-04 01:56:10 +00003402 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00003403}
3404
Charles Davis8bdfafd2013-09-01 04:28:48 +00003405MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00003406MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
3407 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003408 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
Lang Hames697e7cd2016-12-04 01:56:10 +00003409 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00003410}
3411
Charles Davis8bdfafd2013-09-01 04:28:48 +00003412MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00003413 if (SymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00003414 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00003415
3416 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
3417 MachO::symtab_command Cmd;
3418 Cmd.cmd = MachO::LC_SYMTAB;
3419 Cmd.cmdsize = sizeof(MachO::symtab_command);
3420 Cmd.symoff = 0;
3421 Cmd.nsyms = 0;
3422 Cmd.stroff = 0;
3423 Cmd.strsize = 0;
3424 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00003425}
3426
Charles Davis8bdfafd2013-09-01 04:28:48 +00003427MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00003428 if (DysymtabLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00003429 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
Kevin Enderby6f326ce2014-10-23 19:37:31 +00003430
3431 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
3432 MachO::dysymtab_command Cmd;
3433 Cmd.cmd = MachO::LC_DYSYMTAB;
3434 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
3435 Cmd.ilocalsym = 0;
3436 Cmd.nlocalsym = 0;
3437 Cmd.iextdefsym = 0;
3438 Cmd.nextdefsym = 0;
3439 Cmd.iundefsym = 0;
3440 Cmd.nundefsym = 0;
3441 Cmd.tocoff = 0;
3442 Cmd.ntoc = 0;
3443 Cmd.modtaboff = 0;
3444 Cmd.nmodtab = 0;
3445 Cmd.extrefsymoff = 0;
3446 Cmd.nextrefsyms = 0;
3447 Cmd.indirectsymoff = 0;
3448 Cmd.nindirectsyms = 0;
3449 Cmd.extreloff = 0;
3450 Cmd.nextrel = 0;
3451 Cmd.locreloff = 0;
3452 Cmd.nlocrel = 0;
3453 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00003454}
3455
Charles Davis8bdfafd2013-09-01 04:28:48 +00003456MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00003457MachOObjectFile::getDataInCodeLoadCommand() const {
3458 if (DataInCodeLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00003459 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00003460
3461 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00003462 MachO::linkedit_data_command Cmd;
3463 Cmd.cmd = MachO::LC_DATA_IN_CODE;
3464 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3465 Cmd.dataoff = 0;
3466 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00003467 return Cmd;
3468}
3469
Kevin Enderby9a509442015-01-27 21:28:24 +00003470MachO::linkedit_data_command
3471MachOObjectFile::getLinkOptHintsLoadCommand() const {
3472 if (LinkOptHintsLoadCmd)
Lang Hames697e7cd2016-12-04 01:56:10 +00003473 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
Kevin Enderby9a509442015-01-27 21:28:24 +00003474
3475 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
3476 // fields.
3477 MachO::linkedit_data_command Cmd;
3478 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
3479 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3480 Cmd.dataoff = 0;
3481 Cmd.datasize = 0;
3482 return Cmd;
3483}
3484
Nick Kledzikd04bc352014-08-30 00:20:14 +00003485ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003486 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003487 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003488
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003489 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00003490 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003491 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00003492 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00003493 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003494}
3495
3496ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003497 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003498 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003499
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003500 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00003501 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003502 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00003503 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003504 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003505}
3506
3507ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003508 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003509 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003510
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003511 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00003512 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003513 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00003514 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003515 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003516}
3517
3518ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003519 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003520 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003521
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003522 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00003523 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003524 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00003525 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00003526 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003527}
3528
3529ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00003530 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003531 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00003532
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003533 MachO::dyld_info_command DyldInfo =
Lang Hames697e7cd2016-12-04 01:56:10 +00003534 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00003535 const uint8_t *Ptr =
Lang Hames697e7cd2016-12-04 01:56:10 +00003536 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00003537 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00003538}
3539
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00003540ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
3541 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00003542 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00003543 // Returning a pointer is fine as uuid doesn't need endian swapping.
3544 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00003545 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00003546}
Nick Kledzikd04bc352014-08-30 00:20:14 +00003547
Rafael Espindola6e040c02013-04-26 20:07:33 +00003548StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00003549 MachO::symtab_command S = getSymtabLoadCommand();
3550 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00003551}
3552
Rafael Espindola56f976f2013-04-18 18:08:55 +00003553bool MachOObjectFile::is64Bit() const {
3554 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00003555 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003556}
3557
3558void MachOObjectFile::ReadULEB128s(uint64_t Index,
3559 SmallVectorImpl<uint64_t> &Out) const {
3560 DataExtractor extractor(ObjectFile::getData(), true, 0);
3561
3562 uint32_t offset = Index;
3563 uint64_t data = 0;
3564 while (uint64_t delta = extractor.getULEB128(&offset)) {
3565 data += delta;
3566 Out.push_back(data);
3567 }
3568}
3569
Rafael Espindolac66d7612014-08-17 19:09:37 +00003570bool MachOObjectFile::isRelocatableObject() const {
3571 return getHeader().filetype == MachO::MH_OBJECT;
3572}
3573
Lang Hamesff044b12016-03-25 23:11:52 +00003574Expected<std::unique_ptr<MachOObjectFile>>
Kevin Enderby79d6c632016-10-24 21:15:11 +00003575ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
3576 uint32_t UniversalCputype,
3577 uint32_t UniversalIndex) {
Rafael Espindola48af1c22014-08-19 18:44:46 +00003578 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00003579 if (Magic == "\xFE\xED\xFA\xCE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003580 return MachOObjectFile::create(Buffer, false, false,
3581 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003582 if (Magic == "\xCE\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003583 return MachOObjectFile::create(Buffer, true, false,
3584 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003585 if (Magic == "\xFE\xED\xFA\xCF")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003586 return MachOObjectFile::create(Buffer, false, true,
3587 UniversalCputype, UniversalIndex);
David Blaikieb805f732016-03-28 17:45:48 +00003588 if (Magic == "\xCF\xFA\xED\xFE")
Kevin Enderby79d6c632016-10-24 21:15:11 +00003589 return MachOObjectFile::create(Buffer, true, true,
3590 UniversalCputype, UniversalIndex);
Kevin Enderbyd4e075b2016-05-06 20:16:28 +00003591 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
Justin Bogner2a42da92016-05-05 23:59:57 +00003592 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00003593}