blob: f961f0bd050fc6b1f7585ed884300152e6b21de5 [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 +000041static Error
Kevin Enderby89134962016-05-05 23:41:05 +000042malformedError(const MachOObjectFile &Obj, Twine Msg) {
43 std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")";
Justin Bogner2a42da92016-05-05 23:59:57 +000044 return make_error<GenericBinaryError>(Obj.getFileName(), std::move(StringMsg),
Kevin Enderby89134962016-05-05 23:41:05 +000045 object_error::parse_failed);
Lang Hames9e964f32016-03-25 17:25:34 +000046}
47
Alexey Samsonov9f336632015-06-04 19:45:22 +000048// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000049template <typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000050static T getStruct(const MachOObjectFile *O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000051 // Don't read before the beginning or past the end of the file
52 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
53 report_fatal_error("Malformed MachO file.");
54
Rafael Espindola3cdeb172013-04-19 13:45:05 +000055 T Cmd;
56 memcpy(&Cmd, P, sizeof(T));
57 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000058 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000059 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000060}
61
Alexey Samsonov9f336632015-06-04 19:45:22 +000062template <typename T>
Lang Hames9e964f32016-03-25 17:25:34 +000063static Expected<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000064 // Don't read before the beginning or past the end of the file
65 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
Lang Hames9e964f32016-03-25 17:25:34 +000066 return malformedError(*O, "Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000067
68 T Cmd;
69 memcpy(&Cmd, P, sizeof(T));
70 if (O->isLittleEndian() != sys::IsLittleEndianHost)
71 MachO::swapStruct(Cmd);
72 return Cmd;
73}
74
Rafael Espindola6e040c02013-04-26 20:07:33 +000075static const char *
76getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
77 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000078 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
79
80 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000081 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
82 sizeof(MachO::segment_command);
83 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
84 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000085
86 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000087 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000088}
89
Rafael Espindola56f976f2013-04-18 18:08:55 +000090static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
91 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +000092}
93
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000094static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +000095getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +000096 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000097 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +000098}
99
Rafael Espindola56f976f2013-04-18 18:08:55 +0000100static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000101 if (P[15] == 0)
102 // Null terminated.
103 return P;
104 // Not null terminated, so this is a 16 char string.
105 return StringRef(P, 16);
106}
107
Rafael Espindola56f976f2013-04-18 18:08:55 +0000108// Helper to advance a section or symbol iterator multiple increments at a time.
109template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000110static void advance(T &it, size_t Val) {
111 while (Val--)
112 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000113}
114
115static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000116 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000117}
118
Charles Davis8bdfafd2013-09-01 04:28:48 +0000119static uint32_t
120getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
121 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000122}
123
124static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000125getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
126 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000127}
128
129static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000130 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000131 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000132 return (RE.r_word1 >> 24) & 1;
133 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000134}
135
136static bool
137getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000138 const MachO::any_relocation_info &RE) {
139 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000140}
141
142static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000143 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000144 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000145 return (RE.r_word1 >> 25) & 3;
146 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000147}
148
149static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000150getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
151 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152}
153
154static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000155 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000156 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000157 return RE.r_word1 >> 28;
158 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000159}
160
Rafael Espindola56f976f2013-04-18 18:08:55 +0000161static uint32_t getSectionFlags(const MachOObjectFile *O,
162 DataRefImpl Sec) {
163 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000164 MachO::section_64 Sect = O->getSection64(Sec);
165 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000166 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000167 MachO::section Sect = O->getSection(Sec);
168 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000169}
170
Lang Hames9e964f32016-03-25 17:25:34 +0000171static Expected<MachOObjectFile::LoadCommandInfo>
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000172getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr,
173 uint32_t LoadCommandIndex) {
Lang Hames9e964f32016-03-25 17:25:34 +0000174 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
175 if (CmdOrErr->cmdsize < 8)
Kevin Enderby89134962016-05-05 23:41:05 +0000176 return malformedError(*Obj, "load command " + Twine(LoadCommandIndex) +
177 " with size less than 8 bytes");
Lang Hames9e964f32016-03-25 17:25:34 +0000178 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
179 } else
180 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000181}
182
Lang Hames9e964f32016-03-25 17:25:34 +0000183static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000184getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
185 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
186 : sizeof(MachO::mach_header);
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000187 if (sizeof(MachOObjectFile::LoadCommandInfo) > Obj->getHeader().sizeofcmds)
Kevin Enderby89134962016-05-05 23:41:05 +0000188 return malformedError(*Obj, "load command 0 extends past the end all load "
189 "commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000190 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000191}
192
Lang Hames9e964f32016-03-25 17:25:34 +0000193static Expected<MachOObjectFile::LoadCommandInfo>
Kevin Enderby368e7142016-05-03 17:16:08 +0000194getNextLoadCommandInfo(const MachOObjectFile *Obj, uint32_t LoadCommandIndex,
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000195 const MachOObjectFile::LoadCommandInfo &L) {
Kevin Enderby368e7142016-05-03 17:16:08 +0000196 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
197 : sizeof(MachO::mach_header);
198 if (L.Ptr + L.C.cmdsize + sizeof(MachOObjectFile::LoadCommandInfo) >
199 Obj->getData().data() + HeaderSize + Obj->getHeader().sizeofcmds)
Kevin Enderby89134962016-05-05 23:41:05 +0000200 return malformedError(*Obj, "load command " + Twine(LoadCommandIndex + 1) +
201 " extends past the end all load commands in the file");
Kevin Enderbya8e3ab02016-05-03 23:13:50 +0000202 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000203}
204
Alexey Samsonov9f336632015-06-04 19:45:22 +0000205template <typename T>
206static void parseHeader(const MachOObjectFile *Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000207 Error &Err) {
Kevin Enderby87025742016-04-13 21:17:58 +0000208 if (sizeof(T) > Obj->getData().size()) {
Kevin Enderby89134962016-05-05 23:41:05 +0000209 Err = malformedError(*Obj, "the mach header extends past the end of the "
210 "file");
Kevin Enderby87025742016-04-13 21:17:58 +0000211 return;
212 }
Lang Hames9e964f32016-03-25 17:25:34 +0000213 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
214 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000215 else
Lang Hames9e964f32016-03-25 17:25:34 +0000216 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000217}
218
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000219// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
220// sections to \param Sections, and optionally sets
221// \param IsPageZeroSegment to true.
222template <typename SegmentCmd>
Lang Hames9e964f32016-03-25 17:25:34 +0000223static Error parseSegmentLoadCommand(
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000224 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000225 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
226 uint32_t LoadCommandIndex, const char *CmdName) {
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000227 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
228 if (Load.C.cmdsize < SegmentLoadSize)
Kevin Enderby89134962016-05-05 23:41:05 +0000229 return malformedError(*Obj, "load command " + Twine(LoadCommandIndex) +
230 " " + CmdName + " cmdsize too small");
Lang Hames9e964f32016-03-25 17:25:34 +0000231 if (auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr)) {
232 SegmentCmd S = SegOrErr.get();
233 const unsigned SectionSize =
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000234 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
Lang Hames9e964f32016-03-25 17:25:34 +0000235 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
236 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
Kevin Enderby89134962016-05-05 23:41:05 +0000237 return malformedError(*Obj, "load command " + Twine(LoadCommandIndex) +
238 " inconsistent cmdsize in " + CmdName +
239 " for the number of sections");
Lang Hames9e964f32016-03-25 17:25:34 +0000240 for (unsigned J = 0; J < S.nsects; ++J) {
241 const char *Sec = getSectionPtr(Obj, Load, J);
242 Sections.push_back(Sec);
243 }
244 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
245 } else
246 return SegOrErr.takeError();
247
248 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000249}
250
Lang Hames82627642016-03-25 21:59:14 +0000251Expected<std::unique_ptr<MachOObjectFile>>
252MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
253 bool Is64Bits) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000254 Error Err;
Lang Hames82627642016-03-25 21:59:14 +0000255 std::unique_ptr<MachOObjectFile> Obj(
256 new MachOObjectFile(std::move(Object), IsLittleEndian,
257 Is64Bits, Err));
258 if (Err)
259 return std::move(Err);
260 return std::move(Obj);
261}
262
Rafael Espindola48af1c22014-08-19 18:44:46 +0000263MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Lang Hames9e964f32016-03-25 17:25:34 +0000264 bool Is64bits, Error &Err)
Rafael Espindola48af1c22014-08-19 18:44:46 +0000265 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000266 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000267 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
268 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
269 HasPageZeroSegment(false) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000270 ErrorAsOutParameter ErrAsOutParam(Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000271 uint64_t BigSize;
Kevin Enderby87025742016-04-13 21:17:58 +0000272 if (is64Bit()) {
Lang Hames9e964f32016-03-25 17:25:34 +0000273 parseHeader(this, Header64, Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000274 BigSize = sizeof(MachO::mach_header_64);
Kevin Enderby87025742016-04-13 21:17:58 +0000275 } else {
Lang Hames9e964f32016-03-25 17:25:34 +0000276 parseHeader(this, Header, Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000277 BigSize = sizeof(MachO::mach_header);
Kevin Enderby87025742016-04-13 21:17:58 +0000278 }
Lang Hames9e964f32016-03-25 17:25:34 +0000279 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +0000280 return;
Kevin Enderby5e55d172016-04-21 20:29:49 +0000281 BigSize += getHeader().sizeofcmds;
282 if (getData().data() + BigSize > getData().end()) {
Kevin Enderby89134962016-05-05 23:41:05 +0000283 Err = malformedError(*this, "load commands extend past the end of the file");
Kevin Enderby87025742016-04-13 21:17:58 +0000284 return;
285 }
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000286
287 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000288 if (LoadCommandCount == 0)
289 return;
290
Lang Hames9e964f32016-03-25 17:25:34 +0000291 LoadCommandInfo Load;
292 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
293 Load = *LoadOrErr;
294 else {
295 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000296 return;
297 }
Lang Hames9e964f32016-03-25 17:25:34 +0000298
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000299 for (unsigned I = 0; I < LoadCommandCount; ++I) {
300 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000301 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000302 // Multiple symbol tables
303 if (SymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000304 Err = malformedError(*this, "Multiple symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000305 return;
306 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000307 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000308 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000309 // Multiple dynamic symbol tables
310 if (DysymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000311 Err = malformedError(*this, "Multiple dynamic symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000312 return;
313 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000314 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000315 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000316 // Multiple data in code tables
317 if (DataInCodeLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000318 Err = malformedError(*this, "Multiple data-in-code tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000319 return;
320 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000321 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000322 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
323 // Multiple linker optimization hint tables
324 if (LinkOptHintsLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000325 Err = malformedError(*this, "Multiple linker optimization hint tables");
Kevin Enderby9a509442015-01-27 21:28:24 +0000326 return;
327 }
328 LinkOptHintsLoadCmd = Load.Ptr;
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +0000329 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Nick Kledzikd04bc352014-08-30 00:20:14 +0000330 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000331 // Multiple dyldinfo load commands
332 if (DyldInfoLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000333 Err = malformedError(*this, "Multiple dyldinfo load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000334 return;
335 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000336 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000337 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000338 // Multiple UUID load commands
339 if (UuidLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000340 Err = malformedError(*this, "Multiple UUID load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000341 return;
342 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000343 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000344 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Lang Hames9e964f32016-03-25 17:25:34 +0000345 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000346 this, Load, Sections, HasPageZeroSegment, I,
347 "LC_SEGMENT_64")))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000348 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000349 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Lang Hames9e964f32016-03-25 17:25:34 +0000350 if ((Err = parseSegmentLoadCommand<MachO::segment_command>(
Kevin Enderbyb34e3a12016-05-05 17:43:35 +0000351 this, Load, Sections, HasPageZeroSegment, I, "LC_SEGMENT")))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000352 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000353 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
354 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
355 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
356 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
357 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
358 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000359 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000360 if (I < LoadCommandCount - 1) {
Kevin Enderby368e7142016-05-03 17:16:08 +0000361 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load))
Lang Hames9e964f32016-03-25 17:25:34 +0000362 Load = *LoadOrErr;
363 else {
364 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000365 return;
366 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000367 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000368 }
Kevin Enderby1829c682016-01-22 22:49:55 +0000369 if (!SymtabLoadCmd) {
370 if (DysymtabLoadCmd) {
Kevin Enderby89134962016-05-05 23:41:05 +0000371 Err = malformedError(*this, "contains LC_DYSYMTAB load command without a "
372 "LC_SYMTAB load command");
Kevin Enderby1829c682016-01-22 22:49:55 +0000373 return;
374 }
375 } else if (DysymtabLoadCmd) {
376 MachO::symtab_command Symtab =
377 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
378 MachO::dysymtab_command Dysymtab =
379 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
380 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderby89134962016-05-05 23:41:05 +0000381 Err = malformedError(*this, "ilocalsym in LC_DYSYMTAB load command "
382 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000383 return;
384 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000385 uint64_t BigSize = Dysymtab.ilocalsym;
386 BigSize += Dysymtab.nlocalsym;
387 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderby89134962016-05-05 23:41:05 +0000388 Err = malformedError(*this, "ilocalsym plus nlocalsym in LC_DYSYMTAB load "
389 "command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000390 return;
391 }
392 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Kevin Enderby89134962016-05-05 23:41:05 +0000393 Err = malformedError(*this, "nextdefsym in LC_DYSYMTAB load command "
394 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000395 return;
396 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000397 BigSize = Dysymtab.iextdefsym;
398 BigSize += Dysymtab.nextdefsym;
399 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderby89134962016-05-05 23:41:05 +0000400 Err = malformedError(*this, "iextdefsym plus nextdefsym in LC_DYSYMTAB "
401 "load command extends past the end of the symbol "
402 "table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000403 return;
404 }
405 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Kevin Enderby89134962016-05-05 23:41:05 +0000406 Err = malformedError(*this, "nundefsym in LC_DYSYMTAB load command "
407 "extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000408 return;
409 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000410 BigSize = Dysymtab.iundefsym;
411 BigSize += Dysymtab.nundefsym;
412 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Kevin Enderby89134962016-05-05 23:41:05 +0000413 Err = malformedError(*this, "iundefsym plus nundefsym in LC_DYSYMTAB load "
414 " command extends past the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000415 return;
416 }
417 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000418 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +0000419
420 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000421}
422
Rafael Espindola5e812af2014-01-30 02:49:50 +0000423void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000424 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000425 sizeof(MachO::nlist_64) :
426 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000427 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000428}
429
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000430Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000431 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000432 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000433 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000434 if (Start < getData().begin() || Start >= getData().end()) {
Kevin Enderby89134962016-05-05 23:41:05 +0000435 return malformedError(*this, "bad string index: " + Twine(Entry.n_strx) +
436 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000437 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000438 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000439}
440
Rafael Espindola0e77a942014-12-10 20:46:55 +0000441unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
442 DataRefImpl DRI = Sec.getRawDataRefImpl();
443 uint32_t Flags = getSectionFlags(this, DRI);
444 return Flags & MachO::SECTION_TYPE;
445}
446
Rafael Espindola59128922015-06-24 18:14:41 +0000447uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
448 if (is64Bit()) {
449 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
450 return Entry.n_value;
451 }
452 MachO::nlist Entry = getSymbolTableEntry(Sym);
453 return Entry.n_value;
454}
455
Kevin Enderby980b2582014-06-05 21:21:57 +0000456// getIndirectName() returns the name of the alias'ed symbol who's string table
457// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000458std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
459 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000460 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000461 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
462 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
463 return object_error::parse_failed;
464 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000465 if (NValue >= StringTable.size())
466 return object_error::parse_failed;
467 const char *Start = &StringTable.data()[NValue];
468 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000469 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000470}
471
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +0000472uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +0000473 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +0000474}
475
Rafael Espindolaed067c42015-07-03 18:19:00 +0000476ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
477 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000478}
479
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000480uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000481 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000482 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000483 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000484 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000485 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000486 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000487}
488
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000489uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000490 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000491}
492
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000493Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000494MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000495 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000496 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000497
Rafael Espindola56f976f2013-04-18 18:08:55 +0000498 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000499 if (n_type & MachO::N_STAB)
500 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000501
Charles Davis74ec8b02013-08-27 05:00:13 +0000502 switch (n_type & MachO::N_TYPE) {
503 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000504 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +0000505 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000506 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000507 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000508 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000509 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +0000510 if (Sec->isData() || Sec->isBSS())
511 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000512 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000513 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000514 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000515}
516
Rafael Espindola20122a42014-01-31 20:57:12 +0000517uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000518 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000519
Charles Davis8bdfafd2013-09-01 04:28:48 +0000520 uint8_t MachOType = Entry.n_type;
521 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000522
Rafael Espindola20122a42014-01-31 20:57:12 +0000523 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000524
Tim Northovereaef0742014-05-30 13:22:59 +0000525 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
526 Result |= SymbolRef::SF_Indirect;
527
Rafael Espindolaa1356322013-11-02 05:03:24 +0000528 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000529 Result |= SymbolRef::SF_FormatSpecific;
530
Charles Davis74ec8b02013-08-27 05:00:13 +0000531 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000532 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000533 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000534 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000535 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +0000536 else
537 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000538 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000539
540 if (!(MachOType & MachO::N_PEXT))
541 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000542 }
543
Charles Davis74ec8b02013-08-27 05:00:13 +0000544 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000545 Result |= SymbolRef::SF_Weak;
546
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000547 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
548 Result |= SymbolRef::SF_Thumb;
549
Charles Davis74ec8b02013-08-27 05:00:13 +0000550 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000551 Result |= SymbolRef::SF_Absolute;
552
Rafael Espindola20122a42014-01-31 20:57:12 +0000553 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000554}
555
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000556Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +0000557MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000558 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000559 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000560
Rafael Espindola8bab8892015-08-07 23:27:14 +0000561 if (index == 0)
562 return section_end();
563 DataRefImpl DRI;
564 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000565 if (DRI.d.a >= Sections.size()){
Kevin Enderby89134962016-05-05 23:41:05 +0000566 return malformedError(*this, "bad section index: " + Twine((int)index) +
567 " for symbol at index " + Twine(getSymbolIndex(Symb)));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000568 }
Rafael Espindola8bab8892015-08-07 23:27:14 +0000569 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000570}
571
Rafael Espindola6bf32212015-06-24 19:57:32 +0000572unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
573 MachO::nlist_base Entry =
574 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
575 return Entry.n_sect - 1;
576}
577
Rafael Espindola5e812af2014-01-30 02:49:50 +0000578void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000579 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000580}
581
Rafael Espindola3acea392014-06-12 21:46:39 +0000582std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
583 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000584 ArrayRef<char> Raw = getSectionRawName(Sec);
585 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000586 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000587}
588
Rafael Espindola80291272014-10-08 15:28:58 +0000589uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
590 if (is64Bit())
591 return getSection64(Sec).addr;
592 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000593}
594
Rafael Espindola80291272014-10-08 15:28:58 +0000595uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +0000596 // In the case if a malformed Mach-O file where the section offset is past
597 // the end of the file or some part of the section size is past the end of
598 // the file return a size of zero or a size that covers the rest of the file
599 // but does not extend past the end of the file.
600 uint32_t SectOffset, SectType;
601 uint64_t SectSize;
602
603 if (is64Bit()) {
604 MachO::section_64 Sect = getSection64(Sec);
605 SectOffset = Sect.offset;
606 SectSize = Sect.size;
607 SectType = Sect.flags & MachO::SECTION_TYPE;
608 } else {
609 MachO::section Sect = getSection(Sec);
610 SectOffset = Sect.offset;
611 SectSize = Sect.size;
612 SectType = Sect.flags & MachO::SECTION_TYPE;
613 }
614 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
615 return SectSize;
616 uint64_t FileSize = getData().size();
617 if (SectOffset > FileSize)
618 return 0;
619 if (FileSize - SectOffset < SectSize)
620 return FileSize - SectOffset;
621 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000622}
623
Rafael Espindola3acea392014-06-12 21:46:39 +0000624std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
625 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000626 uint32_t Offset;
627 uint64_t Size;
628
629 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000630 MachO::section_64 Sect = getSection64(Sec);
631 Offset = Sect.offset;
632 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000633 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000634 MachO::section Sect = getSection(Sec);
635 Offset = Sect.offset;
636 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000637 }
638
639 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000640 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000641}
642
Rafael Espindola80291272014-10-08 15:28:58 +0000643uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000644 uint32_t Align;
645 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000646 MachO::section_64 Sect = getSection64(Sec);
647 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000648 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000649 MachO::section Sect = getSection(Sec);
650 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000651 }
652
Rafael Espindola80291272014-10-08 15:28:58 +0000653 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000654}
655
Rafael Espindola80291272014-10-08 15:28:58 +0000656bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000657 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000658 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000659}
660
Rafael Espindola80291272014-10-08 15:28:58 +0000661bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000662 uint32_t Flags = getSectionFlags(this, Sec);
663 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000664 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
665 !(SectionType == MachO::S_ZEROFILL ||
666 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000667}
668
Rafael Espindola80291272014-10-08 15:28:58 +0000669bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000670 uint32_t Flags = getSectionFlags(this, Sec);
671 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000672 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
673 (SectionType == MachO::S_ZEROFILL ||
674 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000675}
676
Rafael Espindola6bf32212015-06-24 19:57:32 +0000677unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
678 return Sec.getRawDataRefImpl().d.a;
679}
680
Rafael Espindola80291272014-10-08 15:28:58 +0000681bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000682 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000683 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000684}
685
Steven Wuf2fe0142016-02-29 19:40:10 +0000686bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
687 StringRef SegmentName = getSectionFinalSegmentName(Sec);
688 StringRef SectName;
689 if (!getSectionName(Sec, SectName))
690 return (SegmentName == "__LLVM" && SectName == "__bitcode");
691 return false;
692}
693
Rui Ueyamabc654b12013-09-27 21:47:05 +0000694relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000695 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000696 Ret.d.a = Sec.d.a;
697 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000698 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000699}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000700
Rafael Espindola56f976f2013-04-18 18:08:55 +0000701relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000702MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000703 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000704 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000705 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000706 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000707 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000708 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000709 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000710 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000711
Rafael Espindola56f976f2013-04-18 18:08:55 +0000712 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000713 Ret.d.a = Sec.d.a;
714 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000715 return relocation_iterator(RelocationRef(Ret, this));
716}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000717
Rafael Espindola5e812af2014-01-30 02:49:50 +0000718void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000719 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000720}
Owen Anderson171f4852011-10-24 23:20:07 +0000721
Rafael Espindola96d071c2015-06-29 23:29:12 +0000722uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000723 assert(getHeader().filetype == MachO::MH_OBJECT &&
724 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000725 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000726 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +0000727}
728
Rafael Espindola806f0062013-06-05 01:33:53 +0000729symbol_iterator
730MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000731 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000732 if (isRelocationScattered(RE))
733 return symbol_end();
734
Rafael Espindola56f976f2013-04-18 18:08:55 +0000735 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
736 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000737 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000738 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000739
Charles Davis8bdfafd2013-09-01 04:28:48 +0000740 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000741 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000742 sizeof(MachO::nlist_64) :
743 sizeof(MachO::nlist);
744 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000745 DataRefImpl Sym;
746 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000747 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000748}
749
Keno Fischerc780e8e2015-05-21 21:24:32 +0000750section_iterator
751MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
752 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
753}
754
Rafael Espindola99c041b2015-06-30 01:53:01 +0000755uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000756 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +0000757 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000758}
759
Rafael Espindola41bb4322015-06-30 04:08:37 +0000760void MachOObjectFile::getRelocationTypeName(
761 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000762 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +0000763 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000764
765 unsigned Arch = this->getArch();
766
767 switch (Arch) {
768 case Triple::x86: {
769 static const char *const Table[] = {
770 "GENERIC_RELOC_VANILLA",
771 "GENERIC_RELOC_PAIR",
772 "GENERIC_RELOC_SECTDIFF",
773 "GENERIC_RELOC_PB_LA_PTR",
774 "GENERIC_RELOC_LOCAL_SECTDIFF",
775 "GENERIC_RELOC_TLV" };
776
Eric Christopher13250cb2013-12-06 02:33:38 +0000777 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000778 res = "Unknown";
779 else
780 res = Table[RType];
781 break;
782 }
783 case Triple::x86_64: {
784 static const char *const Table[] = {
785 "X86_64_RELOC_UNSIGNED",
786 "X86_64_RELOC_SIGNED",
787 "X86_64_RELOC_BRANCH",
788 "X86_64_RELOC_GOT_LOAD",
789 "X86_64_RELOC_GOT",
790 "X86_64_RELOC_SUBTRACTOR",
791 "X86_64_RELOC_SIGNED_1",
792 "X86_64_RELOC_SIGNED_2",
793 "X86_64_RELOC_SIGNED_4",
794 "X86_64_RELOC_TLV" };
795
796 if (RType > 9)
797 res = "Unknown";
798 else
799 res = Table[RType];
800 break;
801 }
802 case Triple::arm: {
803 static const char *const Table[] = {
804 "ARM_RELOC_VANILLA",
805 "ARM_RELOC_PAIR",
806 "ARM_RELOC_SECTDIFF",
807 "ARM_RELOC_LOCAL_SECTDIFF",
808 "ARM_RELOC_PB_LA_PTR",
809 "ARM_RELOC_BR24",
810 "ARM_THUMB_RELOC_BR22",
811 "ARM_THUMB_32BIT_BRANCH",
812 "ARM_RELOC_HALF",
813 "ARM_RELOC_HALF_SECTDIFF" };
814
815 if (RType > 9)
816 res = "Unknown";
817 else
818 res = Table[RType];
819 break;
820 }
Tim Northover00ed9962014-03-29 10:18:08 +0000821 case Triple::aarch64: {
822 static const char *const Table[] = {
823 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
824 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
825 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
826 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
827 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
828 "ARM64_RELOC_ADDEND"
829 };
830
831 if (RType >= array_lengthof(Table))
832 res = "Unknown";
833 else
834 res = Table[RType];
835 break;
836 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000837 case Triple::ppc: {
838 static const char *const Table[] = {
839 "PPC_RELOC_VANILLA",
840 "PPC_RELOC_PAIR",
841 "PPC_RELOC_BR14",
842 "PPC_RELOC_BR24",
843 "PPC_RELOC_HI16",
844 "PPC_RELOC_LO16",
845 "PPC_RELOC_HA16",
846 "PPC_RELOC_LO14",
847 "PPC_RELOC_SECTDIFF",
848 "PPC_RELOC_PB_LA_PTR",
849 "PPC_RELOC_HI16_SECTDIFF",
850 "PPC_RELOC_LO16_SECTDIFF",
851 "PPC_RELOC_HA16_SECTDIFF",
852 "PPC_RELOC_JBSR",
853 "PPC_RELOC_LO14_SECTDIFF",
854 "PPC_RELOC_LOCAL_SECTDIFF" };
855
Eric Christopher13250cb2013-12-06 02:33:38 +0000856 if (RType > 15)
857 res = "Unknown";
858 else
859 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000860 break;
861 }
862 case Triple::UnknownArch:
863 res = "Unknown";
864 break;
865 }
866 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +0000867}
868
Keno Fischer281b6942015-05-30 19:44:53 +0000869uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
870 MachO::any_relocation_info RE = getRelocation(Rel);
871 return getAnyRelocationLength(RE);
872}
873
Kevin Enderby980b2582014-06-05 21:21:57 +0000874//
875// guessLibraryShortName() is passed a name of a dynamic library and returns a
876// guess on what the short name is. Then name is returned as a substring of the
877// StringRef Name passed in. The name of the dynamic library is recognized as
878// a framework if it has one of the two following forms:
879// Foo.framework/Versions/A/Foo
880// Foo.framework/Foo
881// Where A and Foo can be any string. And may contain a trailing suffix
882// starting with an underbar. If the Name is recognized as a framework then
883// isFramework is set to true else it is set to false. If the Name has a
884// suffix then Suffix is set to the substring in Name that contains the suffix
885// else it is set to a NULL StringRef.
886//
887// The Name of the dynamic library is recognized as a library name if it has
888// one of the two following forms:
889// libFoo.A.dylib
890// libFoo.dylib
891// The library may have a suffix trailing the name Foo of the form:
892// libFoo_profile.A.dylib
893// libFoo_profile.dylib
894//
895// The Name of the dynamic library is also recognized as a library name if it
896// has the following form:
897// Foo.qtx
898//
899// If the Name of the dynamic library is none of the forms above then a NULL
900// StringRef is returned.
901//
902StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
903 bool &isFramework,
904 StringRef &Suffix) {
905 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
906 size_t a, b, c, d, Idx;
907
908 isFramework = false;
909 Suffix = StringRef();
910
911 // Pull off the last component and make Foo point to it
912 a = Name.rfind('/');
913 if (a == Name.npos || a == 0)
914 goto guess_library;
915 Foo = Name.slice(a+1, Name.npos);
916
917 // Look for a suffix starting with a '_'
918 Idx = Foo.rfind('_');
919 if (Idx != Foo.npos && Foo.size() >= 2) {
920 Suffix = Foo.slice(Idx, Foo.npos);
921 Foo = Foo.slice(0, Idx);
922 }
923
924 // First look for the form Foo.framework/Foo
925 b = Name.rfind('/', a);
926 if (b == Name.npos)
927 Idx = 0;
928 else
929 Idx = b+1;
930 F = Name.slice(Idx, Idx + Foo.size());
931 DotFramework = Name.slice(Idx + Foo.size(),
932 Idx + Foo.size() + sizeof(".framework/")-1);
933 if (F == Foo && DotFramework == ".framework/") {
934 isFramework = true;
935 return Foo;
936 }
937
938 // Next look for the form Foo.framework/Versions/A/Foo
939 if (b == Name.npos)
940 goto guess_library;
941 c = Name.rfind('/', b);
942 if (c == Name.npos || c == 0)
943 goto guess_library;
944 V = Name.slice(c+1, Name.npos);
945 if (!V.startswith("Versions/"))
946 goto guess_library;
947 d = Name.rfind('/', c);
948 if (d == Name.npos)
949 Idx = 0;
950 else
951 Idx = d+1;
952 F = Name.slice(Idx, Idx + Foo.size());
953 DotFramework = Name.slice(Idx + Foo.size(),
954 Idx + Foo.size() + sizeof(".framework/")-1);
955 if (F == Foo && DotFramework == ".framework/") {
956 isFramework = true;
957 return Foo;
958 }
959
960guess_library:
961 // pull off the suffix after the "." and make a point to it
962 a = Name.rfind('.');
963 if (a == Name.npos || a == 0)
964 return StringRef();
965 Dylib = Name.slice(a, Name.npos);
966 if (Dylib != ".dylib")
967 goto guess_qtx;
968
969 // First pull off the version letter for the form Foo.A.dylib if any.
970 if (a >= 3) {
971 Dot = Name.slice(a-2, a-1);
972 if (Dot == ".")
973 a = a - 2;
974 }
975
976 b = Name.rfind('/', a);
977 if (b == Name.npos)
978 b = 0;
979 else
980 b = b+1;
981 // ignore any suffix after an underbar like Foo_profile.A.dylib
982 Idx = Name.find('_', b);
983 if (Idx != Name.npos && Idx != b) {
984 Lib = Name.slice(b, Idx);
985 Suffix = Name.slice(Idx, a);
986 }
987 else
988 Lib = Name.slice(b, a);
989 // There are incorrect library names of the form:
990 // libATS.A_profile.dylib so check for these.
991 if (Lib.size() >= 3) {
992 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
993 if (Dot == ".")
994 Lib = Lib.slice(0, Lib.size()-2);
995 }
996 return Lib;
997
998guess_qtx:
999 Qtx = Name.slice(a, Name.npos);
1000 if (Qtx != ".qtx")
1001 return StringRef();
1002 b = Name.rfind('/', a);
1003 if (b == Name.npos)
1004 Lib = Name.slice(0, a);
1005 else
1006 Lib = Name.slice(b+1, a);
1007 // There are library names of the form: QT.A.qtx so check for these.
1008 if (Lib.size() >= 3) {
1009 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1010 if (Dot == ".")
1011 Lib = Lib.slice(0, Lib.size()-2);
1012 }
1013 return Lib;
1014}
1015
1016// getLibraryShortNameByIndex() is used to get the short name of the library
1017// for an undefined symbol in a linked Mach-O binary that was linked with the
1018// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1019// It is passed the index (0 - based) of the library as translated from
1020// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001021std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001022 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001023 if (Index >= Libraries.size())
1024 return object_error::parse_failed;
1025
Kevin Enderby980b2582014-06-05 21:21:57 +00001026 // If the cache of LibrariesShortNames is not built up do that first for
1027 // all the Libraries.
1028 if (LibrariesShortNames.size() == 0) {
1029 for (unsigned i = 0; i < Libraries.size(); i++) {
1030 MachO::dylib_command D =
1031 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001032 if (D.dylib.name >= D.cmdsize)
1033 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001034 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001035 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001036 if (D.dylib.name+Name.size() >= D.cmdsize)
1037 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001038 StringRef Suffix;
1039 bool isFramework;
1040 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001041 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001042 LibrariesShortNames.push_back(Name);
1043 else
1044 LibrariesShortNames.push_back(shortName);
1045 }
1046 }
1047
1048 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00001049 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001050}
1051
Rafael Espindola76ad2322015-07-06 14:55:37 +00001052section_iterator
1053MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
1054 DataRefImpl Sec;
1055 Sec.d.a = Rel->getRawDataRefImpl().d.a;
1056 return section_iterator(SectionRef(Sec, this));
1057}
1058
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001059basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00001060 DataRefImpl DRI;
1061 MachO::symtab_command Symtab = getSymtabLoadCommand();
1062 if (!SymtabLoadCmd || Symtab.nsyms == 0)
1063 return basic_symbol_iterator(SymbolRef(DRI, this));
1064
Lang Hames36072da2014-05-12 21:39:59 +00001065 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001066}
1067
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001068basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001069 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00001070 MachO::symtab_command Symtab = getSymtabLoadCommand();
1071 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001072 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001073
Rafael Espindola75c30362013-04-24 19:47:55 +00001074 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001075 sizeof(MachO::nlist_64) :
1076 sizeof(MachO::nlist);
1077 unsigned Offset = Symtab.symoff +
1078 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001079 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001080 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001081}
1082
Lang Hames36072da2014-05-12 21:39:59 +00001083basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00001084 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00001085 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001086 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001087 unsigned SymbolTableEntrySize =
1088 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00001089 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00001090 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1091 DRI.p += Index * SymbolTableEntrySize;
1092 return basic_symbol_iterator(SymbolRef(DRI, this));
1093}
1094
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001095uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
1096 MachO::symtab_command Symtab = getSymtabLoadCommand();
1097 if (!SymtabLoadCmd)
1098 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
1099 unsigned SymbolTableEntrySize =
1100 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1101 DataRefImpl DRIstart;
1102 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1103 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
1104 return Index;
1105}
1106
Rafael Espindolab5155a52014-02-10 20:24:04 +00001107section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001108 DataRefImpl DRI;
1109 return section_iterator(SectionRef(DRI, this));
1110}
1111
Rafael Espindolab5155a52014-02-10 20:24:04 +00001112section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001113 DataRefImpl DRI;
1114 DRI.d.a = Sections.size();
1115 return section_iterator(SectionRef(DRI, this));
1116}
1117
Rafael Espindola56f976f2013-04-18 18:08:55 +00001118uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001119 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001120}
1121
Rafael Espindola56f976f2013-04-18 18:08:55 +00001122StringRef MachOObjectFile::getFileFormatName() const {
1123 unsigned CPUType = getCPUType(this);
1124 if (!is64Bit()) {
1125 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001126 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001127 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001128 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001129 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001130 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001131 return "Mach-O 32-bit ppc";
1132 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001133 return "Mach-O 32-bit unknown";
1134 }
1135 }
1136
Rafael Espindola56f976f2013-04-18 18:08:55 +00001137 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001138 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001139 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001140 case llvm::MachO::CPU_TYPE_ARM64:
1141 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001142 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001143 return "Mach-O 64-bit ppc64";
1144 default:
1145 return "Mach-O 64-bit unknown";
1146 }
1147}
1148
Alexey Samsonove6388e62013-06-18 15:03:28 +00001149Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1150 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001151 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001152 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001153 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001154 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001155 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001156 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001157 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001158 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001159 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001160 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001161 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001162 return Triple::ppc64;
1163 default:
1164 return Triple::UnknownArch;
1165 }
1166}
1167
Tim Northover9e8eb412016-04-22 23:21:13 +00001168Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
1169 const char **McpuDefault) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001170 if (McpuDefault)
1171 *McpuDefault = nullptr;
1172
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001173 switch (CPUType) {
1174 case MachO::CPU_TYPE_I386:
1175 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1176 case MachO::CPU_SUBTYPE_I386_ALL:
1177 return Triple("i386-apple-darwin");
1178 default:
1179 return Triple();
1180 }
1181 case MachO::CPU_TYPE_X86_64:
1182 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1183 case MachO::CPU_SUBTYPE_X86_64_ALL:
1184 return Triple("x86_64-apple-darwin");
1185 case MachO::CPU_SUBTYPE_X86_64_H:
1186 return Triple("x86_64h-apple-darwin");
1187 default:
1188 return Triple();
1189 }
1190 case MachO::CPU_TYPE_ARM:
1191 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1192 case MachO::CPU_SUBTYPE_ARM_V4T:
1193 return Triple("armv4t-apple-darwin");
1194 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1195 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001196 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1197 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001198 case MachO::CPU_SUBTYPE_ARM_V6:
1199 return Triple("armv6-apple-darwin");
1200 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001201 if (McpuDefault)
1202 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001203 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001204 case MachO::CPU_SUBTYPE_ARM_V7:
1205 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001206 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001207 if (McpuDefault)
1208 *McpuDefault = "cortex-m4";
Tim Northover9e8eb412016-04-22 23:21:13 +00001209 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001210 case MachO::CPU_SUBTYPE_ARM_V7K:
1211 return Triple("armv7k-apple-darwin");
1212 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001213 if (McpuDefault)
1214 *McpuDefault = "cortex-m3";
Tim Northover9e8eb412016-04-22 23:21:13 +00001215 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001216 case MachO::CPU_SUBTYPE_ARM_V7S:
1217 return Triple("armv7s-apple-darwin");
1218 default:
1219 return Triple();
1220 }
1221 case MachO::CPU_TYPE_ARM64:
1222 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1223 case MachO::CPU_SUBTYPE_ARM64_ALL:
1224 return Triple("arm64-apple-darwin");
1225 default:
1226 return Triple();
1227 }
1228 case MachO::CPU_TYPE_POWERPC:
1229 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1230 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1231 return Triple("ppc-apple-darwin");
1232 default:
1233 return Triple();
1234 }
1235 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001236 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001237 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1238 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001239 default:
1240 return Triple();
1241 }
1242 default:
1243 return Triple();
1244 }
1245}
1246
1247Triple MachOObjectFile::getHostArch() {
1248 return Triple(sys::getDefaultTargetTriple());
1249}
1250
Rafael Espindola72318b42014-08-08 16:30:17 +00001251bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1252 return StringSwitch<bool>(ArchFlag)
1253 .Case("i386", true)
1254 .Case("x86_64", true)
1255 .Case("x86_64h", true)
1256 .Case("armv4t", true)
1257 .Case("arm", true)
1258 .Case("armv5e", true)
1259 .Case("armv6", true)
1260 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001261 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001262 .Case("armv7em", true)
1263 .Case("armv7k", true)
1264 .Case("armv7m", true)
1265 .Case("armv7s", true)
1266 .Case("arm64", true)
1267 .Case("ppc", true)
1268 .Case("ppc64", true)
1269 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001270}
1271
Alexey Samsonove6388e62013-06-18 15:03:28 +00001272unsigned MachOObjectFile::getArch() const {
1273 return getArch(getCPUType(this));
1274}
1275
Tim Northover9e8eb412016-04-22 23:21:13 +00001276Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
1277 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001278}
1279
Rui Ueyamabc654b12013-09-27 21:47:05 +00001280relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001281 DataRefImpl DRI;
1282 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001283 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001284}
1285
Rui Ueyamabc654b12013-09-27 21:47:05 +00001286relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001287 DataRefImpl DRI;
1288 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001289 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001290}
1291
Kevin Enderby273ae012013-06-06 17:20:50 +00001292dice_iterator MachOObjectFile::begin_dices() const {
1293 DataRefImpl DRI;
1294 if (!DataInCodeLoadCmd)
1295 return dice_iterator(DiceRef(DRI, this));
1296
Charles Davis8bdfafd2013-09-01 04:28:48 +00001297 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1298 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001299 return dice_iterator(DiceRef(DRI, this));
1300}
1301
1302dice_iterator MachOObjectFile::end_dices() const {
1303 DataRefImpl DRI;
1304 if (!DataInCodeLoadCmd)
1305 return dice_iterator(DiceRef(DRI, this));
1306
Charles Davis8bdfafd2013-09-01 04:28:48 +00001307 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1308 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001309 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1310 return dice_iterator(DiceRef(DRI, this));
1311}
1312
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001313ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1314 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001315
1316void ExportEntry::moveToFirst() {
1317 pushNode(0);
1318 pushDownUntilBottom();
1319}
1320
1321void ExportEntry::moveToEnd() {
1322 Stack.clear();
1323 Done = true;
1324}
1325
1326bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001327 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001328 if (Done || Other.Done)
1329 return (Done == Other.Done);
1330 // Not equal if different stack sizes.
1331 if (Stack.size() != Other.Stack.size())
1332 return false;
1333 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001334 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001335 return false;
1336 // Equal if all nodes in both stacks match.
1337 for (unsigned i=0; i < Stack.size(); ++i) {
1338 if (Stack[i].Start != Other.Stack[i].Start)
1339 return false;
1340 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001341 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001342}
1343
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001344uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1345 unsigned Count;
1346 uint64_t Result = decodeULEB128(Ptr, &Count);
1347 Ptr += Count;
1348 if (Ptr > Trie.end()) {
1349 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001350 Malformed = true;
1351 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001352 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001353}
1354
1355StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001356 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001357}
1358
1359uint64_t ExportEntry::flags() const {
1360 return Stack.back().Flags;
1361}
1362
1363uint64_t ExportEntry::address() const {
1364 return Stack.back().Address;
1365}
1366
1367uint64_t ExportEntry::other() const {
1368 return Stack.back().Other;
1369}
1370
1371StringRef ExportEntry::otherName() const {
1372 const char* ImportName = Stack.back().ImportName;
1373 if (ImportName)
1374 return StringRef(ImportName);
1375 return StringRef();
1376}
1377
1378uint32_t ExportEntry::nodeOffset() const {
1379 return Stack.back().Start - Trie.begin();
1380}
1381
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001382ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1383 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1384 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1385 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001386
1387void ExportEntry::pushNode(uint64_t offset) {
1388 const uint8_t *Ptr = Trie.begin() + offset;
1389 NodeState State(Ptr);
1390 uint64_t ExportInfoSize = readULEB128(State.Current);
1391 State.IsExportNode = (ExportInfoSize != 0);
1392 const uint8_t* Children = State.Current + ExportInfoSize;
1393 if (State.IsExportNode) {
1394 State.Flags = readULEB128(State.Current);
1395 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1396 State.Address = 0;
1397 State.Other = readULEB128(State.Current); // dylib ordinal
1398 State.ImportName = reinterpret_cast<const char*>(State.Current);
1399 } else {
1400 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001401 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001402 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001403 }
1404 }
1405 State.ChildCount = *Children;
1406 State.Current = Children + 1;
1407 State.NextChildIndex = 0;
1408 State.ParentStringLength = CumulativeString.size();
1409 Stack.push_back(State);
1410}
1411
1412void ExportEntry::pushDownUntilBottom() {
1413 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1414 NodeState &Top = Stack.back();
1415 CumulativeString.resize(Top.ParentStringLength);
1416 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001417 char C = *Top.Current;
1418 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001419 }
1420 Top.Current += 1;
1421 uint64_t childNodeIndex = readULEB128(Top.Current);
1422 Top.NextChildIndex += 1;
1423 pushNode(childNodeIndex);
1424 }
1425 if (!Stack.back().IsExportNode) {
1426 Malformed = true;
1427 moveToEnd();
1428 }
1429}
1430
1431// We have a trie data structure and need a way to walk it that is compatible
1432// with the C++ iterator model. The solution is a non-recursive depth first
1433// traversal where the iterator contains a stack of parent nodes along with a
1434// string that is the accumulation of all edge strings along the parent chain
1435// to this point.
1436//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001437// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001438// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001439// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001440//
1441// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1442// child until hitting a node with no children (which is an export node or
1443// else the trie is malformed). On the way down, each node is pushed on the
1444// stack ivar. If there is no more ways down, it pops up one and tries to go
1445// down a sibling path until a childless node is reached.
1446void ExportEntry::moveNext() {
1447 if (Stack.empty() || !Stack.back().IsExportNode) {
1448 Malformed = true;
1449 moveToEnd();
1450 return;
1451 }
1452
1453 Stack.pop_back();
1454 while (!Stack.empty()) {
1455 NodeState &Top = Stack.back();
1456 if (Top.NextChildIndex < Top.ChildCount) {
1457 pushDownUntilBottom();
1458 // Now at the next export node.
1459 return;
1460 } else {
1461 if (Top.IsExportNode) {
1462 // This node has no children but is itself an export node.
1463 CumulativeString.resize(Top.ParentStringLength);
1464 return;
1465 }
1466 Stack.pop_back();
1467 }
1468 }
1469 Done = true;
1470}
1471
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001472iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00001473MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1474 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001475 if (Trie.size() == 0)
1476 Start.moveToEnd();
1477 else
1478 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001479
1480 ExportEntry Finish(Trie);
1481 Finish.moveToEnd();
1482
Craig Topper15576e12015-12-06 05:08:07 +00001483 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00001484}
1485
1486iterator_range<export_iterator> MachOObjectFile::exports() const {
1487 return exports(getDyldInfoExportsTrie());
1488}
1489
Nick Kledzikac431442014-09-12 21:34:15 +00001490MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1491 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1492 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1493 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1494
1495void MachORebaseEntry::moveToFirst() {
1496 Ptr = Opcodes.begin();
1497 moveNext();
1498}
1499
1500void MachORebaseEntry::moveToEnd() {
1501 Ptr = Opcodes.end();
1502 RemainingLoopCount = 0;
1503 Done = true;
1504}
1505
1506void MachORebaseEntry::moveNext() {
1507 // If in the middle of some loop, move to next rebasing in loop.
1508 SegmentOffset += AdvanceAmount;
1509 if (RemainingLoopCount) {
1510 --RemainingLoopCount;
1511 return;
1512 }
1513 if (Ptr == Opcodes.end()) {
1514 Done = true;
1515 return;
1516 }
1517 bool More = true;
1518 while (More && !Malformed) {
1519 // Parse next opcode and set up next loop.
1520 uint8_t Byte = *Ptr++;
1521 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1522 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1523 switch (Opcode) {
1524 case MachO::REBASE_OPCODE_DONE:
1525 More = false;
1526 Done = true;
1527 moveToEnd();
1528 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1529 break;
1530 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1531 RebaseType = ImmValue;
1532 DEBUG_WITH_TYPE(
1533 "mach-o-rebase",
1534 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1535 << "RebaseType=" << (int) RebaseType << "\n");
1536 break;
1537 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1538 SegmentIndex = ImmValue;
1539 SegmentOffset = readULEB128();
1540 DEBUG_WITH_TYPE(
1541 "mach-o-rebase",
1542 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1543 << "SegmentIndex=" << SegmentIndex << ", "
1544 << format("SegmentOffset=0x%06X", SegmentOffset)
1545 << "\n");
1546 break;
1547 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1548 SegmentOffset += readULEB128();
1549 DEBUG_WITH_TYPE("mach-o-rebase",
1550 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1551 << format("SegmentOffset=0x%06X",
1552 SegmentOffset) << "\n");
1553 break;
1554 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1555 SegmentOffset += ImmValue * PointerSize;
1556 DEBUG_WITH_TYPE("mach-o-rebase",
1557 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1558 << format("SegmentOffset=0x%06X",
1559 SegmentOffset) << "\n");
1560 break;
1561 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1562 AdvanceAmount = PointerSize;
1563 RemainingLoopCount = ImmValue - 1;
1564 DEBUG_WITH_TYPE(
1565 "mach-o-rebase",
1566 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1567 << format("SegmentOffset=0x%06X", SegmentOffset)
1568 << ", AdvanceAmount=" << AdvanceAmount
1569 << ", RemainingLoopCount=" << RemainingLoopCount
1570 << "\n");
1571 return;
1572 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1573 AdvanceAmount = PointerSize;
1574 RemainingLoopCount = readULEB128() - 1;
1575 DEBUG_WITH_TYPE(
1576 "mach-o-rebase",
1577 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1578 << format("SegmentOffset=0x%06X", SegmentOffset)
1579 << ", AdvanceAmount=" << AdvanceAmount
1580 << ", RemainingLoopCount=" << RemainingLoopCount
1581 << "\n");
1582 return;
1583 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1584 AdvanceAmount = readULEB128() + PointerSize;
1585 RemainingLoopCount = 0;
1586 DEBUG_WITH_TYPE(
1587 "mach-o-rebase",
1588 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1589 << format("SegmentOffset=0x%06X", SegmentOffset)
1590 << ", AdvanceAmount=" << AdvanceAmount
1591 << ", RemainingLoopCount=" << RemainingLoopCount
1592 << "\n");
1593 return;
1594 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1595 RemainingLoopCount = readULEB128() - 1;
1596 AdvanceAmount = readULEB128() + PointerSize;
1597 DEBUG_WITH_TYPE(
1598 "mach-o-rebase",
1599 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1600 << format("SegmentOffset=0x%06X", SegmentOffset)
1601 << ", AdvanceAmount=" << AdvanceAmount
1602 << ", RemainingLoopCount=" << RemainingLoopCount
1603 << "\n");
1604 return;
1605 default:
1606 Malformed = true;
1607 }
1608 }
1609}
1610
1611uint64_t MachORebaseEntry::readULEB128() {
1612 unsigned Count;
1613 uint64_t Result = decodeULEB128(Ptr, &Count);
1614 Ptr += Count;
1615 if (Ptr > Opcodes.end()) {
1616 Ptr = Opcodes.end();
1617 Malformed = true;
1618 }
1619 return Result;
1620}
1621
1622uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1623
1624uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1625
1626StringRef MachORebaseEntry::typeName() const {
1627 switch (RebaseType) {
1628 case MachO::REBASE_TYPE_POINTER:
1629 return "pointer";
1630 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1631 return "text abs32";
1632 case MachO::REBASE_TYPE_TEXT_PCREL32:
1633 return "text rel32";
1634 }
1635 return "unknown";
1636}
1637
1638bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1639 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1640 return (Ptr == Other.Ptr) &&
1641 (RemainingLoopCount == Other.RemainingLoopCount) &&
1642 (Done == Other.Done);
1643}
1644
1645iterator_range<rebase_iterator>
1646MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1647 MachORebaseEntry Start(Opcodes, is64);
1648 Start.moveToFirst();
1649
1650 MachORebaseEntry Finish(Opcodes, is64);
1651 Finish.moveToEnd();
1652
Craig Topper15576e12015-12-06 05:08:07 +00001653 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00001654}
1655
1656iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1657 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1658}
1659
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001660MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00001661 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1662 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1663 BindType(0), PointerSize(is64Bit ? 8 : 4),
1664 TableKind(BK), Malformed(false), Done(false) {}
1665
1666void MachOBindEntry::moveToFirst() {
1667 Ptr = Opcodes.begin();
1668 moveNext();
1669}
1670
1671void MachOBindEntry::moveToEnd() {
1672 Ptr = Opcodes.end();
1673 RemainingLoopCount = 0;
1674 Done = true;
1675}
1676
1677void MachOBindEntry::moveNext() {
1678 // If in the middle of some loop, move to next binding in loop.
1679 SegmentOffset += AdvanceAmount;
1680 if (RemainingLoopCount) {
1681 --RemainingLoopCount;
1682 return;
1683 }
1684 if (Ptr == Opcodes.end()) {
1685 Done = true;
1686 return;
1687 }
1688 bool More = true;
1689 while (More && !Malformed) {
1690 // Parse next opcode and set up next loop.
1691 uint8_t Byte = *Ptr++;
1692 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1693 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1694 int8_t SignExtended;
1695 const uint8_t *SymStart;
1696 switch (Opcode) {
1697 case MachO::BIND_OPCODE_DONE:
1698 if (TableKind == Kind::Lazy) {
1699 // Lazying bindings have a DONE opcode between entries. Need to ignore
1700 // it to advance to next entry. But need not if this is last entry.
1701 bool NotLastEntry = false;
1702 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1703 if (*P) {
1704 NotLastEntry = true;
1705 }
1706 }
1707 if (NotLastEntry)
1708 break;
1709 }
1710 More = false;
1711 Done = true;
1712 moveToEnd();
1713 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1714 break;
1715 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1716 Ordinal = ImmValue;
1717 DEBUG_WITH_TYPE(
1718 "mach-o-bind",
1719 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1720 << "Ordinal=" << Ordinal << "\n");
1721 break;
1722 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1723 Ordinal = readULEB128();
1724 DEBUG_WITH_TYPE(
1725 "mach-o-bind",
1726 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1727 << "Ordinal=" << Ordinal << "\n");
1728 break;
1729 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1730 if (ImmValue) {
1731 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1732 Ordinal = SignExtended;
1733 } else
1734 Ordinal = 0;
1735 DEBUG_WITH_TYPE(
1736 "mach-o-bind",
1737 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1738 << "Ordinal=" << Ordinal << "\n");
1739 break;
1740 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1741 Flags = ImmValue;
1742 SymStart = Ptr;
1743 while (*Ptr) {
1744 ++Ptr;
1745 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001746 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1747 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001748 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001749 DEBUG_WITH_TYPE(
1750 "mach-o-bind",
1751 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1752 << "SymbolName=" << SymbolName << "\n");
1753 if (TableKind == Kind::Weak) {
1754 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1755 return;
1756 }
1757 break;
1758 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1759 BindType = ImmValue;
1760 DEBUG_WITH_TYPE(
1761 "mach-o-bind",
1762 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1763 << "BindType=" << (int)BindType << "\n");
1764 break;
1765 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1766 Addend = readSLEB128();
1767 if (TableKind == Kind::Lazy)
1768 Malformed = true;
1769 DEBUG_WITH_TYPE(
1770 "mach-o-bind",
1771 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1772 << "Addend=" << Addend << "\n");
1773 break;
1774 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1775 SegmentIndex = ImmValue;
1776 SegmentOffset = readULEB128();
1777 DEBUG_WITH_TYPE(
1778 "mach-o-bind",
1779 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1780 << "SegmentIndex=" << SegmentIndex << ", "
1781 << format("SegmentOffset=0x%06X", SegmentOffset)
1782 << "\n");
1783 break;
1784 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1785 SegmentOffset += readULEB128();
1786 DEBUG_WITH_TYPE("mach-o-bind",
1787 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1788 << format("SegmentOffset=0x%06X",
1789 SegmentOffset) << "\n");
1790 break;
1791 case MachO::BIND_OPCODE_DO_BIND:
1792 AdvanceAmount = PointerSize;
1793 RemainingLoopCount = 0;
1794 DEBUG_WITH_TYPE("mach-o-bind",
1795 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1796 << format("SegmentOffset=0x%06X",
1797 SegmentOffset) << "\n");
1798 return;
1799 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001800 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001801 RemainingLoopCount = 0;
1802 if (TableKind == Kind::Lazy)
1803 Malformed = true;
1804 DEBUG_WITH_TYPE(
1805 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001806 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001807 << format("SegmentOffset=0x%06X", SegmentOffset)
1808 << ", AdvanceAmount=" << AdvanceAmount
1809 << ", RemainingLoopCount=" << RemainingLoopCount
1810 << "\n");
1811 return;
1812 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001813 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001814 RemainingLoopCount = 0;
1815 if (TableKind == Kind::Lazy)
1816 Malformed = true;
1817 DEBUG_WITH_TYPE("mach-o-bind",
1818 llvm::dbgs()
1819 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1820 << format("SegmentOffset=0x%06X",
1821 SegmentOffset) << "\n");
1822 return;
1823 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1824 RemainingLoopCount = readULEB128() - 1;
1825 AdvanceAmount = readULEB128() + PointerSize;
1826 if (TableKind == Kind::Lazy)
1827 Malformed = true;
1828 DEBUG_WITH_TYPE(
1829 "mach-o-bind",
1830 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1831 << format("SegmentOffset=0x%06X", SegmentOffset)
1832 << ", AdvanceAmount=" << AdvanceAmount
1833 << ", RemainingLoopCount=" << RemainingLoopCount
1834 << "\n");
1835 return;
1836 default:
1837 Malformed = true;
1838 }
1839 }
1840}
1841
1842uint64_t MachOBindEntry::readULEB128() {
1843 unsigned Count;
1844 uint64_t Result = decodeULEB128(Ptr, &Count);
1845 Ptr += Count;
1846 if (Ptr > Opcodes.end()) {
1847 Ptr = Opcodes.end();
1848 Malformed = true;
1849 }
1850 return Result;
1851}
1852
1853int64_t MachOBindEntry::readSLEB128() {
1854 unsigned Count;
1855 int64_t Result = decodeSLEB128(Ptr, &Count);
1856 Ptr += Count;
1857 if (Ptr > Opcodes.end()) {
1858 Ptr = Opcodes.end();
1859 Malformed = true;
1860 }
1861 return Result;
1862}
1863
Nick Kledzik56ebef42014-09-16 01:41:51 +00001864uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1865
1866uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1867
1868StringRef MachOBindEntry::typeName() const {
1869 switch (BindType) {
1870 case MachO::BIND_TYPE_POINTER:
1871 return "pointer";
1872 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1873 return "text abs32";
1874 case MachO::BIND_TYPE_TEXT_PCREL32:
1875 return "text rel32";
1876 }
1877 return "unknown";
1878}
1879
1880StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1881
1882int64_t MachOBindEntry::addend() const { return Addend; }
1883
1884uint32_t MachOBindEntry::flags() const { return Flags; }
1885
1886int MachOBindEntry::ordinal() const { return Ordinal; }
1887
1888bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1889 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1890 return (Ptr == Other.Ptr) &&
1891 (RemainingLoopCount == Other.RemainingLoopCount) &&
1892 (Done == Other.Done);
1893}
1894
1895iterator_range<bind_iterator>
1896MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1897 MachOBindEntry::Kind BKind) {
1898 MachOBindEntry Start(Opcodes, is64, BKind);
1899 Start.moveToFirst();
1900
1901 MachOBindEntry Finish(Opcodes, is64, BKind);
1902 Finish.moveToEnd();
1903
Craig Topper15576e12015-12-06 05:08:07 +00001904 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00001905}
1906
1907iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1908 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1909 MachOBindEntry::Kind::Regular);
1910}
1911
1912iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1913 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1914 MachOBindEntry::Kind::Lazy);
1915}
1916
1917iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1918 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1919 MachOBindEntry::Kind::Weak);
1920}
1921
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001922MachOObjectFile::load_command_iterator
1923MachOObjectFile::begin_load_commands() const {
1924 return LoadCommands.begin();
1925}
1926
1927MachOObjectFile::load_command_iterator
1928MachOObjectFile::end_load_commands() const {
1929 return LoadCommands.end();
1930}
1931
1932iterator_range<MachOObjectFile::load_command_iterator>
1933MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00001934 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001935}
1936
Rafael Espindola56f976f2013-04-18 18:08:55 +00001937StringRef
1938MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1939 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1940 return parseSegmentOrSectionName(Raw.data());
1941}
1942
1943ArrayRef<char>
1944MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001945 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001946 const section_base *Base =
1947 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001948 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001949}
1950
1951ArrayRef<char>
1952MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001953 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001954 const section_base *Base =
1955 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001956 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001957}
1958
1959bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001960MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001961 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001962 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001963 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001964 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001965}
1966
Eric Christopher1d62c252013-07-22 22:25:07 +00001967unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001968 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001969 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001970 return RE.r_word1 & 0xffffff;
1971 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001972}
1973
Eric Christopher1d62c252013-07-22 22:25:07 +00001974bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001975 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001976 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001977 return (RE.r_word1 >> 27) & 1;
1978 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001979}
1980
Eric Christopher1d62c252013-07-22 22:25:07 +00001981bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001982 const MachO::any_relocation_info &RE) const {
1983 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001984}
1985
Eric Christopher1d62c252013-07-22 22:25:07 +00001986uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001987 const MachO::any_relocation_info &RE) const {
1988 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001989}
1990
Kevin Enderby9907d0a2014-11-04 00:43:16 +00001991uint32_t MachOObjectFile::getScatteredRelocationType(
1992 const MachO::any_relocation_info &RE) const {
1993 return (RE.r_word0 >> 24) & 0xf;
1994}
1995
Eric Christopher1d62c252013-07-22 22:25:07 +00001996unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001997 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001998 if (isRelocationScattered(RE))
1999 return getScatteredRelocationAddress(RE);
2000 return getPlainRelocationAddress(RE);
2001}
2002
Charles Davis8bdfafd2013-09-01 04:28:48 +00002003unsigned MachOObjectFile::getAnyRelocationPCRel(
2004 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002005 if (isRelocationScattered(RE))
2006 return getScatteredRelocationPCRel(this, RE);
2007 return getPlainRelocationPCRel(this, RE);
2008}
2009
Eric Christopher1d62c252013-07-22 22:25:07 +00002010unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002011 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002012 if (isRelocationScattered(RE))
2013 return getScatteredRelocationLength(RE);
2014 return getPlainRelocationLength(this, RE);
2015}
2016
2017unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002018MachOObjectFile::getAnyRelocationType(
2019 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002020 if (isRelocationScattered(RE))
2021 return getScatteredRelocationType(RE);
2022 return getPlainRelocationType(this, RE);
2023}
2024
Rafael Espindola52501032013-04-30 15:40:54 +00002025SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002026MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002027 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002028 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002029 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002030 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2031 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2032 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002033 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002034 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002035 return SectionRef(DRI, this);
2036}
2037
Charles Davis8bdfafd2013-09-01 04:28:48 +00002038MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002039 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002040 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002041}
2042
Charles Davis8bdfafd2013-09-01 04:28:48 +00002043MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002044 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002045 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002046}
2047
Charles Davis8bdfafd2013-09-01 04:28:48 +00002048MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002049 unsigned Index) const {
2050 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002051 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002052}
2053
Charles Davis8bdfafd2013-09-01 04:28:48 +00002054MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2055 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002056 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002057 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002058}
2059
Charles Davis8bdfafd2013-09-01 04:28:48 +00002060MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002061MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002062 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002063 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002064}
2065
Charles Davis8bdfafd2013-09-01 04:28:48 +00002066MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002067MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002068 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002069 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002070}
2071
Charles Davis8bdfafd2013-09-01 04:28:48 +00002072MachO::linkedit_data_command
2073MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2074 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002075}
2076
Charles Davis8bdfafd2013-09-01 04:28:48 +00002077MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002078MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002079 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002080}
2081
Charles Davis8bdfafd2013-09-01 04:28:48 +00002082MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002083MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002084 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002085}
2086
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002087MachO::linker_option_command
2088MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2089 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002090}
2091
Jim Grosbach448334a2014-03-18 22:09:05 +00002092MachO::version_min_command
2093MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2094 return getStruct<MachO::version_min_command>(this, L.Ptr);
2095}
2096
Tim Northover8f9590b2014-06-30 14:40:57 +00002097MachO::dylib_command
2098MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2099 return getStruct<MachO::dylib_command>(this, L.Ptr);
2100}
2101
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002102MachO::dyld_info_command
2103MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2104 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2105}
2106
2107MachO::dylinker_command
2108MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2109 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2110}
2111
2112MachO::uuid_command
2113MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2114 return getStruct<MachO::uuid_command>(this, L.Ptr);
2115}
2116
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002117MachO::rpath_command
2118MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2119 return getStruct<MachO::rpath_command>(this, L.Ptr);
2120}
2121
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002122MachO::source_version_command
2123MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2124 return getStruct<MachO::source_version_command>(this, L.Ptr);
2125}
2126
2127MachO::entry_point_command
2128MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2129 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2130}
2131
Kevin Enderby0804f4672014-12-16 23:25:52 +00002132MachO::encryption_info_command
2133MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2134 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2135}
2136
Kevin Enderby57538292014-12-17 01:01:30 +00002137MachO::encryption_info_command_64
2138MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2139 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2140}
2141
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002142MachO::sub_framework_command
2143MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2144 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2145}
Tim Northover8f9590b2014-06-30 14:40:57 +00002146
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002147MachO::sub_umbrella_command
2148MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2149 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2150}
2151
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002152MachO::sub_library_command
2153MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2154 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2155}
2156
Kevin Enderby186eac32014-12-19 21:06:24 +00002157MachO::sub_client_command
2158MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2159 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2160}
2161
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002162MachO::routines_command
2163MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2164 return getStruct<MachO::routines_command>(this, L.Ptr);
2165}
2166
2167MachO::routines_command_64
2168MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2169 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2170}
2171
Kevin Enderby48ef5342014-12-23 22:56:39 +00002172MachO::thread_command
2173MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2174 return getStruct<MachO::thread_command>(this, L.Ptr);
2175}
2176
Charles Davis8bdfafd2013-09-01 04:28:48 +00002177MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002178MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002179 DataRefImpl Sec;
2180 Sec.d.a = Rel.d.a;
2181 uint32_t Offset;
2182 if (is64Bit()) {
2183 MachO::section_64 Sect = getSection64(Sec);
2184 Offset = Sect.reloff;
2185 } else {
2186 MachO::section Sect = getSection(Sec);
2187 Offset = Sect.reloff;
2188 }
2189
2190 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2191 getPtr(this, Offset)) + Rel.d.b;
2192 return getStruct<MachO::any_relocation_info>(
2193 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002194}
2195
Charles Davis8bdfafd2013-09-01 04:28:48 +00002196MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002197MachOObjectFile::getDice(DataRefImpl Rel) const {
2198 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002199 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002200}
2201
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002202const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002203 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002204}
2205
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002206const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2207 assert(is64Bit());
2208 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002209}
2210
Charles Davis8bdfafd2013-09-01 04:28:48 +00002211uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2212 const MachO::dysymtab_command &DLC,
2213 unsigned Index) const {
2214 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2215 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002216}
2217
Charles Davis8bdfafd2013-09-01 04:28:48 +00002218MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002219MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2220 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002221 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2222 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002223}
2224
Charles Davis8bdfafd2013-09-01 04:28:48 +00002225MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002226 if (SymtabLoadCmd)
2227 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2228
2229 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2230 MachO::symtab_command Cmd;
2231 Cmd.cmd = MachO::LC_SYMTAB;
2232 Cmd.cmdsize = sizeof(MachO::symtab_command);
2233 Cmd.symoff = 0;
2234 Cmd.nsyms = 0;
2235 Cmd.stroff = 0;
2236 Cmd.strsize = 0;
2237 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002238}
2239
Charles Davis8bdfafd2013-09-01 04:28:48 +00002240MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002241 if (DysymtabLoadCmd)
2242 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2243
2244 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2245 MachO::dysymtab_command Cmd;
2246 Cmd.cmd = MachO::LC_DYSYMTAB;
2247 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2248 Cmd.ilocalsym = 0;
2249 Cmd.nlocalsym = 0;
2250 Cmd.iextdefsym = 0;
2251 Cmd.nextdefsym = 0;
2252 Cmd.iundefsym = 0;
2253 Cmd.nundefsym = 0;
2254 Cmd.tocoff = 0;
2255 Cmd.ntoc = 0;
2256 Cmd.modtaboff = 0;
2257 Cmd.nmodtab = 0;
2258 Cmd.extrefsymoff = 0;
2259 Cmd.nextrefsyms = 0;
2260 Cmd.indirectsymoff = 0;
2261 Cmd.nindirectsyms = 0;
2262 Cmd.extreloff = 0;
2263 Cmd.nextrel = 0;
2264 Cmd.locreloff = 0;
2265 Cmd.nlocrel = 0;
2266 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002267}
2268
Charles Davis8bdfafd2013-09-01 04:28:48 +00002269MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002270MachOObjectFile::getDataInCodeLoadCommand() const {
2271 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002272 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002273
2274 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002275 MachO::linkedit_data_command Cmd;
2276 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2277 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2278 Cmd.dataoff = 0;
2279 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002280 return Cmd;
2281}
2282
Kevin Enderby9a509442015-01-27 21:28:24 +00002283MachO::linkedit_data_command
2284MachOObjectFile::getLinkOptHintsLoadCommand() const {
2285 if (LinkOptHintsLoadCmd)
2286 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2287
2288 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2289 // fields.
2290 MachO::linkedit_data_command Cmd;
2291 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2292 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2293 Cmd.dataoff = 0;
2294 Cmd.datasize = 0;
2295 return Cmd;
2296}
2297
Nick Kledzikd04bc352014-08-30 00:20:14 +00002298ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002299 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002300 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002301
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002302 MachO::dyld_info_command DyldInfo =
2303 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2304 const uint8_t *Ptr =
2305 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00002306 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002307}
2308
2309ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002310 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002311 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002312
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002313 MachO::dyld_info_command DyldInfo =
2314 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2315 const uint8_t *Ptr =
2316 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002317 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002318}
2319
2320ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002321 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002322 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002323
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002324 MachO::dyld_info_command DyldInfo =
2325 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2326 const uint8_t *Ptr =
2327 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002328 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002329}
2330
2331ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002332 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002333 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002334
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002335 MachO::dyld_info_command DyldInfo =
2336 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2337 const uint8_t *Ptr =
2338 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002339 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002340}
2341
2342ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002343 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002344 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002345
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002346 MachO::dyld_info_command DyldInfo =
2347 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2348 const uint8_t *Ptr =
2349 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00002350 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002351}
2352
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002353ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2354 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002355 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00002356 // Returning a pointer is fine as uuid doesn't need endian swapping.
2357 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00002358 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002359}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002360
Rafael Espindola6e040c02013-04-26 20:07:33 +00002361StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002362 MachO::symtab_command S = getSymtabLoadCommand();
2363 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002364}
2365
Rafael Espindola56f976f2013-04-18 18:08:55 +00002366bool MachOObjectFile::is64Bit() const {
2367 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002368 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002369}
2370
2371void MachOObjectFile::ReadULEB128s(uint64_t Index,
2372 SmallVectorImpl<uint64_t> &Out) const {
2373 DataExtractor extractor(ObjectFile::getData(), true, 0);
2374
2375 uint32_t offset = Index;
2376 uint64_t data = 0;
2377 while (uint64_t delta = extractor.getULEB128(&offset)) {
2378 data += delta;
2379 Out.push_back(data);
2380 }
2381}
2382
Rafael Espindolac66d7612014-08-17 19:09:37 +00002383bool MachOObjectFile::isRelocatableObject() const {
2384 return getHeader().filetype == MachO::MH_OBJECT;
2385}
2386
Lang Hamesff044b12016-03-25 23:11:52 +00002387Expected<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002388ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2389 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00002390 if (Magic == "\xFE\xED\xFA\xCE")
Lang Hamesff044b12016-03-25 23:11:52 +00002391 return MachOObjectFile::create(Buffer, false, false);
David Blaikieb805f732016-03-28 17:45:48 +00002392 if (Magic == "\xCE\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002393 return MachOObjectFile::create(Buffer, true, false);
David Blaikieb805f732016-03-28 17:45:48 +00002394 if (Magic == "\xFE\xED\xFA\xCF")
Lang Hamesff044b12016-03-25 23:11:52 +00002395 return MachOObjectFile::create(Buffer, false, true);
David Blaikieb805f732016-03-28 17:45:48 +00002396 if (Magic == "\xCF\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002397 return MachOObjectFile::create(Buffer, true, true);
Justin Bogner2a42da92016-05-05 23:59:57 +00002398 return make_error<GenericBinaryError>(Buffer.getBufferIdentifier(),
2399 "Unrecognized MachO magic number",
2400 object_error::invalid_file_type);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002401}