blob: 516607dea234c85b6ddaa29f96c78c6459e384d7 [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>
30
31using namespace llvm;
32using namespace object;
33
Artyom Skrobov7d602f72014-07-20 12:08:28 +000034namespace {
35 struct section_base {
36 char sectname[16];
37 char segname[16];
38 };
39}
Rafael Espindola56f976f2013-04-18 18:08:55 +000040
Lang Hames9e964f32016-03-25 17:25:34 +000041// FIXME: Remove ECOverride once Error has been plumbed down to obj tool code.
42static Error
43malformedError(std::string FileName, std::string Msg,
44 object_error ECOverride = object_error::parse_failed) {
45 return make_error<GenericBinaryError>(std::move(FileName), std::move(Msg),
46 ECOverride);
47}
48
Lang Hames9e964f32016-03-25 17:25:34 +000049// FIXME: Remove ECOverride once Error has been plumbed down to obj tool code.
50static Error
Kevin Enderby81e8b7d2016-04-20 21:24:34 +000051malformedError(const MachOObjectFile &Obj, Twine Msg,
Lang Hames9e964f32016-03-25 17:25:34 +000052 object_error ECOverride = object_error::parse_failed) {
Evgeniy Stepanov23834652016-04-20 22:44:40 +000053 return malformedError(Obj.getFileName(), Msg.str(), ECOverride);
Lang Hames9e964f32016-03-25 17:25:34 +000054}
55
Alexey Samsonov9f336632015-06-04 19:45:22 +000056// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000057template <typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000058static T getStruct(const MachOObjectFile *O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000059 // Don't read before the beginning or past the end of the file
60 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
61 report_fatal_error("Malformed MachO file.");
62
Rafael Espindola3cdeb172013-04-19 13:45:05 +000063 T Cmd;
64 memcpy(&Cmd, P, sizeof(T));
65 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000066 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000067 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000068}
69
Alexey Samsonov9f336632015-06-04 19:45:22 +000070template <typename T>
Lang Hames9e964f32016-03-25 17:25:34 +000071static Expected<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000072 // Don't read before the beginning or past the end of the file
73 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
Lang Hames9e964f32016-03-25 17:25:34 +000074 return malformedError(*O, "Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000075
76 T Cmd;
77 memcpy(&Cmd, P, sizeof(T));
78 if (O->isLittleEndian() != sys::IsLittleEndianHost)
79 MachO::swapStruct(Cmd);
80 return Cmd;
81}
82
Rafael Espindola6e040c02013-04-26 20:07:33 +000083static const char *
84getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
85 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000086 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
87
88 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000089 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
90 sizeof(MachO::segment_command);
91 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
92 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000093
94 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000095 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000096}
97
Rafael Espindola56f976f2013-04-18 18:08:55 +000098static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
99 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +0000100}
101
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000102static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +0000103getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +0000104 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000105 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +0000106}
107
Rafael Espindola56f976f2013-04-18 18:08:55 +0000108static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000109 if (P[15] == 0)
110 // Null terminated.
111 return P;
112 // Not null terminated, so this is a 16 char string.
113 return StringRef(P, 16);
114}
115
Rafael Espindola56f976f2013-04-18 18:08:55 +0000116// Helper to advance a section or symbol iterator multiple increments at a time.
117template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000118static void advance(T &it, size_t Val) {
119 while (Val--)
120 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000121}
122
123static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000124 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000125}
126
Charles Davis8bdfafd2013-09-01 04:28:48 +0000127static uint32_t
128getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
129 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000130}
131
132static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000133getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
134 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000135}
136
137static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000138 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000139 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000140 return (RE.r_word1 >> 24) & 1;
141 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000142}
143
144static bool
145getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000146 const MachO::any_relocation_info &RE) {
147 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000148}
149
150static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000151 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000153 return (RE.r_word1 >> 25) & 3;
154 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000155}
156
157static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000158getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
159 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000160}
161
162static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000163 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000164 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000165 return RE.r_word1 >> 28;
166 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000167}
168
Rafael Espindola56f976f2013-04-18 18:08:55 +0000169static uint32_t getSectionFlags(const MachOObjectFile *O,
170 DataRefImpl Sec) {
171 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000172 MachO::section_64 Sect = O->getSection64(Sec);
173 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000174 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000175 MachO::section Sect = O->getSection(Sec);
176 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000177}
178
Lang Hames9e964f32016-03-25 17:25:34 +0000179static Expected<MachOObjectFile::LoadCommandInfo>
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000180getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr,
181 uint32_t LoadCommandIndex) {
Lang Hames9e964f32016-03-25 17:25:34 +0000182 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
183 if (CmdOrErr->cmdsize < 8)
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000184 return malformedError(*Obj, Twine("truncated or malformed object (load "
185 "command ") + Twine(LoadCommandIndex) +
186 Twine(" with size less than 8 bytes)"));
Lang Hames9e964f32016-03-25 17:25:34 +0000187 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
188 } else
189 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000190}
191
Lang Hames9e964f32016-03-25 17:25:34 +0000192static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000193getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
194 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
195 : sizeof(MachO::mach_header);
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000196 if (sizeof(MachOObjectFile::LoadCommandInfo) > Obj->getHeader().sizeofcmds)
197 return malformedError(*Obj, "truncated or malformed object (load command "
198 "0 extends past the end all load commands in the "
199 "file)");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000200 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000201}
202
Lang Hames9e964f32016-03-25 17:25:34 +0000203static Expected<MachOObjectFile::LoadCommandInfo>
Kevin Enderby368e7142016-05-03 17:16:08 +0000204getNextLoadCommandInfo(const MachOObjectFile *Obj, uint32_t LoadCommandIndex,
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000205 const MachOObjectFile::LoadCommandInfo &L) {
Kevin Enderby368e7142016-05-03 17:16:08 +0000206 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
207 : sizeof(MachO::mach_header);
208 if (L.Ptr + L.C.cmdsize + sizeof(MachOObjectFile::LoadCommandInfo) >
209 Obj->getData().data() + HeaderSize + Obj->getHeader().sizeofcmds)
210 return malformedError(*Obj, Twine("truncated or malformed object "
211 "(load command ") + Twine(LoadCommandIndex + 1) +
212 Twine(" extends past the end all load commands in the "
213 "file)"));
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000214 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000215}
216
Alexey Samsonov9f336632015-06-04 19:45:22 +0000217template <typename T>
218static void parseHeader(const MachOObjectFile *Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000219 Error &Err) {
Kevin Enderby87025742016-04-13 21:17:58 +0000220 if (sizeof(T) > Obj->getData().size()) {
221 Err = malformedError(*Obj, "truncated or malformed object (the mach header "
222 "extends past the end of the file)");
223 return;
224 }
Lang Hames9e964f32016-03-25 17:25:34 +0000225 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
226 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000227 else
Lang Hames9e964f32016-03-25 17:25:34 +0000228 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000229}
230
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000231// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
232// sections to \param Sections, and optionally sets
233// \param IsPageZeroSegment to true.
234template <typename SegmentCmd>
Lang Hames9e964f32016-03-25 17:25:34 +0000235static Error parseSegmentLoadCommand(
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000236 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000237 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
238 uint32_t LoadCommandIndex, const char *CmdName) {
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000239 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
240 if (Load.C.cmdsize < SegmentLoadSize)
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000241 return malformedError(*Obj, Twine("truncated or malformed object "
242 "(load command ") + Twine(LoadCommandIndex) +
243 Twine(" ") + CmdName + Twine(" cmdsize too small)"));
Lang Hames9e964f32016-03-25 17:25:34 +0000244 if (auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr)) {
245 SegmentCmd S = SegOrErr.get();
246 const unsigned SectionSize =
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000247 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
Lang Hames9e964f32016-03-25 17:25:34 +0000248 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
249 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000250 return malformedError(*Obj, Twine("truncated or malformed object "
251 "(load command ") + Twine(LoadCommandIndex) +
252 Twine(" inconsistent cmdsize in ") + CmdName +
253 Twine(" for the number of sections)"));
Lang Hames9e964f32016-03-25 17:25:34 +0000254 for (unsigned J = 0; J < S.nsects; ++J) {
255 const char *Sec = getSectionPtr(Obj, Load, J);
256 Sections.push_back(Sec);
257 }
258 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
259 } else
260 return SegOrErr.takeError();
261
262 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000263}
264
Lang Hames82627642016-03-25 21:59:14 +0000265Expected<std::unique_ptr<MachOObjectFile>>
266MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
267 bool Is64Bits) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000268 Error Err;
Lang Hames82627642016-03-25 21:59:14 +0000269 std::unique_ptr<MachOObjectFile> Obj(
270 new MachOObjectFile(std::move(Object), IsLittleEndian,
271 Is64Bits, Err));
272 if (Err)
273 return std::move(Err);
274 return std::move(Obj);
275}
276
Rafael Espindola48af1c22014-08-19 18:44:46 +0000277MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Lang Hames9e964f32016-03-25 17:25:34 +0000278 bool Is64bits, Error &Err)
Rafael Espindola48af1c22014-08-19 18:44:46 +0000279 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000280 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000281 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
282 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
283 HasPageZeroSegment(false) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000284 ErrorAsOutParameter ErrAsOutParam(Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000285 uint64_t BigSize;
Kevin Enderby87025742016-04-13 21:17:58 +0000286 if (is64Bit()) {
Lang Hames9e964f32016-03-25 17:25:34 +0000287 parseHeader(this, Header64, Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000288 BigSize = sizeof(MachO::mach_header_64);
Kevin Enderby87025742016-04-13 21:17:58 +0000289 } else {
Lang Hames9e964f32016-03-25 17:25:34 +0000290 parseHeader(this, Header, Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000291 BigSize = sizeof(MachO::mach_header);
Kevin Enderby87025742016-04-13 21:17:58 +0000292 }
Lang Hames9e964f32016-03-25 17:25:34 +0000293 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +0000294 return;
Kevin Enderby5e55d172016-04-21 20:29:49 +0000295 BigSize += getHeader().sizeofcmds;
296 if (getData().data() + BigSize > getData().end()) {
Kevin Enderby87025742016-04-13 21:17:58 +0000297 Err = malformedError(getFileName(), "truncated or malformed object "
Kevin Enderby6e295f22016-04-21 21:20:40 +0000298 "(load commands extend past the end of the file)");
Kevin Enderby87025742016-04-13 21:17:58 +0000299 return;
300 }
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000301
302 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000303 if (LoadCommandCount == 0)
304 return;
305
Lang Hames9e964f32016-03-25 17:25:34 +0000306 LoadCommandInfo Load;
307 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
308 Load = *LoadOrErr;
309 else {
310 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000311 return;
312 }
Lang Hames9e964f32016-03-25 17:25:34 +0000313
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000314 for (unsigned I = 0; I < LoadCommandCount; ++I) {
315 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000316 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000317 // Multiple symbol tables
318 if (SymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000319 Err = malformedError(*this, "Multiple symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000320 return;
321 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000322 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000323 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000324 // Multiple dynamic symbol tables
325 if (DysymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000326 Err = malformedError(*this, "Multiple dynamic symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000327 return;
328 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000329 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000330 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000331 // Multiple data in code tables
332 if (DataInCodeLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000333 Err = malformedError(*this, "Multiple data-in-code tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000334 return;
335 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000336 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000337 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
338 // Multiple linker optimization hint tables
339 if (LinkOptHintsLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000340 Err = malformedError(*this, "Multiple linker optimization hint tables");
Kevin Enderby9a509442015-01-27 21:28:24 +0000341 return;
342 }
343 LinkOptHintsLoadCmd = Load.Ptr;
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +0000344 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Nick Kledzikd04bc352014-08-30 00:20:14 +0000345 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000346 // Multiple dyldinfo load commands
347 if (DyldInfoLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000348 Err = malformedError(*this, "Multiple dyldinfo load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000349 return;
350 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000351 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000352 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000353 // Multiple UUID load commands
354 if (UuidLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000355 Err = malformedError(*this, "Multiple UUID load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000356 return;
357 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000358 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000359 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Lang Hames9e964f32016-03-25 17:25:34 +0000360 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000361 this, Load, Sections, HasPageZeroSegment, I,
362 "LC_SEGMENT_64")))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000363 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000364 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Lang Hames9e964f32016-03-25 17:25:34 +0000365 if ((Err = parseSegmentLoadCommand<MachO::segment_command>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000366 this, Load, Sections, HasPageZeroSegment, I, "LC_SEGMENT")))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000367 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000368 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
369 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
370 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
371 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
372 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
373 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000374 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000375 if (I < LoadCommandCount - 1) {
Kevin Enderby368e7142016-05-03 17:16:08 +0000376 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +0000377 Load = *LoadOrErr;
378 else {
379 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000380 return;
381 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000382 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000383 }
Kevin Enderby1829c682016-01-22 22:49:55 +0000384 if (!SymtabLoadCmd) {
385 if (DysymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000386 Err = malformedError(*this,
387 "truncated or malformed object (contains "
388 "LC_DYSYMTAB load command without a LC_SYMTAB load "
389 "command)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000390 return;
391 }
392 } else if (DysymtabLoadCmd) {
393 MachO::symtab_command Symtab =
394 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
395 MachO::dysymtab_command Dysymtab =
396 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
397 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000398 Err = malformedError(*this,
399 "truncated or malformed object (iolocalsym in "
400 "LC_DYSYMTAB load command extends past the end of "
401 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000402 return;
403 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000404 uint64_t BigSize = Dysymtab.ilocalsym;
405 BigSize += Dysymtab.nlocalsym;
406 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000407 Err = malformedError(*this,
408 "truncated or malformed object (ilocalsym plus "
409 "nlocalsym in LC_DYSYMTAB load command extends past "
410 "the end of the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000411 return;
412 }
413 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000414 Err = malformedError(*this,
415 "truncated or malformed object (nextdefsym in "
416 "LC_DYSYMTAB load command extends past the end of "
417 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000418 return;
419 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000420 BigSize = Dysymtab.iextdefsym;
421 BigSize += Dysymtab.nextdefsym;
422 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000423 Err = malformedError(*this,
424 "truncated or malformed object (iextdefsym plus "
425 "nextdefsym in LC_DYSYMTAB load command extends "
426 "past the end of the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000427 return;
428 }
429 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000430 Err = malformedError(*this,
431 "truncated or malformed object (nundefsym in "
432 "LC_DYSYMTAB load command extends past the end of "
433 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000434 return;
435 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000436 BigSize = Dysymtab.iundefsym;
437 BigSize += Dysymtab.nundefsym;
438 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000439 Err = malformedError(*this,
440 "truncated or malformed object (iundefsym plus "
441 "nundefsym in LC_DYSYMTAB load command extends past "
442 "the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000443 return;
444 }
445 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000446 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +0000447
448 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000449}
450
Rafael Espindola5e812af2014-01-30 02:49:50 +0000451void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000452 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000453 sizeof(MachO::nlist_64) :
454 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000455 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000456}
457
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000458Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000459 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000460 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000461 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000462 if (Start < getData().begin() || Start >= getData().end()) {
463 return malformedError(*this, Twine("truncated or malformed object (bad "
464 "string index: ") + Twine(Entry.n_strx) + Twine(" for "
465 "symbol at index ") + Twine(getSymbolIndex(Symb)) +
466 Twine(")"));
467 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000468 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000469}
470
Rafael Espindola0e77a942014-12-10 20:46:55 +0000471unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
472 DataRefImpl DRI = Sec.getRawDataRefImpl();
473 uint32_t Flags = getSectionFlags(this, DRI);
474 return Flags & MachO::SECTION_TYPE;
475}
476
Rafael Espindola59128922015-06-24 18:14:41 +0000477uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
478 if (is64Bit()) {
479 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
480 return Entry.n_value;
481 }
482 MachO::nlist Entry = getSymbolTableEntry(Sym);
483 return Entry.n_value;
484}
485
Kevin Enderby980b2582014-06-05 21:21:57 +0000486// getIndirectName() returns the name of the alias'ed symbol who's string table
487// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000488std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
489 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000490 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000491 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
492 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
493 return object_error::parse_failed;
494 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000495 if (NValue >= StringTable.size())
496 return object_error::parse_failed;
497 const char *Start = &StringTable.data()[NValue];
498 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000499 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000500}
501
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +0000502uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +0000503 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +0000504}
505
Rafael Espindolaed067c42015-07-03 18:19:00 +0000506ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
507 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000508}
509
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000510uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000511 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000512 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000513 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000514 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000515 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000516 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000517}
518
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000519uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000520 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000521}
522
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000523Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000524MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000525 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000526 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000527
Rafael Espindola56f976f2013-04-18 18:08:55 +0000528 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000529 if (n_type & MachO::N_STAB)
530 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000531
Charles Davis74ec8b02013-08-27 05:00:13 +0000532 switch (n_type & MachO::N_TYPE) {
533 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000534 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +0000535 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000536 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000537 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000538 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000539 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +0000540 if (Sec->isData() || Sec->isBSS())
541 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000542 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000543 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000544 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000545}
546
Rafael Espindola20122a42014-01-31 20:57:12 +0000547uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000548 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000549
Charles Davis8bdfafd2013-09-01 04:28:48 +0000550 uint8_t MachOType = Entry.n_type;
551 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000552
Rafael Espindola20122a42014-01-31 20:57:12 +0000553 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000554
Tim Northovereaef0742014-05-30 13:22:59 +0000555 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
556 Result |= SymbolRef::SF_Indirect;
557
Rafael Espindolaa1356322013-11-02 05:03:24 +0000558 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000559 Result |= SymbolRef::SF_FormatSpecific;
560
Charles Davis74ec8b02013-08-27 05:00:13 +0000561 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000562 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000563 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000564 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000565 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +0000566 else
567 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000568 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000569
570 if (!(MachOType & MachO::N_PEXT))
571 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000572 }
573
Charles Davis74ec8b02013-08-27 05:00:13 +0000574 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000575 Result |= SymbolRef::SF_Weak;
576
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000577 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
578 Result |= SymbolRef::SF_Thumb;
579
Charles Davis74ec8b02013-08-27 05:00:13 +0000580 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000581 Result |= SymbolRef::SF_Absolute;
582
Rafael Espindola20122a42014-01-31 20:57:12 +0000583 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000584}
585
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000586Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +0000587MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000588 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000589 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000590
Rafael Espindola8bab8892015-08-07 23:27:14 +0000591 if (index == 0)
592 return section_end();
593 DataRefImpl DRI;
594 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000595 if (DRI.d.a >= Sections.size()){
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000596 return malformedError(*this, Twine("truncated or malformed object (bad "
597 "section index: ") + Twine((int)index) + Twine(" for "
598 "symbol at index ") + Twine(getSymbolIndex(Symb)) +
599 Twine(")"));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000600 }
Rafael Espindola8bab8892015-08-07 23:27:14 +0000601 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000602}
603
Rafael Espindola6bf32212015-06-24 19:57:32 +0000604unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
605 MachO::nlist_base Entry =
606 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
607 return Entry.n_sect - 1;
608}
609
Rafael Espindola5e812af2014-01-30 02:49:50 +0000610void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000611 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000612}
613
Rafael Espindola3acea392014-06-12 21:46:39 +0000614std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
615 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000616 ArrayRef<char> Raw = getSectionRawName(Sec);
617 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000618 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000619}
620
Rafael Espindola80291272014-10-08 15:28:58 +0000621uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
622 if (is64Bit())
623 return getSection64(Sec).addr;
624 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000625}
626
Rafael Espindola80291272014-10-08 15:28:58 +0000627uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +0000628 // In the case if a malformed Mach-O file where the section offset is past
629 // the end of the file or some part of the section size is past the end of
630 // the file return a size of zero or a size that covers the rest of the file
631 // but does not extend past the end of the file.
632 uint32_t SectOffset, SectType;
633 uint64_t SectSize;
634
635 if (is64Bit()) {
636 MachO::section_64 Sect = getSection64(Sec);
637 SectOffset = Sect.offset;
638 SectSize = Sect.size;
639 SectType = Sect.flags & MachO::SECTION_TYPE;
640 } else {
641 MachO::section Sect = getSection(Sec);
642 SectOffset = Sect.offset;
643 SectSize = Sect.size;
644 SectType = Sect.flags & MachO::SECTION_TYPE;
645 }
646 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
647 return SectSize;
648 uint64_t FileSize = getData().size();
649 if (SectOffset > FileSize)
650 return 0;
651 if (FileSize - SectOffset < SectSize)
652 return FileSize - SectOffset;
653 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000654}
655
Rafael Espindola3acea392014-06-12 21:46:39 +0000656std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
657 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000658 uint32_t Offset;
659 uint64_t Size;
660
661 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000662 MachO::section_64 Sect = getSection64(Sec);
663 Offset = Sect.offset;
664 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000665 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000666 MachO::section Sect = getSection(Sec);
667 Offset = Sect.offset;
668 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000669 }
670
671 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000672 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000673}
674
Rafael Espindola80291272014-10-08 15:28:58 +0000675uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000676 uint32_t Align;
677 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000678 MachO::section_64 Sect = getSection64(Sec);
679 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000680 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000681 MachO::section Sect = getSection(Sec);
682 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000683 }
684
Rafael Espindola80291272014-10-08 15:28:58 +0000685 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000686}
687
Rafael Espindola80291272014-10-08 15:28:58 +0000688bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000689 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000690 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000691}
692
Rafael Espindola80291272014-10-08 15:28:58 +0000693bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000694 uint32_t Flags = getSectionFlags(this, Sec);
695 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000696 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
697 !(SectionType == MachO::S_ZEROFILL ||
698 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000699}
700
Rafael Espindola80291272014-10-08 15:28:58 +0000701bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000702 uint32_t Flags = getSectionFlags(this, Sec);
703 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000704 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
705 (SectionType == MachO::S_ZEROFILL ||
706 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000707}
708
Rafael Espindola6bf32212015-06-24 19:57:32 +0000709unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
710 return Sec.getRawDataRefImpl().d.a;
711}
712
Rafael Espindola80291272014-10-08 15:28:58 +0000713bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000714 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000715 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000716}
717
Steven Wuf2fe0142016-02-29 19:40:10 +0000718bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
719 StringRef SegmentName = getSectionFinalSegmentName(Sec);
720 StringRef SectName;
721 if (!getSectionName(Sec, SectName))
722 return (SegmentName == "__LLVM" && SectName == "__bitcode");
723 return false;
724}
725
Rui Ueyamabc654b12013-09-27 21:47:05 +0000726relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000727 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000728 Ret.d.a = Sec.d.a;
729 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000730 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000731}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000732
Rafael Espindola56f976f2013-04-18 18:08:55 +0000733relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000734MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000735 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000736 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000737 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000738 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000739 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000740 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000741 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000742 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000743
Rafael Espindola56f976f2013-04-18 18:08:55 +0000744 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000745 Ret.d.a = Sec.d.a;
746 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000747 return relocation_iterator(RelocationRef(Ret, this));
748}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000749
Rafael Espindola5e812af2014-01-30 02:49:50 +0000750void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000751 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000752}
Owen Anderson171f4852011-10-24 23:20:07 +0000753
Rafael Espindola96d071c2015-06-29 23:29:12 +0000754uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000755 assert(getHeader().filetype == MachO::MH_OBJECT &&
756 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000757 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000758 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +0000759}
760
Rafael Espindola806f0062013-06-05 01:33:53 +0000761symbol_iterator
762MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000763 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000764 if (isRelocationScattered(RE))
765 return symbol_end();
766
Rafael Espindola56f976f2013-04-18 18:08:55 +0000767 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
768 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000769 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000770 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000771
Charles Davis8bdfafd2013-09-01 04:28:48 +0000772 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000773 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000774 sizeof(MachO::nlist_64) :
775 sizeof(MachO::nlist);
776 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000777 DataRefImpl Sym;
778 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000779 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000780}
781
Keno Fischerc780e8e2015-05-21 21:24:32 +0000782section_iterator
783MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
784 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
785}
786
Rafael Espindola99c041b2015-06-30 01:53:01 +0000787uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000788 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +0000789 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000790}
791
Rafael Espindola41bb4322015-06-30 04:08:37 +0000792void MachOObjectFile::getRelocationTypeName(
793 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000794 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +0000795 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000796
797 unsigned Arch = this->getArch();
798
799 switch (Arch) {
800 case Triple::x86: {
801 static const char *const Table[] = {
802 "GENERIC_RELOC_VANILLA",
803 "GENERIC_RELOC_PAIR",
804 "GENERIC_RELOC_SECTDIFF",
805 "GENERIC_RELOC_PB_LA_PTR",
806 "GENERIC_RELOC_LOCAL_SECTDIFF",
807 "GENERIC_RELOC_TLV" };
808
Eric Christopher13250cb2013-12-06 02:33:38 +0000809 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000810 res = "Unknown";
811 else
812 res = Table[RType];
813 break;
814 }
815 case Triple::x86_64: {
816 static const char *const Table[] = {
817 "X86_64_RELOC_UNSIGNED",
818 "X86_64_RELOC_SIGNED",
819 "X86_64_RELOC_BRANCH",
820 "X86_64_RELOC_GOT_LOAD",
821 "X86_64_RELOC_GOT",
822 "X86_64_RELOC_SUBTRACTOR",
823 "X86_64_RELOC_SIGNED_1",
824 "X86_64_RELOC_SIGNED_2",
825 "X86_64_RELOC_SIGNED_4",
826 "X86_64_RELOC_TLV" };
827
828 if (RType > 9)
829 res = "Unknown";
830 else
831 res = Table[RType];
832 break;
833 }
834 case Triple::arm: {
835 static const char *const Table[] = {
836 "ARM_RELOC_VANILLA",
837 "ARM_RELOC_PAIR",
838 "ARM_RELOC_SECTDIFF",
839 "ARM_RELOC_LOCAL_SECTDIFF",
840 "ARM_RELOC_PB_LA_PTR",
841 "ARM_RELOC_BR24",
842 "ARM_THUMB_RELOC_BR22",
843 "ARM_THUMB_32BIT_BRANCH",
844 "ARM_RELOC_HALF",
845 "ARM_RELOC_HALF_SECTDIFF" };
846
847 if (RType > 9)
848 res = "Unknown";
849 else
850 res = Table[RType];
851 break;
852 }
Tim Northover00ed9962014-03-29 10:18:08 +0000853 case Triple::aarch64: {
854 static const char *const Table[] = {
855 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
856 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
857 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
858 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
859 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
860 "ARM64_RELOC_ADDEND"
861 };
862
863 if (RType >= array_lengthof(Table))
864 res = "Unknown";
865 else
866 res = Table[RType];
867 break;
868 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000869 case Triple::ppc: {
870 static const char *const Table[] = {
871 "PPC_RELOC_VANILLA",
872 "PPC_RELOC_PAIR",
873 "PPC_RELOC_BR14",
874 "PPC_RELOC_BR24",
875 "PPC_RELOC_HI16",
876 "PPC_RELOC_LO16",
877 "PPC_RELOC_HA16",
878 "PPC_RELOC_LO14",
879 "PPC_RELOC_SECTDIFF",
880 "PPC_RELOC_PB_LA_PTR",
881 "PPC_RELOC_HI16_SECTDIFF",
882 "PPC_RELOC_LO16_SECTDIFF",
883 "PPC_RELOC_HA16_SECTDIFF",
884 "PPC_RELOC_JBSR",
885 "PPC_RELOC_LO14_SECTDIFF",
886 "PPC_RELOC_LOCAL_SECTDIFF" };
887
Eric Christopher13250cb2013-12-06 02:33:38 +0000888 if (RType > 15)
889 res = "Unknown";
890 else
891 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000892 break;
893 }
894 case Triple::UnknownArch:
895 res = "Unknown";
896 break;
897 }
898 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +0000899}
900
Keno Fischer281b6942015-05-30 19:44:53 +0000901uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
902 MachO::any_relocation_info RE = getRelocation(Rel);
903 return getAnyRelocationLength(RE);
904}
905
Kevin Enderby980b2582014-06-05 21:21:57 +0000906//
907// guessLibraryShortName() is passed a name of a dynamic library and returns a
908// guess on what the short name is. Then name is returned as a substring of the
909// StringRef Name passed in. The name of the dynamic library is recognized as
910// a framework if it has one of the two following forms:
911// Foo.framework/Versions/A/Foo
912// Foo.framework/Foo
913// Where A and Foo can be any string. And may contain a trailing suffix
914// starting with an underbar. If the Name is recognized as a framework then
915// isFramework is set to true else it is set to false. If the Name has a
916// suffix then Suffix is set to the substring in Name that contains the suffix
917// else it is set to a NULL StringRef.
918//
919// The Name of the dynamic library is recognized as a library name if it has
920// one of the two following forms:
921// libFoo.A.dylib
922// libFoo.dylib
923// The library may have a suffix trailing the name Foo of the form:
924// libFoo_profile.A.dylib
925// libFoo_profile.dylib
926//
927// The Name of the dynamic library is also recognized as a library name if it
928// has the following form:
929// Foo.qtx
930//
931// If the Name of the dynamic library is none of the forms above then a NULL
932// StringRef is returned.
933//
934StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
935 bool &isFramework,
936 StringRef &Suffix) {
937 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
938 size_t a, b, c, d, Idx;
939
940 isFramework = false;
941 Suffix = StringRef();
942
943 // Pull off the last component and make Foo point to it
944 a = Name.rfind('/');
945 if (a == Name.npos || a == 0)
946 goto guess_library;
947 Foo = Name.slice(a+1, Name.npos);
948
949 // Look for a suffix starting with a '_'
950 Idx = Foo.rfind('_');
951 if (Idx != Foo.npos && Foo.size() >= 2) {
952 Suffix = Foo.slice(Idx, Foo.npos);
953 Foo = Foo.slice(0, Idx);
954 }
955
956 // First look for the form Foo.framework/Foo
957 b = Name.rfind('/', a);
958 if (b == Name.npos)
959 Idx = 0;
960 else
961 Idx = b+1;
962 F = Name.slice(Idx, Idx + Foo.size());
963 DotFramework = Name.slice(Idx + Foo.size(),
964 Idx + Foo.size() + sizeof(".framework/")-1);
965 if (F == Foo && DotFramework == ".framework/") {
966 isFramework = true;
967 return Foo;
968 }
969
970 // Next look for the form Foo.framework/Versions/A/Foo
971 if (b == Name.npos)
972 goto guess_library;
973 c = Name.rfind('/', b);
974 if (c == Name.npos || c == 0)
975 goto guess_library;
976 V = Name.slice(c+1, Name.npos);
977 if (!V.startswith("Versions/"))
978 goto guess_library;
979 d = Name.rfind('/', c);
980 if (d == Name.npos)
981 Idx = 0;
982 else
983 Idx = d+1;
984 F = Name.slice(Idx, Idx + Foo.size());
985 DotFramework = Name.slice(Idx + Foo.size(),
986 Idx + Foo.size() + sizeof(".framework/")-1);
987 if (F == Foo && DotFramework == ".framework/") {
988 isFramework = true;
989 return Foo;
990 }
991
992guess_library:
993 // pull off the suffix after the "." and make a point to it
994 a = Name.rfind('.');
995 if (a == Name.npos || a == 0)
996 return StringRef();
997 Dylib = Name.slice(a, Name.npos);
998 if (Dylib != ".dylib")
999 goto guess_qtx;
1000
1001 // First pull off the version letter for the form Foo.A.dylib if any.
1002 if (a >= 3) {
1003 Dot = Name.slice(a-2, a-1);
1004 if (Dot == ".")
1005 a = a - 2;
1006 }
1007
1008 b = Name.rfind('/', a);
1009 if (b == Name.npos)
1010 b = 0;
1011 else
1012 b = b+1;
1013 // ignore any suffix after an underbar like Foo_profile.A.dylib
1014 Idx = Name.find('_', b);
1015 if (Idx != Name.npos && Idx != b) {
1016 Lib = Name.slice(b, Idx);
1017 Suffix = Name.slice(Idx, a);
1018 }
1019 else
1020 Lib = Name.slice(b, a);
1021 // There are incorrect library names of the form:
1022 // libATS.A_profile.dylib so check for these.
1023 if (Lib.size() >= 3) {
1024 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1025 if (Dot == ".")
1026 Lib = Lib.slice(0, Lib.size()-2);
1027 }
1028 return Lib;
1029
1030guess_qtx:
1031 Qtx = Name.slice(a, Name.npos);
1032 if (Qtx != ".qtx")
1033 return StringRef();
1034 b = Name.rfind('/', a);
1035 if (b == Name.npos)
1036 Lib = Name.slice(0, a);
1037 else
1038 Lib = Name.slice(b+1, a);
1039 // There are library names of the form: QT.A.qtx so check for these.
1040 if (Lib.size() >= 3) {
1041 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1042 if (Dot == ".")
1043 Lib = Lib.slice(0, Lib.size()-2);
1044 }
1045 return Lib;
1046}
1047
1048// getLibraryShortNameByIndex() is used to get the short name of the library
1049// for an undefined symbol in a linked Mach-O binary that was linked with the
1050// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1051// It is passed the index (0 - based) of the library as translated from
1052// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001053std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001054 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001055 if (Index >= Libraries.size())
1056 return object_error::parse_failed;
1057
Kevin Enderby980b2582014-06-05 21:21:57 +00001058 // If the cache of LibrariesShortNames is not built up do that first for
1059 // all the Libraries.
1060 if (LibrariesShortNames.size() == 0) {
1061 for (unsigned i = 0; i < Libraries.size(); i++) {
1062 MachO::dylib_command D =
1063 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001064 if (D.dylib.name >= D.cmdsize)
1065 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001066 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001067 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001068 if (D.dylib.name+Name.size() >= D.cmdsize)
1069 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001070 StringRef Suffix;
1071 bool isFramework;
1072 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001073 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001074 LibrariesShortNames.push_back(Name);
1075 else
1076 LibrariesShortNames.push_back(shortName);
1077 }
1078 }
1079
1080 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00001081 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001082}
1083
Rafael Espindola76ad2322015-07-06 14:55:37 +00001084section_iterator
1085MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
1086 DataRefImpl Sec;
1087 Sec.d.a = Rel->getRawDataRefImpl().d.a;
1088 return section_iterator(SectionRef(Sec, this));
1089}
1090
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001091basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00001092 DataRefImpl DRI;
1093 MachO::symtab_command Symtab = getSymtabLoadCommand();
1094 if (!SymtabLoadCmd || Symtab.nsyms == 0)
1095 return basic_symbol_iterator(SymbolRef(DRI, this));
1096
Lang Hames36072da2014-05-12 21:39:59 +00001097 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001098}
1099
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001100basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001101 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00001102 MachO::symtab_command Symtab = getSymtabLoadCommand();
1103 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001104 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001105
Rafael Espindola75c30362013-04-24 19:47:55 +00001106 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001107 sizeof(MachO::nlist_64) :
1108 sizeof(MachO::nlist);
1109 unsigned Offset = Symtab.symoff +
1110 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001111 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001112 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001113}
1114
Lang Hames36072da2014-05-12 21:39:59 +00001115basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00001116 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00001117 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001118 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001119 unsigned SymbolTableEntrySize =
1120 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00001121 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00001122 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1123 DRI.p += Index * SymbolTableEntrySize;
1124 return basic_symbol_iterator(SymbolRef(DRI, this));
1125}
1126
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001127uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
1128 MachO::symtab_command Symtab = getSymtabLoadCommand();
1129 if (!SymtabLoadCmd)
1130 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
1131 unsigned SymbolTableEntrySize =
1132 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1133 DataRefImpl DRIstart;
1134 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1135 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
1136 return Index;
1137}
1138
Rafael Espindolab5155a52014-02-10 20:24:04 +00001139section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001140 DataRefImpl DRI;
1141 return section_iterator(SectionRef(DRI, this));
1142}
1143
Rafael Espindolab5155a52014-02-10 20:24:04 +00001144section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001145 DataRefImpl DRI;
1146 DRI.d.a = Sections.size();
1147 return section_iterator(SectionRef(DRI, this));
1148}
1149
Rafael Espindola56f976f2013-04-18 18:08:55 +00001150uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001151 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001152}
1153
Rafael Espindola56f976f2013-04-18 18:08:55 +00001154StringRef MachOObjectFile::getFileFormatName() const {
1155 unsigned CPUType = getCPUType(this);
1156 if (!is64Bit()) {
1157 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001158 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001159 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001160 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001161 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001162 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001163 return "Mach-O 32-bit ppc";
1164 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001165 return "Mach-O 32-bit unknown";
1166 }
1167 }
1168
Rafael Espindola56f976f2013-04-18 18:08:55 +00001169 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001170 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001171 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001172 case llvm::MachO::CPU_TYPE_ARM64:
1173 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001174 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001175 return "Mach-O 64-bit ppc64";
1176 default:
1177 return "Mach-O 64-bit unknown";
1178 }
1179}
1180
Alexey Samsonove6388e62013-06-18 15:03:28 +00001181Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1182 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001183 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001184 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001185 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001186 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001187 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001188 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001189 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001190 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001191 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001192 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001193 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001194 return Triple::ppc64;
1195 default:
1196 return Triple::UnknownArch;
1197 }
1198}
1199
Tim Northover9e8eb412016-04-22 23:21:13 +00001200Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
1201 const char **McpuDefault) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001202 if (McpuDefault)
1203 *McpuDefault = nullptr;
1204
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001205 switch (CPUType) {
1206 case MachO::CPU_TYPE_I386:
1207 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1208 case MachO::CPU_SUBTYPE_I386_ALL:
1209 return Triple("i386-apple-darwin");
1210 default:
1211 return Triple();
1212 }
1213 case MachO::CPU_TYPE_X86_64:
1214 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1215 case MachO::CPU_SUBTYPE_X86_64_ALL:
1216 return Triple("x86_64-apple-darwin");
1217 case MachO::CPU_SUBTYPE_X86_64_H:
1218 return Triple("x86_64h-apple-darwin");
1219 default:
1220 return Triple();
1221 }
1222 case MachO::CPU_TYPE_ARM:
1223 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1224 case MachO::CPU_SUBTYPE_ARM_V4T:
1225 return Triple("armv4t-apple-darwin");
1226 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1227 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001228 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1229 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001230 case MachO::CPU_SUBTYPE_ARM_V6:
1231 return Triple("armv6-apple-darwin");
1232 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001233 if (McpuDefault)
1234 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001235 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001236 case MachO::CPU_SUBTYPE_ARM_V7:
1237 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001238 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001239 if (McpuDefault)
1240 *McpuDefault = "cortex-m4";
Tim Northover9e8eb412016-04-22 23:21:13 +00001241 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001242 case MachO::CPU_SUBTYPE_ARM_V7K:
1243 return Triple("armv7k-apple-darwin");
1244 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001245 if (McpuDefault)
1246 *McpuDefault = "cortex-m3";
Tim Northover9e8eb412016-04-22 23:21:13 +00001247 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001248 case MachO::CPU_SUBTYPE_ARM_V7S:
1249 return Triple("armv7s-apple-darwin");
1250 default:
1251 return Triple();
1252 }
1253 case MachO::CPU_TYPE_ARM64:
1254 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1255 case MachO::CPU_SUBTYPE_ARM64_ALL:
1256 return Triple("arm64-apple-darwin");
1257 default:
1258 return Triple();
1259 }
1260 case MachO::CPU_TYPE_POWERPC:
1261 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1262 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1263 return Triple("ppc-apple-darwin");
1264 default:
1265 return Triple();
1266 }
1267 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001268 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001269 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1270 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001271 default:
1272 return Triple();
1273 }
1274 default:
1275 return Triple();
1276 }
1277}
1278
1279Triple MachOObjectFile::getHostArch() {
1280 return Triple(sys::getDefaultTargetTriple());
1281}
1282
Rafael Espindola72318b42014-08-08 16:30:17 +00001283bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1284 return StringSwitch<bool>(ArchFlag)
1285 .Case("i386", true)
1286 .Case("x86_64", true)
1287 .Case("x86_64h", true)
1288 .Case("armv4t", true)
1289 .Case("arm", true)
1290 .Case("armv5e", true)
1291 .Case("armv6", true)
1292 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001293 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001294 .Case("armv7em", true)
1295 .Case("armv7k", true)
1296 .Case("armv7m", true)
1297 .Case("armv7s", true)
1298 .Case("arm64", true)
1299 .Case("ppc", true)
1300 .Case("ppc64", true)
1301 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001302}
1303
Alexey Samsonove6388e62013-06-18 15:03:28 +00001304unsigned MachOObjectFile::getArch() const {
1305 return getArch(getCPUType(this));
1306}
1307
Tim Northover9e8eb412016-04-22 23:21:13 +00001308Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
1309 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001310}
1311
Rui Ueyamabc654b12013-09-27 21:47:05 +00001312relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001313 DataRefImpl DRI;
1314 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001315 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001316}
1317
Rui Ueyamabc654b12013-09-27 21:47:05 +00001318relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001319 DataRefImpl DRI;
1320 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001321 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001322}
1323
Kevin Enderby273ae012013-06-06 17:20:50 +00001324dice_iterator MachOObjectFile::begin_dices() const {
1325 DataRefImpl DRI;
1326 if (!DataInCodeLoadCmd)
1327 return dice_iterator(DiceRef(DRI, this));
1328
Charles Davis8bdfafd2013-09-01 04:28:48 +00001329 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1330 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001331 return dice_iterator(DiceRef(DRI, this));
1332}
1333
1334dice_iterator MachOObjectFile::end_dices() const {
1335 DataRefImpl DRI;
1336 if (!DataInCodeLoadCmd)
1337 return dice_iterator(DiceRef(DRI, this));
1338
Charles Davis8bdfafd2013-09-01 04:28:48 +00001339 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1340 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001341 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1342 return dice_iterator(DiceRef(DRI, this));
1343}
1344
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001345ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1346 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001347
1348void ExportEntry::moveToFirst() {
1349 pushNode(0);
1350 pushDownUntilBottom();
1351}
1352
1353void ExportEntry::moveToEnd() {
1354 Stack.clear();
1355 Done = true;
1356}
1357
1358bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001359 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001360 if (Done || Other.Done)
1361 return (Done == Other.Done);
1362 // Not equal if different stack sizes.
1363 if (Stack.size() != Other.Stack.size())
1364 return false;
1365 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001366 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001367 return false;
1368 // Equal if all nodes in both stacks match.
1369 for (unsigned i=0; i < Stack.size(); ++i) {
1370 if (Stack[i].Start != Other.Stack[i].Start)
1371 return false;
1372 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001373 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001374}
1375
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001376uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1377 unsigned Count;
1378 uint64_t Result = decodeULEB128(Ptr, &Count);
1379 Ptr += Count;
1380 if (Ptr > Trie.end()) {
1381 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001382 Malformed = true;
1383 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001384 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001385}
1386
1387StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001388 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001389}
1390
1391uint64_t ExportEntry::flags() const {
1392 return Stack.back().Flags;
1393}
1394
1395uint64_t ExportEntry::address() const {
1396 return Stack.back().Address;
1397}
1398
1399uint64_t ExportEntry::other() const {
1400 return Stack.back().Other;
1401}
1402
1403StringRef ExportEntry::otherName() const {
1404 const char* ImportName = Stack.back().ImportName;
1405 if (ImportName)
1406 return StringRef(ImportName);
1407 return StringRef();
1408}
1409
1410uint32_t ExportEntry::nodeOffset() const {
1411 return Stack.back().Start - Trie.begin();
1412}
1413
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001414ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1415 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1416 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1417 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001418
1419void ExportEntry::pushNode(uint64_t offset) {
1420 const uint8_t *Ptr = Trie.begin() + offset;
1421 NodeState State(Ptr);
1422 uint64_t ExportInfoSize = readULEB128(State.Current);
1423 State.IsExportNode = (ExportInfoSize != 0);
1424 const uint8_t* Children = State.Current + ExportInfoSize;
1425 if (State.IsExportNode) {
1426 State.Flags = readULEB128(State.Current);
1427 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1428 State.Address = 0;
1429 State.Other = readULEB128(State.Current); // dylib ordinal
1430 State.ImportName = reinterpret_cast<const char*>(State.Current);
1431 } else {
1432 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001433 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001434 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001435 }
1436 }
1437 State.ChildCount = *Children;
1438 State.Current = Children + 1;
1439 State.NextChildIndex = 0;
1440 State.ParentStringLength = CumulativeString.size();
1441 Stack.push_back(State);
1442}
1443
1444void ExportEntry::pushDownUntilBottom() {
1445 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1446 NodeState &Top = Stack.back();
1447 CumulativeString.resize(Top.ParentStringLength);
1448 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001449 char C = *Top.Current;
1450 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001451 }
1452 Top.Current += 1;
1453 uint64_t childNodeIndex = readULEB128(Top.Current);
1454 Top.NextChildIndex += 1;
1455 pushNode(childNodeIndex);
1456 }
1457 if (!Stack.back().IsExportNode) {
1458 Malformed = true;
1459 moveToEnd();
1460 }
1461}
1462
1463// We have a trie data structure and need a way to walk it that is compatible
1464// with the C++ iterator model. The solution is a non-recursive depth first
1465// traversal where the iterator contains a stack of parent nodes along with a
1466// string that is the accumulation of all edge strings along the parent chain
1467// to this point.
1468//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001469// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001470// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001471// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001472//
1473// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1474// child until hitting a node with no children (which is an export node or
1475// else the trie is malformed). On the way down, each node is pushed on the
1476// stack ivar. If there is no more ways down, it pops up one and tries to go
1477// down a sibling path until a childless node is reached.
1478void ExportEntry::moveNext() {
1479 if (Stack.empty() || !Stack.back().IsExportNode) {
1480 Malformed = true;
1481 moveToEnd();
1482 return;
1483 }
1484
1485 Stack.pop_back();
1486 while (!Stack.empty()) {
1487 NodeState &Top = Stack.back();
1488 if (Top.NextChildIndex < Top.ChildCount) {
1489 pushDownUntilBottom();
1490 // Now at the next export node.
1491 return;
1492 } else {
1493 if (Top.IsExportNode) {
1494 // This node has no children but is itself an export node.
1495 CumulativeString.resize(Top.ParentStringLength);
1496 return;
1497 }
1498 Stack.pop_back();
1499 }
1500 }
1501 Done = true;
1502}
1503
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001504iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00001505MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1506 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001507 if (Trie.size() == 0)
1508 Start.moveToEnd();
1509 else
1510 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001511
1512 ExportEntry Finish(Trie);
1513 Finish.moveToEnd();
1514
Craig Topper15576e12015-12-06 05:08:07 +00001515 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00001516}
1517
1518iterator_range<export_iterator> MachOObjectFile::exports() const {
1519 return exports(getDyldInfoExportsTrie());
1520}
1521
Nick Kledzikac431442014-09-12 21:34:15 +00001522MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1523 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1524 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1525 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1526
1527void MachORebaseEntry::moveToFirst() {
1528 Ptr = Opcodes.begin();
1529 moveNext();
1530}
1531
1532void MachORebaseEntry::moveToEnd() {
1533 Ptr = Opcodes.end();
1534 RemainingLoopCount = 0;
1535 Done = true;
1536}
1537
1538void MachORebaseEntry::moveNext() {
1539 // If in the middle of some loop, move to next rebasing in loop.
1540 SegmentOffset += AdvanceAmount;
1541 if (RemainingLoopCount) {
1542 --RemainingLoopCount;
1543 return;
1544 }
1545 if (Ptr == Opcodes.end()) {
1546 Done = true;
1547 return;
1548 }
1549 bool More = true;
1550 while (More && !Malformed) {
1551 // Parse next opcode and set up next loop.
1552 uint8_t Byte = *Ptr++;
1553 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1554 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1555 switch (Opcode) {
1556 case MachO::REBASE_OPCODE_DONE:
1557 More = false;
1558 Done = true;
1559 moveToEnd();
1560 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1561 break;
1562 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1563 RebaseType = ImmValue;
1564 DEBUG_WITH_TYPE(
1565 "mach-o-rebase",
1566 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1567 << "RebaseType=" << (int) RebaseType << "\n");
1568 break;
1569 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1570 SegmentIndex = ImmValue;
1571 SegmentOffset = readULEB128();
1572 DEBUG_WITH_TYPE(
1573 "mach-o-rebase",
1574 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1575 << "SegmentIndex=" << SegmentIndex << ", "
1576 << format("SegmentOffset=0x%06X", SegmentOffset)
1577 << "\n");
1578 break;
1579 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1580 SegmentOffset += readULEB128();
1581 DEBUG_WITH_TYPE("mach-o-rebase",
1582 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1583 << format("SegmentOffset=0x%06X",
1584 SegmentOffset) << "\n");
1585 break;
1586 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1587 SegmentOffset += ImmValue * PointerSize;
1588 DEBUG_WITH_TYPE("mach-o-rebase",
1589 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1590 << format("SegmentOffset=0x%06X",
1591 SegmentOffset) << "\n");
1592 break;
1593 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1594 AdvanceAmount = PointerSize;
1595 RemainingLoopCount = ImmValue - 1;
1596 DEBUG_WITH_TYPE(
1597 "mach-o-rebase",
1598 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1599 << format("SegmentOffset=0x%06X", SegmentOffset)
1600 << ", AdvanceAmount=" << AdvanceAmount
1601 << ", RemainingLoopCount=" << RemainingLoopCount
1602 << "\n");
1603 return;
1604 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1605 AdvanceAmount = PointerSize;
1606 RemainingLoopCount = readULEB128() - 1;
1607 DEBUG_WITH_TYPE(
1608 "mach-o-rebase",
1609 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1610 << format("SegmentOffset=0x%06X", SegmentOffset)
1611 << ", AdvanceAmount=" << AdvanceAmount
1612 << ", RemainingLoopCount=" << RemainingLoopCount
1613 << "\n");
1614 return;
1615 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1616 AdvanceAmount = readULEB128() + PointerSize;
1617 RemainingLoopCount = 0;
1618 DEBUG_WITH_TYPE(
1619 "mach-o-rebase",
1620 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1621 << format("SegmentOffset=0x%06X", SegmentOffset)
1622 << ", AdvanceAmount=" << AdvanceAmount
1623 << ", RemainingLoopCount=" << RemainingLoopCount
1624 << "\n");
1625 return;
1626 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1627 RemainingLoopCount = readULEB128() - 1;
1628 AdvanceAmount = readULEB128() + PointerSize;
1629 DEBUG_WITH_TYPE(
1630 "mach-o-rebase",
1631 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1632 << format("SegmentOffset=0x%06X", SegmentOffset)
1633 << ", AdvanceAmount=" << AdvanceAmount
1634 << ", RemainingLoopCount=" << RemainingLoopCount
1635 << "\n");
1636 return;
1637 default:
1638 Malformed = true;
1639 }
1640 }
1641}
1642
1643uint64_t MachORebaseEntry::readULEB128() {
1644 unsigned Count;
1645 uint64_t Result = decodeULEB128(Ptr, &Count);
1646 Ptr += Count;
1647 if (Ptr > Opcodes.end()) {
1648 Ptr = Opcodes.end();
1649 Malformed = true;
1650 }
1651 return Result;
1652}
1653
1654uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1655
1656uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1657
1658StringRef MachORebaseEntry::typeName() const {
1659 switch (RebaseType) {
1660 case MachO::REBASE_TYPE_POINTER:
1661 return "pointer";
1662 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1663 return "text abs32";
1664 case MachO::REBASE_TYPE_TEXT_PCREL32:
1665 return "text rel32";
1666 }
1667 return "unknown";
1668}
1669
1670bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1671 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1672 return (Ptr == Other.Ptr) &&
1673 (RemainingLoopCount == Other.RemainingLoopCount) &&
1674 (Done == Other.Done);
1675}
1676
1677iterator_range<rebase_iterator>
1678MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1679 MachORebaseEntry Start(Opcodes, is64);
1680 Start.moveToFirst();
1681
1682 MachORebaseEntry Finish(Opcodes, is64);
1683 Finish.moveToEnd();
1684
Craig Topper15576e12015-12-06 05:08:07 +00001685 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00001686}
1687
1688iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1689 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1690}
1691
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001692MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00001693 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1694 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1695 BindType(0), PointerSize(is64Bit ? 8 : 4),
1696 TableKind(BK), Malformed(false), Done(false) {}
1697
1698void MachOBindEntry::moveToFirst() {
1699 Ptr = Opcodes.begin();
1700 moveNext();
1701}
1702
1703void MachOBindEntry::moveToEnd() {
1704 Ptr = Opcodes.end();
1705 RemainingLoopCount = 0;
1706 Done = true;
1707}
1708
1709void MachOBindEntry::moveNext() {
1710 // If in the middle of some loop, move to next binding in loop.
1711 SegmentOffset += AdvanceAmount;
1712 if (RemainingLoopCount) {
1713 --RemainingLoopCount;
1714 return;
1715 }
1716 if (Ptr == Opcodes.end()) {
1717 Done = true;
1718 return;
1719 }
1720 bool More = true;
1721 while (More && !Malformed) {
1722 // Parse next opcode and set up next loop.
1723 uint8_t Byte = *Ptr++;
1724 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1725 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1726 int8_t SignExtended;
1727 const uint8_t *SymStart;
1728 switch (Opcode) {
1729 case MachO::BIND_OPCODE_DONE:
1730 if (TableKind == Kind::Lazy) {
1731 // Lazying bindings have a DONE opcode between entries. Need to ignore
1732 // it to advance to next entry. But need not if this is last entry.
1733 bool NotLastEntry = false;
1734 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1735 if (*P) {
1736 NotLastEntry = true;
1737 }
1738 }
1739 if (NotLastEntry)
1740 break;
1741 }
1742 More = false;
1743 Done = true;
1744 moveToEnd();
1745 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1746 break;
1747 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1748 Ordinal = ImmValue;
1749 DEBUG_WITH_TYPE(
1750 "mach-o-bind",
1751 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1752 << "Ordinal=" << Ordinal << "\n");
1753 break;
1754 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1755 Ordinal = readULEB128();
1756 DEBUG_WITH_TYPE(
1757 "mach-o-bind",
1758 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1759 << "Ordinal=" << Ordinal << "\n");
1760 break;
1761 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1762 if (ImmValue) {
1763 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1764 Ordinal = SignExtended;
1765 } else
1766 Ordinal = 0;
1767 DEBUG_WITH_TYPE(
1768 "mach-o-bind",
1769 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1770 << "Ordinal=" << Ordinal << "\n");
1771 break;
1772 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1773 Flags = ImmValue;
1774 SymStart = Ptr;
1775 while (*Ptr) {
1776 ++Ptr;
1777 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001778 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1779 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001780 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001781 DEBUG_WITH_TYPE(
1782 "mach-o-bind",
1783 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1784 << "SymbolName=" << SymbolName << "\n");
1785 if (TableKind == Kind::Weak) {
1786 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1787 return;
1788 }
1789 break;
1790 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1791 BindType = ImmValue;
1792 DEBUG_WITH_TYPE(
1793 "mach-o-bind",
1794 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1795 << "BindType=" << (int)BindType << "\n");
1796 break;
1797 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1798 Addend = readSLEB128();
1799 if (TableKind == Kind::Lazy)
1800 Malformed = true;
1801 DEBUG_WITH_TYPE(
1802 "mach-o-bind",
1803 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1804 << "Addend=" << Addend << "\n");
1805 break;
1806 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1807 SegmentIndex = ImmValue;
1808 SegmentOffset = readULEB128();
1809 DEBUG_WITH_TYPE(
1810 "mach-o-bind",
1811 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1812 << "SegmentIndex=" << SegmentIndex << ", "
1813 << format("SegmentOffset=0x%06X", SegmentOffset)
1814 << "\n");
1815 break;
1816 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1817 SegmentOffset += readULEB128();
1818 DEBUG_WITH_TYPE("mach-o-bind",
1819 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1820 << format("SegmentOffset=0x%06X",
1821 SegmentOffset) << "\n");
1822 break;
1823 case MachO::BIND_OPCODE_DO_BIND:
1824 AdvanceAmount = PointerSize;
1825 RemainingLoopCount = 0;
1826 DEBUG_WITH_TYPE("mach-o-bind",
1827 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1828 << format("SegmentOffset=0x%06X",
1829 SegmentOffset) << "\n");
1830 return;
1831 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001832 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001833 RemainingLoopCount = 0;
1834 if (TableKind == Kind::Lazy)
1835 Malformed = true;
1836 DEBUG_WITH_TYPE(
1837 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001838 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001839 << format("SegmentOffset=0x%06X", SegmentOffset)
1840 << ", AdvanceAmount=" << AdvanceAmount
1841 << ", RemainingLoopCount=" << RemainingLoopCount
1842 << "\n");
1843 return;
1844 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001845 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001846 RemainingLoopCount = 0;
1847 if (TableKind == Kind::Lazy)
1848 Malformed = true;
1849 DEBUG_WITH_TYPE("mach-o-bind",
1850 llvm::dbgs()
1851 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1852 << format("SegmentOffset=0x%06X",
1853 SegmentOffset) << "\n");
1854 return;
1855 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1856 RemainingLoopCount = readULEB128() - 1;
1857 AdvanceAmount = readULEB128() + PointerSize;
1858 if (TableKind == Kind::Lazy)
1859 Malformed = true;
1860 DEBUG_WITH_TYPE(
1861 "mach-o-bind",
1862 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1863 << format("SegmentOffset=0x%06X", SegmentOffset)
1864 << ", AdvanceAmount=" << AdvanceAmount
1865 << ", RemainingLoopCount=" << RemainingLoopCount
1866 << "\n");
1867 return;
1868 default:
1869 Malformed = true;
1870 }
1871 }
1872}
1873
1874uint64_t MachOBindEntry::readULEB128() {
1875 unsigned Count;
1876 uint64_t Result = decodeULEB128(Ptr, &Count);
1877 Ptr += Count;
1878 if (Ptr > Opcodes.end()) {
1879 Ptr = Opcodes.end();
1880 Malformed = true;
1881 }
1882 return Result;
1883}
1884
1885int64_t MachOBindEntry::readSLEB128() {
1886 unsigned Count;
1887 int64_t Result = decodeSLEB128(Ptr, &Count);
1888 Ptr += Count;
1889 if (Ptr > Opcodes.end()) {
1890 Ptr = Opcodes.end();
1891 Malformed = true;
1892 }
1893 return Result;
1894}
1895
Nick Kledzik56ebef42014-09-16 01:41:51 +00001896uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1897
1898uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1899
1900StringRef MachOBindEntry::typeName() const {
1901 switch (BindType) {
1902 case MachO::BIND_TYPE_POINTER:
1903 return "pointer";
1904 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1905 return "text abs32";
1906 case MachO::BIND_TYPE_TEXT_PCREL32:
1907 return "text rel32";
1908 }
1909 return "unknown";
1910}
1911
1912StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1913
1914int64_t MachOBindEntry::addend() const { return Addend; }
1915
1916uint32_t MachOBindEntry::flags() const { return Flags; }
1917
1918int MachOBindEntry::ordinal() const { return Ordinal; }
1919
1920bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1921 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1922 return (Ptr == Other.Ptr) &&
1923 (RemainingLoopCount == Other.RemainingLoopCount) &&
1924 (Done == Other.Done);
1925}
1926
1927iterator_range<bind_iterator>
1928MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1929 MachOBindEntry::Kind BKind) {
1930 MachOBindEntry Start(Opcodes, is64, BKind);
1931 Start.moveToFirst();
1932
1933 MachOBindEntry Finish(Opcodes, is64, BKind);
1934 Finish.moveToEnd();
1935
Craig Topper15576e12015-12-06 05:08:07 +00001936 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00001937}
1938
1939iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1940 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1941 MachOBindEntry::Kind::Regular);
1942}
1943
1944iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1945 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1946 MachOBindEntry::Kind::Lazy);
1947}
1948
1949iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1950 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1951 MachOBindEntry::Kind::Weak);
1952}
1953
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001954MachOObjectFile::load_command_iterator
1955MachOObjectFile::begin_load_commands() const {
1956 return LoadCommands.begin();
1957}
1958
1959MachOObjectFile::load_command_iterator
1960MachOObjectFile::end_load_commands() const {
1961 return LoadCommands.end();
1962}
1963
1964iterator_range<MachOObjectFile::load_command_iterator>
1965MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00001966 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001967}
1968
Rafael Espindola56f976f2013-04-18 18:08:55 +00001969StringRef
1970MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1971 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1972 return parseSegmentOrSectionName(Raw.data());
1973}
1974
1975ArrayRef<char>
1976MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001977 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001978 const section_base *Base =
1979 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001980 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001981}
1982
1983ArrayRef<char>
1984MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001985 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001986 const section_base *Base =
1987 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001988 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001989}
1990
1991bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001992MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001993 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001994 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001995 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001996 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001997}
1998
Eric Christopher1d62c252013-07-22 22:25:07 +00001999unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002000 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002001 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002002 return RE.r_word1 & 0xffffff;
2003 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002004}
2005
Eric Christopher1d62c252013-07-22 22:25:07 +00002006bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002007 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002008 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002009 return (RE.r_word1 >> 27) & 1;
2010 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002011}
2012
Eric Christopher1d62c252013-07-22 22:25:07 +00002013bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002014 const MachO::any_relocation_info &RE) const {
2015 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002016}
2017
Eric Christopher1d62c252013-07-22 22:25:07 +00002018uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002019 const MachO::any_relocation_info &RE) const {
2020 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002021}
2022
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002023uint32_t MachOObjectFile::getScatteredRelocationType(
2024 const MachO::any_relocation_info &RE) const {
2025 return (RE.r_word0 >> 24) & 0xf;
2026}
2027
Eric Christopher1d62c252013-07-22 22:25:07 +00002028unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002029 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002030 if (isRelocationScattered(RE))
2031 return getScatteredRelocationAddress(RE);
2032 return getPlainRelocationAddress(RE);
2033}
2034
Charles Davis8bdfafd2013-09-01 04:28:48 +00002035unsigned MachOObjectFile::getAnyRelocationPCRel(
2036 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002037 if (isRelocationScattered(RE))
2038 return getScatteredRelocationPCRel(this, RE);
2039 return getPlainRelocationPCRel(this, RE);
2040}
2041
Eric Christopher1d62c252013-07-22 22:25:07 +00002042unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002043 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002044 if (isRelocationScattered(RE))
2045 return getScatteredRelocationLength(RE);
2046 return getPlainRelocationLength(this, RE);
2047}
2048
2049unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002050MachOObjectFile::getAnyRelocationType(
2051 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002052 if (isRelocationScattered(RE))
2053 return getScatteredRelocationType(RE);
2054 return getPlainRelocationType(this, RE);
2055}
2056
Rafael Espindola52501032013-04-30 15:40:54 +00002057SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002058MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002059 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002060 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002061 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002062 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2063 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2064 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002065 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002066 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002067 return SectionRef(DRI, this);
2068}
2069
Charles Davis8bdfafd2013-09-01 04:28:48 +00002070MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002071 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002072 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002073}
2074
Charles Davis8bdfafd2013-09-01 04:28:48 +00002075MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002076 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002077 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002078}
2079
Charles Davis8bdfafd2013-09-01 04:28:48 +00002080MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002081 unsigned Index) const {
2082 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002083 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002084}
2085
Charles Davis8bdfafd2013-09-01 04:28:48 +00002086MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2087 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002088 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002089 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002090}
2091
Charles Davis8bdfafd2013-09-01 04:28:48 +00002092MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002093MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002094 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002095 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002096}
2097
Charles Davis8bdfafd2013-09-01 04:28:48 +00002098MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002099MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002100 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002101 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002102}
2103
Charles Davis8bdfafd2013-09-01 04:28:48 +00002104MachO::linkedit_data_command
2105MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2106 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002107}
2108
Charles Davis8bdfafd2013-09-01 04:28:48 +00002109MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002110MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002111 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002112}
2113
Charles Davis8bdfafd2013-09-01 04:28:48 +00002114MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002115MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002116 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002117}
2118
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002119MachO::linker_option_command
2120MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2121 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002122}
2123
Jim Grosbach448334a2014-03-18 22:09:05 +00002124MachO::version_min_command
2125MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2126 return getStruct<MachO::version_min_command>(this, L.Ptr);
2127}
2128
Tim Northover8f9590b2014-06-30 14:40:57 +00002129MachO::dylib_command
2130MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2131 return getStruct<MachO::dylib_command>(this, L.Ptr);
2132}
2133
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002134MachO::dyld_info_command
2135MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2136 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2137}
2138
2139MachO::dylinker_command
2140MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2141 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2142}
2143
2144MachO::uuid_command
2145MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2146 return getStruct<MachO::uuid_command>(this, L.Ptr);
2147}
2148
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002149MachO::rpath_command
2150MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2151 return getStruct<MachO::rpath_command>(this, L.Ptr);
2152}
2153
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002154MachO::source_version_command
2155MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2156 return getStruct<MachO::source_version_command>(this, L.Ptr);
2157}
2158
2159MachO::entry_point_command
2160MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2161 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2162}
2163
Kevin Enderby0804f4672014-12-16 23:25:52 +00002164MachO::encryption_info_command
2165MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2166 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2167}
2168
Kevin Enderby57538292014-12-17 01:01:30 +00002169MachO::encryption_info_command_64
2170MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2171 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2172}
2173
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002174MachO::sub_framework_command
2175MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2176 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2177}
Tim Northover8f9590b2014-06-30 14:40:57 +00002178
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002179MachO::sub_umbrella_command
2180MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2181 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2182}
2183
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002184MachO::sub_library_command
2185MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2186 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2187}
2188
Kevin Enderby186eac32014-12-19 21:06:24 +00002189MachO::sub_client_command
2190MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2191 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2192}
2193
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002194MachO::routines_command
2195MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2196 return getStruct<MachO::routines_command>(this, L.Ptr);
2197}
2198
2199MachO::routines_command_64
2200MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2201 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2202}
2203
Kevin Enderby48ef5342014-12-23 22:56:39 +00002204MachO::thread_command
2205MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2206 return getStruct<MachO::thread_command>(this, L.Ptr);
2207}
2208
Charles Davis8bdfafd2013-09-01 04:28:48 +00002209MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002210MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002211 DataRefImpl Sec;
2212 Sec.d.a = Rel.d.a;
2213 uint32_t Offset;
2214 if (is64Bit()) {
2215 MachO::section_64 Sect = getSection64(Sec);
2216 Offset = Sect.reloff;
2217 } else {
2218 MachO::section Sect = getSection(Sec);
2219 Offset = Sect.reloff;
2220 }
2221
2222 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2223 getPtr(this, Offset)) + Rel.d.b;
2224 return getStruct<MachO::any_relocation_info>(
2225 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002226}
2227
Charles Davis8bdfafd2013-09-01 04:28:48 +00002228MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002229MachOObjectFile::getDice(DataRefImpl Rel) const {
2230 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002231 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002232}
2233
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002234const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002235 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002236}
2237
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002238const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2239 assert(is64Bit());
2240 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002241}
2242
Charles Davis8bdfafd2013-09-01 04:28:48 +00002243uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2244 const MachO::dysymtab_command &DLC,
2245 unsigned Index) const {
2246 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2247 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002248}
2249
Charles Davis8bdfafd2013-09-01 04:28:48 +00002250MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002251MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2252 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002253 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2254 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002255}
2256
Charles Davis8bdfafd2013-09-01 04:28:48 +00002257MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002258 if (SymtabLoadCmd)
2259 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2260
2261 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2262 MachO::symtab_command Cmd;
2263 Cmd.cmd = MachO::LC_SYMTAB;
2264 Cmd.cmdsize = sizeof(MachO::symtab_command);
2265 Cmd.symoff = 0;
2266 Cmd.nsyms = 0;
2267 Cmd.stroff = 0;
2268 Cmd.strsize = 0;
2269 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002270}
2271
Charles Davis8bdfafd2013-09-01 04:28:48 +00002272MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002273 if (DysymtabLoadCmd)
2274 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2275
2276 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2277 MachO::dysymtab_command Cmd;
2278 Cmd.cmd = MachO::LC_DYSYMTAB;
2279 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2280 Cmd.ilocalsym = 0;
2281 Cmd.nlocalsym = 0;
2282 Cmd.iextdefsym = 0;
2283 Cmd.nextdefsym = 0;
2284 Cmd.iundefsym = 0;
2285 Cmd.nundefsym = 0;
2286 Cmd.tocoff = 0;
2287 Cmd.ntoc = 0;
2288 Cmd.modtaboff = 0;
2289 Cmd.nmodtab = 0;
2290 Cmd.extrefsymoff = 0;
2291 Cmd.nextrefsyms = 0;
2292 Cmd.indirectsymoff = 0;
2293 Cmd.nindirectsyms = 0;
2294 Cmd.extreloff = 0;
2295 Cmd.nextrel = 0;
2296 Cmd.locreloff = 0;
2297 Cmd.nlocrel = 0;
2298 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002299}
2300
Charles Davis8bdfafd2013-09-01 04:28:48 +00002301MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002302MachOObjectFile::getDataInCodeLoadCommand() const {
2303 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002304 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002305
2306 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002307 MachO::linkedit_data_command Cmd;
2308 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2309 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2310 Cmd.dataoff = 0;
2311 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002312 return Cmd;
2313}
2314
Kevin Enderby9a509442015-01-27 21:28:24 +00002315MachO::linkedit_data_command
2316MachOObjectFile::getLinkOptHintsLoadCommand() const {
2317 if (LinkOptHintsLoadCmd)
2318 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2319
2320 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2321 // fields.
2322 MachO::linkedit_data_command Cmd;
2323 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2324 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2325 Cmd.dataoff = 0;
2326 Cmd.datasize = 0;
2327 return Cmd;
2328}
2329
Nick Kledzikd04bc352014-08-30 00:20:14 +00002330ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002331 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002332 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002333
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002334 MachO::dyld_info_command DyldInfo =
2335 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2336 const uint8_t *Ptr =
2337 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00002338 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002339}
2340
2341ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002342 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002343 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002344
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002345 MachO::dyld_info_command DyldInfo =
2346 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2347 const uint8_t *Ptr =
2348 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002349 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002350}
2351
2352ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002353 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002354 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002355
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002356 MachO::dyld_info_command DyldInfo =
2357 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2358 const uint8_t *Ptr =
2359 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002360 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002361}
2362
2363ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002364 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002365 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002366
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002367 MachO::dyld_info_command DyldInfo =
2368 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2369 const uint8_t *Ptr =
2370 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002371 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002372}
2373
2374ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002375 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002376 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002377
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002378 MachO::dyld_info_command DyldInfo =
2379 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2380 const uint8_t *Ptr =
2381 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00002382 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002383}
2384
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002385ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2386 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002387 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00002388 // Returning a pointer is fine as uuid doesn't need endian swapping.
2389 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00002390 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002391}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002392
Rafael Espindola6e040c02013-04-26 20:07:33 +00002393StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002394 MachO::symtab_command S = getSymtabLoadCommand();
2395 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002396}
2397
Rafael Espindola56f976f2013-04-18 18:08:55 +00002398bool MachOObjectFile::is64Bit() const {
2399 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002400 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002401}
2402
2403void MachOObjectFile::ReadULEB128s(uint64_t Index,
2404 SmallVectorImpl<uint64_t> &Out) const {
2405 DataExtractor extractor(ObjectFile::getData(), true, 0);
2406
2407 uint32_t offset = Index;
2408 uint64_t data = 0;
2409 while (uint64_t delta = extractor.getULEB128(&offset)) {
2410 data += delta;
2411 Out.push_back(data);
2412 }
2413}
2414
Rafael Espindolac66d7612014-08-17 19:09:37 +00002415bool MachOObjectFile::isRelocatableObject() const {
2416 return getHeader().filetype == MachO::MH_OBJECT;
2417}
2418
Lang Hamesff044b12016-03-25 23:11:52 +00002419Expected<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002420ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2421 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00002422 if (Magic == "\xFE\xED\xFA\xCE")
Lang Hamesff044b12016-03-25 23:11:52 +00002423 return MachOObjectFile::create(Buffer, false, false);
David Blaikieb805f732016-03-28 17:45:48 +00002424 if (Magic == "\xCE\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002425 return MachOObjectFile::create(Buffer, true, false);
David Blaikieb805f732016-03-28 17:45:48 +00002426 if (Magic == "\xFE\xED\xFA\xCF")
Lang Hamesff044b12016-03-25 23:11:52 +00002427 return MachOObjectFile::create(Buffer, false, true);
David Blaikieb805f732016-03-28 17:45:48 +00002428 if (Magic == "\xCF\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002429 return MachOObjectFile::create(Buffer, true, true);
Lang Hamesff044b12016-03-25 23:11:52 +00002430 return malformedError(Buffer.getBufferIdentifier(),
2431 "Unrecognized MachO magic number");
Rafael Espindola56f976f2013-04-18 18:08:55 +00002432}