blob: 2240dc8b04a58c749b153fbc9098c3809e0f11f2 [file] [log] [blame]
Eric Christopher7b015c72011-04-22 03:19:48 +00001//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Owen Anderson27c579d2011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Tim Northover00ed9962014-03-29 10:18:08 +000016#include "llvm/ADT/STLExtras.h"
Rafael Espindola72318b42014-08-08 16:30:17 +000017#include "llvm/ADT/StringSwitch.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000018#include "llvm/ADT/Triple.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000019#include "llvm/Support/DataExtractor.h"
Nick Kledzikac431442014-09-12 21:34:15 +000020#include "llvm/Support/Debug.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000021#include "llvm/Support/Format.h"
Rafael Espindola56f976f2013-04-18 18:08:55 +000022#include "llvm/Support/Host.h"
Nick Kledzikd04bc352014-08-30 00:20:14 +000023#include "llvm/Support/LEB128.h"
24#include "llvm/Support/MachO.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000025#include "llvm/Support/MemoryBuffer.h"
Jakub Staszak84a0ae72013-08-21 01:20:11 +000026#include "llvm/Support/raw_ostream.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000027#include <cctype>
28#include <cstring>
29#include <limits>
30
31using namespace llvm;
32using namespace object;
33
Artyom Skrobov7d602f72014-07-20 12:08:28 +000034namespace {
35 struct section_base {
36 char sectname[16];
37 char segname[16];
38 };
39}
Rafael Espindola56f976f2013-04-18 18:08:55 +000040
Lang Hames9e964f32016-03-25 17:25:34 +000041// FIXME: Remove ECOverride once Error has been plumbed down to obj tool code.
42static Error
43malformedError(std::string FileName, std::string Msg,
44 object_error ECOverride = object_error::parse_failed) {
45 return make_error<GenericBinaryError>(std::move(FileName), std::move(Msg),
46 ECOverride);
47}
48
Lang Hames9e964f32016-03-25 17:25:34 +000049// FIXME: Remove ECOverride once Error has been plumbed down to obj tool code.
50static Error
Kevin Enderby81e8b7d2016-04-20 21:24:34 +000051malformedError(const MachOObjectFile &Obj, Twine Msg,
Lang Hames9e964f32016-03-25 17:25:34 +000052 object_error ECOverride = object_error::parse_failed) {
Evgeniy Stepanov23834652016-04-20 22:44:40 +000053 return malformedError(Obj.getFileName(), Msg.str(), ECOverride);
Lang Hames9e964f32016-03-25 17:25:34 +000054}
55
Alexey Samsonov9f336632015-06-04 19:45:22 +000056// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000057template <typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000058static T getStruct(const MachOObjectFile *O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000059 // Don't read before the beginning or past the end of the file
60 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
61 report_fatal_error("Malformed MachO file.");
62
Rafael Espindola3cdeb172013-04-19 13:45:05 +000063 T Cmd;
64 memcpy(&Cmd, P, sizeof(T));
65 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000066 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000067 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000068}
69
Alexey Samsonov9f336632015-06-04 19:45:22 +000070template <typename T>
Lang Hames9e964f32016-03-25 17:25:34 +000071static Expected<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000072 // Don't read before the beginning or past the end of the file
73 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
Lang Hames9e964f32016-03-25 17:25:34 +000074 return malformedError(*O, "Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000075
76 T Cmd;
77 memcpy(&Cmd, P, sizeof(T));
78 if (O->isLittleEndian() != sys::IsLittleEndianHost)
79 MachO::swapStruct(Cmd);
80 return Cmd;
81}
82
Rafael Espindola6e040c02013-04-26 20:07:33 +000083static const char *
84getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
85 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000086 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
87
88 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000089 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
90 sizeof(MachO::segment_command);
91 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
92 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000093
94 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000095 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000096}
97
Rafael Espindola56f976f2013-04-18 18:08:55 +000098static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
99 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +0000100}
101
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000102static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +0000103getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +0000104 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000105 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +0000106}
107
Rafael Espindola56f976f2013-04-18 18:08:55 +0000108static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000109 if (P[15] == 0)
110 // Null terminated.
111 return P;
112 // Not null terminated, so this is a 16 char string.
113 return StringRef(P, 16);
114}
115
Rafael Espindola56f976f2013-04-18 18:08:55 +0000116// Helper to advance a section or symbol iterator multiple increments at a time.
117template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000118static void advance(T &it, size_t Val) {
119 while (Val--)
120 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000121}
122
123static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000124 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000125}
126
Charles Davis8bdfafd2013-09-01 04:28:48 +0000127static uint32_t
128getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
129 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000130}
131
132static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000133getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
134 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000135}
136
137static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000138 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000139 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000140 return (RE.r_word1 >> 24) & 1;
141 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000142}
143
144static bool
145getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000146 const MachO::any_relocation_info &RE) {
147 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000148}
149
150static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000151 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000152 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000153 return (RE.r_word1 >> 25) & 3;
154 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000155}
156
157static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000158getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
159 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000160}
161
162static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000163 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000164 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000165 return RE.r_word1 >> 28;
166 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000167}
168
Rafael Espindola56f976f2013-04-18 18:08:55 +0000169static uint32_t getSectionFlags(const MachOObjectFile *O,
170 DataRefImpl Sec) {
171 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000172 MachO::section_64 Sect = O->getSection64(Sec);
173 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000174 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000175 MachO::section Sect = O->getSection(Sec);
176 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000177}
178
Lang Hames9e964f32016-03-25 17:25:34 +0000179static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000180getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
Lang Hames9e964f32016-03-25 17:25:34 +0000181 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
182 if (CmdOrErr->cmdsize < 8)
183 return malformedError(*Obj, "Mach-O load command with size < 8 bytes",
184 object_error::macho_small_load_command);
185 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
186 } else
187 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000188}
189
Lang Hames9e964f32016-03-25 17:25:34 +0000190static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000191getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
192 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
193 : sizeof(MachO::mach_header);
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000194 if (sizeof(MachOObjectFile::LoadCommandInfo) > Obj->getHeader().sizeofcmds)
195 return malformedError(*Obj, "truncated or malformed object (load command "
196 "0 extends past the end all load commands in the "
197 "file)");
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000198 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
199}
200
Lang Hames9e964f32016-03-25 17:25:34 +0000201static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000202getNextLoadCommandInfo(const MachOObjectFile *Obj,
203 const MachOObjectFile::LoadCommandInfo &L) {
204 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
205}
206
Alexey Samsonov9f336632015-06-04 19:45:22 +0000207template <typename T>
208static void parseHeader(const MachOObjectFile *Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000209 Error &Err) {
Kevin Enderby87025742016-04-13 21:17:58 +0000210 if (sizeof(T) > Obj->getData().size()) {
211 Err = malformedError(*Obj, "truncated or malformed object (the mach header "
212 "extends past the end of the file)");
213 return;
214 }
Lang Hames9e964f32016-03-25 17:25:34 +0000215 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
216 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000217 else
Lang Hames9e964f32016-03-25 17:25:34 +0000218 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000219}
220
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000221// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
222// sections to \param Sections, and optionally sets
223// \param IsPageZeroSegment to true.
224template <typename SegmentCmd>
Lang Hames9e964f32016-03-25 17:25:34 +0000225static Error parseSegmentLoadCommand(
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000226 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
227 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
228 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
229 if (Load.C.cmdsize < SegmentLoadSize)
Lang Hames9e964f32016-03-25 17:25:34 +0000230 return malformedError(*Obj,
231 "Mach-O segment load command size is too small",
232 object_error::macho_load_segment_too_small);
233 if (auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr)) {
234 SegmentCmd S = SegOrErr.get();
235 const unsigned SectionSize =
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000236 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
Lang Hames9e964f32016-03-25 17:25:34 +0000237 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
238 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
239 return malformedError(*Obj,
240 "Mach-O segment load command contains too many "
241 "sections",
242 object_error::macho_load_segment_too_many_sections);
243 for (unsigned J = 0; J < S.nsects; ++J) {
244 const char *Sec = getSectionPtr(Obj, Load, J);
245 Sections.push_back(Sec);
246 }
247 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
248 } else
249 return SegOrErr.takeError();
250
251 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000252}
253
Lang Hames82627642016-03-25 21:59:14 +0000254Expected<std::unique_ptr<MachOObjectFile>>
255MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
256 bool Is64Bits) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000257 Error Err;
Lang Hames82627642016-03-25 21:59:14 +0000258 std::unique_ptr<MachOObjectFile> Obj(
259 new MachOObjectFile(std::move(Object), IsLittleEndian,
260 Is64Bits, Err));
261 if (Err)
262 return std::move(Err);
263 return std::move(Obj);
264}
265
Rafael Espindola48af1c22014-08-19 18:44:46 +0000266MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Lang Hames9e964f32016-03-25 17:25:34 +0000267 bool Is64bits, Error &Err)
Rafael Espindola48af1c22014-08-19 18:44:46 +0000268 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000269 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000270 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
271 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
272 HasPageZeroSegment(false) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000273 ErrorAsOutParameter ErrAsOutParam(Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000274 uint64_t BigSize;
Kevin Enderby87025742016-04-13 21:17:58 +0000275 if (is64Bit()) {
Lang Hames9e964f32016-03-25 17:25:34 +0000276 parseHeader(this, Header64, Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000277 BigSize = sizeof(MachO::mach_header_64);
Kevin Enderby87025742016-04-13 21:17:58 +0000278 } else {
Lang Hames9e964f32016-03-25 17:25:34 +0000279 parseHeader(this, Header, Err);
Kevin Enderby5e55d172016-04-21 20:29:49 +0000280 BigSize = sizeof(MachO::mach_header);
Kevin Enderby87025742016-04-13 21:17:58 +0000281 }
Lang Hames9e964f32016-03-25 17:25:34 +0000282 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +0000283 return;
Kevin Enderby5e55d172016-04-21 20:29:49 +0000284 BigSize += getHeader().sizeofcmds;
285 if (getData().data() + BigSize > getData().end()) {
Kevin Enderby87025742016-04-13 21:17:58 +0000286 Err = malformedError(getFileName(), "truncated or malformed object "
Kevin Enderby6e295f22016-04-21 21:20:40 +0000287 "(load commands extend past the end of the file)");
Kevin Enderby87025742016-04-13 21:17:58 +0000288 return;
289 }
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000290
291 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000292 if (LoadCommandCount == 0)
293 return;
294
Lang Hames9e964f32016-03-25 17:25:34 +0000295 LoadCommandInfo Load;
296 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
297 Load = *LoadOrErr;
298 else {
299 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000300 return;
301 }
Lang Hames9e964f32016-03-25 17:25:34 +0000302
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000303 for (unsigned I = 0; I < LoadCommandCount; ++I) {
304 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000305 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000306 // Multiple symbol tables
307 if (SymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000308 Err = malformedError(*this, "Multiple symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000309 return;
310 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000311 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000312 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000313 // Multiple dynamic symbol tables
314 if (DysymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000315 Err = malformedError(*this, "Multiple dynamic symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000316 return;
317 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000318 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000319 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000320 // Multiple data in code tables
321 if (DataInCodeLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000322 Err = malformedError(*this, "Multiple data-in-code tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000323 return;
324 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000325 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000326 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
327 // Multiple linker optimization hint tables
328 if (LinkOptHintsLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000329 Err = malformedError(*this, "Multiple linker optimization hint tables");
Kevin Enderby9a509442015-01-27 21:28:24 +0000330 return;
331 }
332 LinkOptHintsLoadCmd = Load.Ptr;
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +0000333 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Nick Kledzikd04bc352014-08-30 00:20:14 +0000334 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000335 // Multiple dyldinfo load commands
336 if (DyldInfoLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000337 Err = malformedError(*this, "Multiple dyldinfo load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000338 return;
339 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000340 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000341 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000342 // Multiple UUID load commands
343 if (UuidLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000344 Err = malformedError(*this, "Multiple UUID load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000345 return;
346 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000347 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000348 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Lang Hames9e964f32016-03-25 17:25:34 +0000349 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64>(
350 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000351 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000352 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Lang Hames9e964f32016-03-25 17:25:34 +0000353 if ((Err = parseSegmentLoadCommand<MachO::segment_command>(
354 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000355 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000356 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
357 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
358 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
359 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
360 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
361 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000362 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000363 if (I < LoadCommandCount - 1) {
Lang Hames9e964f32016-03-25 17:25:34 +0000364 if (auto LoadOrErr = getNextLoadCommandInfo(this, Load))
365 Load = *LoadOrErr;
366 else {
367 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000368 return;
369 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000370 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000371 }
Kevin Enderby1829c682016-01-22 22:49:55 +0000372 if (!SymtabLoadCmd) {
373 if (DysymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000374 Err = malformedError(*this,
375 "truncated or malformed object (contains "
376 "LC_DYSYMTAB load command without a LC_SYMTAB load "
377 "command)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000378 return;
379 }
380 } else if (DysymtabLoadCmd) {
381 MachO::symtab_command Symtab =
382 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
383 MachO::dysymtab_command Dysymtab =
384 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
385 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000386 Err = malformedError(*this,
387 "truncated or malformed object (iolocalsym in "
388 "LC_DYSYMTAB load command extends past the end of "
389 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000390 return;
391 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000392 uint64_t BigSize = Dysymtab.ilocalsym;
393 BigSize += Dysymtab.nlocalsym;
394 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000395 Err = malformedError(*this,
396 "truncated or malformed object (ilocalsym plus "
397 "nlocalsym in LC_DYSYMTAB load command extends past "
398 "the end of the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000399 return;
400 }
401 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000402 Err = malformedError(*this,
403 "truncated or malformed object (nextdefsym in "
404 "LC_DYSYMTAB load command extends past the end of "
405 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000406 return;
407 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000408 BigSize = Dysymtab.iextdefsym;
409 BigSize += Dysymtab.nextdefsym;
410 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000411 Err = malformedError(*this,
412 "truncated or malformed object (iextdefsym plus "
413 "nextdefsym in LC_DYSYMTAB load command extends "
414 "past the end of the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000415 return;
416 }
417 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000418 Err = malformedError(*this,
419 "truncated or malformed object (nundefsym in "
420 "LC_DYSYMTAB load command extends past the end of "
421 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000422 return;
423 }
Kevin Enderby5e55d172016-04-21 20:29:49 +0000424 BigSize = Dysymtab.iundefsym;
425 BigSize += Dysymtab.nundefsym;
426 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000427 Err = malformedError(*this,
428 "truncated or malformed object (iundefsym plus "
429 "nundefsym in LC_DYSYMTAB load command extends past "
430 "the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000431 return;
432 }
433 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000434 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +0000435
436 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000437}
438
Rafael Espindola5e812af2014-01-30 02:49:50 +0000439void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000440 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000441 sizeof(MachO::nlist_64) :
442 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000443 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000444}
445
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000446Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000447 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000448 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000449 const char *Start = &StringTable.data()[Entry.n_strx];
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000450 if (Start < getData().begin() || Start >= getData().end()) {
451 return malformedError(*this, Twine("truncated or malformed object (bad "
452 "string index: ") + Twine(Entry.n_strx) + Twine(" for "
453 "symbol at index ") + Twine(getSymbolIndex(Symb)) +
454 Twine(")"));
455 }
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000456 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000457}
458
Rafael Espindola0e77a942014-12-10 20:46:55 +0000459unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
460 DataRefImpl DRI = Sec.getRawDataRefImpl();
461 uint32_t Flags = getSectionFlags(this, DRI);
462 return Flags & MachO::SECTION_TYPE;
463}
464
Rafael Espindola59128922015-06-24 18:14:41 +0000465uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
466 if (is64Bit()) {
467 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
468 return Entry.n_value;
469 }
470 MachO::nlist Entry = getSymbolTableEntry(Sym);
471 return Entry.n_value;
472}
473
Kevin Enderby980b2582014-06-05 21:21:57 +0000474// getIndirectName() returns the name of the alias'ed symbol who's string table
475// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000476std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
477 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000478 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000479 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
480 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
481 return object_error::parse_failed;
482 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000483 if (NValue >= StringTable.size())
484 return object_error::parse_failed;
485 const char *Start = &StringTable.data()[NValue];
486 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000487 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000488}
489
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +0000490uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +0000491 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +0000492}
493
Rafael Espindolaed067c42015-07-03 18:19:00 +0000494ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
495 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000496}
497
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000498uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000499 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000500 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000501 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000502 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000503 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000504 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000505}
506
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000507uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000508 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000509}
510
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000511Expected<SymbolRef::Type>
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000512MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000513 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000514 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000515
Rafael Espindola56f976f2013-04-18 18:08:55 +0000516 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000517 if (n_type & MachO::N_STAB)
518 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000519
Charles Davis74ec8b02013-08-27 05:00:13 +0000520 switch (n_type & MachO::N_TYPE) {
521 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000522 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +0000523 case MachO::N_SECT :
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000524 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000525 if (!SecOrError)
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000526 return SecOrError.takeError();
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000527 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +0000528 if (Sec->isData() || Sec->isBSS())
529 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000530 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000531 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000532 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000533}
534
Rafael Espindola20122a42014-01-31 20:57:12 +0000535uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000536 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000537
Charles Davis8bdfafd2013-09-01 04:28:48 +0000538 uint8_t MachOType = Entry.n_type;
539 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000540
Rafael Espindola20122a42014-01-31 20:57:12 +0000541 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000542
Tim Northovereaef0742014-05-30 13:22:59 +0000543 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
544 Result |= SymbolRef::SF_Indirect;
545
Rafael Espindolaa1356322013-11-02 05:03:24 +0000546 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000547 Result |= SymbolRef::SF_FormatSpecific;
548
Charles Davis74ec8b02013-08-27 05:00:13 +0000549 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000550 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000551 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000552 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000553 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +0000554 else
555 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000556 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000557
558 if (!(MachOType & MachO::N_PEXT))
559 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000560 }
561
Charles Davis74ec8b02013-08-27 05:00:13 +0000562 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000563 Result |= SymbolRef::SF_Weak;
564
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000565 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
566 Result |= SymbolRef::SF_Thumb;
567
Charles Davis74ec8b02013-08-27 05:00:13 +0000568 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000569 Result |= SymbolRef::SF_Absolute;
570
Rafael Espindola20122a42014-01-31 20:57:12 +0000571 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000572}
573
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000574Expected<section_iterator>
Rafael Espindola8bab8892015-08-07 23:27:14 +0000575MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000576 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000577 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000578
Rafael Espindola8bab8892015-08-07 23:27:14 +0000579 if (index == 0)
580 return section_end();
581 DataRefImpl DRI;
582 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000583 if (DRI.d.a >= Sections.size()){
Kevin Enderby7bd8d992016-05-02 20:28:12 +0000584 return malformedError(*this, Twine("truncated or malformed object (bad "
585 "section index: ") + Twine((int)index) + Twine(" for "
586 "symbol at index ") + Twine(getSymbolIndex(Symb)) +
587 Twine(")"));
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000588 }
Rafael Espindola8bab8892015-08-07 23:27:14 +0000589 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000590}
591
Rafael Espindola6bf32212015-06-24 19:57:32 +0000592unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
593 MachO::nlist_base Entry =
594 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
595 return Entry.n_sect - 1;
596}
597
Rafael Espindola5e812af2014-01-30 02:49:50 +0000598void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000599 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000600}
601
Rafael Espindola3acea392014-06-12 21:46:39 +0000602std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
603 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000604 ArrayRef<char> Raw = getSectionRawName(Sec);
605 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000606 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000607}
608
Rafael Espindola80291272014-10-08 15:28:58 +0000609uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
610 if (is64Bit())
611 return getSection64(Sec).addr;
612 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000613}
614
Rafael Espindola80291272014-10-08 15:28:58 +0000615uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +0000616 // In the case if a malformed Mach-O file where the section offset is past
617 // the end of the file or some part of the section size is past the end of
618 // the file return a size of zero or a size that covers the rest of the file
619 // but does not extend past the end of the file.
620 uint32_t SectOffset, SectType;
621 uint64_t SectSize;
622
623 if (is64Bit()) {
624 MachO::section_64 Sect = getSection64(Sec);
625 SectOffset = Sect.offset;
626 SectSize = Sect.size;
627 SectType = Sect.flags & MachO::SECTION_TYPE;
628 } else {
629 MachO::section Sect = getSection(Sec);
630 SectOffset = Sect.offset;
631 SectSize = Sect.size;
632 SectType = Sect.flags & MachO::SECTION_TYPE;
633 }
634 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
635 return SectSize;
636 uint64_t FileSize = getData().size();
637 if (SectOffset > FileSize)
638 return 0;
639 if (FileSize - SectOffset < SectSize)
640 return FileSize - SectOffset;
641 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000642}
643
Rafael Espindola3acea392014-06-12 21:46:39 +0000644std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
645 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000646 uint32_t Offset;
647 uint64_t Size;
648
649 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000650 MachO::section_64 Sect = getSection64(Sec);
651 Offset = Sect.offset;
652 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000653 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000654 MachO::section Sect = getSection(Sec);
655 Offset = Sect.offset;
656 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000657 }
658
659 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000660 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000661}
662
Rafael Espindola80291272014-10-08 15:28:58 +0000663uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000664 uint32_t Align;
665 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000666 MachO::section_64 Sect = getSection64(Sec);
667 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000668 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000669 MachO::section Sect = getSection(Sec);
670 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000671 }
672
Rafael Espindola80291272014-10-08 15:28:58 +0000673 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000674}
675
Rafael Espindola80291272014-10-08 15:28:58 +0000676bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000677 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000678 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000679}
680
Rafael Espindola80291272014-10-08 15:28:58 +0000681bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000682 uint32_t Flags = getSectionFlags(this, Sec);
683 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000684 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
685 !(SectionType == MachO::S_ZEROFILL ||
686 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000687}
688
Rafael Espindola80291272014-10-08 15:28:58 +0000689bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000690 uint32_t Flags = getSectionFlags(this, Sec);
691 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000692 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
693 (SectionType == MachO::S_ZEROFILL ||
694 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000695}
696
Rafael Espindola6bf32212015-06-24 19:57:32 +0000697unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
698 return Sec.getRawDataRefImpl().d.a;
699}
700
Rafael Espindola80291272014-10-08 15:28:58 +0000701bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000702 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000703 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000704}
705
Steven Wuf2fe0142016-02-29 19:40:10 +0000706bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
707 StringRef SegmentName = getSectionFinalSegmentName(Sec);
708 StringRef SectName;
709 if (!getSectionName(Sec, SectName))
710 return (SegmentName == "__LLVM" && SectName == "__bitcode");
711 return false;
712}
713
Rui Ueyamabc654b12013-09-27 21:47:05 +0000714relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000715 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000716 Ret.d.a = Sec.d.a;
717 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000718 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000719}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000720
Rafael Espindola56f976f2013-04-18 18:08:55 +0000721relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000722MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000723 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000724 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000725 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000726 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000727 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000728 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000729 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000730 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000731
Rafael Espindola56f976f2013-04-18 18:08:55 +0000732 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000733 Ret.d.a = Sec.d.a;
734 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000735 return relocation_iterator(RelocationRef(Ret, this));
736}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000737
Rafael Espindola5e812af2014-01-30 02:49:50 +0000738void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000739 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000740}
Owen Anderson171f4852011-10-24 23:20:07 +0000741
Rafael Espindola96d071c2015-06-29 23:29:12 +0000742uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000743 assert(getHeader().filetype == MachO::MH_OBJECT &&
744 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000745 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000746 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +0000747}
748
Rafael Espindola806f0062013-06-05 01:33:53 +0000749symbol_iterator
750MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000751 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000752 if (isRelocationScattered(RE))
753 return symbol_end();
754
Rafael Espindola56f976f2013-04-18 18:08:55 +0000755 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
756 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000757 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000758 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000759
Charles Davis8bdfafd2013-09-01 04:28:48 +0000760 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000761 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000762 sizeof(MachO::nlist_64) :
763 sizeof(MachO::nlist);
764 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000765 DataRefImpl Sym;
766 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000767 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000768}
769
Keno Fischerc780e8e2015-05-21 21:24:32 +0000770section_iterator
771MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
772 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
773}
774
Rafael Espindola99c041b2015-06-30 01:53:01 +0000775uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000776 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +0000777 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000778}
779
Rafael Espindola41bb4322015-06-30 04:08:37 +0000780void MachOObjectFile::getRelocationTypeName(
781 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000782 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +0000783 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000784
785 unsigned Arch = this->getArch();
786
787 switch (Arch) {
788 case Triple::x86: {
789 static const char *const Table[] = {
790 "GENERIC_RELOC_VANILLA",
791 "GENERIC_RELOC_PAIR",
792 "GENERIC_RELOC_SECTDIFF",
793 "GENERIC_RELOC_PB_LA_PTR",
794 "GENERIC_RELOC_LOCAL_SECTDIFF",
795 "GENERIC_RELOC_TLV" };
796
Eric Christopher13250cb2013-12-06 02:33:38 +0000797 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000798 res = "Unknown";
799 else
800 res = Table[RType];
801 break;
802 }
803 case Triple::x86_64: {
804 static const char *const Table[] = {
805 "X86_64_RELOC_UNSIGNED",
806 "X86_64_RELOC_SIGNED",
807 "X86_64_RELOC_BRANCH",
808 "X86_64_RELOC_GOT_LOAD",
809 "X86_64_RELOC_GOT",
810 "X86_64_RELOC_SUBTRACTOR",
811 "X86_64_RELOC_SIGNED_1",
812 "X86_64_RELOC_SIGNED_2",
813 "X86_64_RELOC_SIGNED_4",
814 "X86_64_RELOC_TLV" };
815
816 if (RType > 9)
817 res = "Unknown";
818 else
819 res = Table[RType];
820 break;
821 }
822 case Triple::arm: {
823 static const char *const Table[] = {
824 "ARM_RELOC_VANILLA",
825 "ARM_RELOC_PAIR",
826 "ARM_RELOC_SECTDIFF",
827 "ARM_RELOC_LOCAL_SECTDIFF",
828 "ARM_RELOC_PB_LA_PTR",
829 "ARM_RELOC_BR24",
830 "ARM_THUMB_RELOC_BR22",
831 "ARM_THUMB_32BIT_BRANCH",
832 "ARM_RELOC_HALF",
833 "ARM_RELOC_HALF_SECTDIFF" };
834
835 if (RType > 9)
836 res = "Unknown";
837 else
838 res = Table[RType];
839 break;
840 }
Tim Northover00ed9962014-03-29 10:18:08 +0000841 case Triple::aarch64: {
842 static const char *const Table[] = {
843 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
844 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
845 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
846 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
847 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
848 "ARM64_RELOC_ADDEND"
849 };
850
851 if (RType >= array_lengthof(Table))
852 res = "Unknown";
853 else
854 res = Table[RType];
855 break;
856 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000857 case Triple::ppc: {
858 static const char *const Table[] = {
859 "PPC_RELOC_VANILLA",
860 "PPC_RELOC_PAIR",
861 "PPC_RELOC_BR14",
862 "PPC_RELOC_BR24",
863 "PPC_RELOC_HI16",
864 "PPC_RELOC_LO16",
865 "PPC_RELOC_HA16",
866 "PPC_RELOC_LO14",
867 "PPC_RELOC_SECTDIFF",
868 "PPC_RELOC_PB_LA_PTR",
869 "PPC_RELOC_HI16_SECTDIFF",
870 "PPC_RELOC_LO16_SECTDIFF",
871 "PPC_RELOC_HA16_SECTDIFF",
872 "PPC_RELOC_JBSR",
873 "PPC_RELOC_LO14_SECTDIFF",
874 "PPC_RELOC_LOCAL_SECTDIFF" };
875
Eric Christopher13250cb2013-12-06 02:33:38 +0000876 if (RType > 15)
877 res = "Unknown";
878 else
879 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000880 break;
881 }
882 case Triple::UnknownArch:
883 res = "Unknown";
884 break;
885 }
886 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +0000887}
888
Keno Fischer281b6942015-05-30 19:44:53 +0000889uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
890 MachO::any_relocation_info RE = getRelocation(Rel);
891 return getAnyRelocationLength(RE);
892}
893
Kevin Enderby980b2582014-06-05 21:21:57 +0000894//
895// guessLibraryShortName() is passed a name of a dynamic library and returns a
896// guess on what the short name is. Then name is returned as a substring of the
897// StringRef Name passed in. The name of the dynamic library is recognized as
898// a framework if it has one of the two following forms:
899// Foo.framework/Versions/A/Foo
900// Foo.framework/Foo
901// Where A and Foo can be any string. And may contain a trailing suffix
902// starting with an underbar. If the Name is recognized as a framework then
903// isFramework is set to true else it is set to false. If the Name has a
904// suffix then Suffix is set to the substring in Name that contains the suffix
905// else it is set to a NULL StringRef.
906//
907// The Name of the dynamic library is recognized as a library name if it has
908// one of the two following forms:
909// libFoo.A.dylib
910// libFoo.dylib
911// The library may have a suffix trailing the name Foo of the form:
912// libFoo_profile.A.dylib
913// libFoo_profile.dylib
914//
915// The Name of the dynamic library is also recognized as a library name if it
916// has the following form:
917// Foo.qtx
918//
919// If the Name of the dynamic library is none of the forms above then a NULL
920// StringRef is returned.
921//
922StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
923 bool &isFramework,
924 StringRef &Suffix) {
925 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
926 size_t a, b, c, d, Idx;
927
928 isFramework = false;
929 Suffix = StringRef();
930
931 // Pull off the last component and make Foo point to it
932 a = Name.rfind('/');
933 if (a == Name.npos || a == 0)
934 goto guess_library;
935 Foo = Name.slice(a+1, Name.npos);
936
937 // Look for a suffix starting with a '_'
938 Idx = Foo.rfind('_');
939 if (Idx != Foo.npos && Foo.size() >= 2) {
940 Suffix = Foo.slice(Idx, Foo.npos);
941 Foo = Foo.slice(0, Idx);
942 }
943
944 // First look for the form Foo.framework/Foo
945 b = Name.rfind('/', a);
946 if (b == Name.npos)
947 Idx = 0;
948 else
949 Idx = b+1;
950 F = Name.slice(Idx, Idx + Foo.size());
951 DotFramework = Name.slice(Idx + Foo.size(),
952 Idx + Foo.size() + sizeof(".framework/")-1);
953 if (F == Foo && DotFramework == ".framework/") {
954 isFramework = true;
955 return Foo;
956 }
957
958 // Next look for the form Foo.framework/Versions/A/Foo
959 if (b == Name.npos)
960 goto guess_library;
961 c = Name.rfind('/', b);
962 if (c == Name.npos || c == 0)
963 goto guess_library;
964 V = Name.slice(c+1, Name.npos);
965 if (!V.startswith("Versions/"))
966 goto guess_library;
967 d = Name.rfind('/', c);
968 if (d == Name.npos)
969 Idx = 0;
970 else
971 Idx = d+1;
972 F = Name.slice(Idx, Idx + Foo.size());
973 DotFramework = Name.slice(Idx + Foo.size(),
974 Idx + Foo.size() + sizeof(".framework/")-1);
975 if (F == Foo && DotFramework == ".framework/") {
976 isFramework = true;
977 return Foo;
978 }
979
980guess_library:
981 // pull off the suffix after the "." and make a point to it
982 a = Name.rfind('.');
983 if (a == Name.npos || a == 0)
984 return StringRef();
985 Dylib = Name.slice(a, Name.npos);
986 if (Dylib != ".dylib")
987 goto guess_qtx;
988
989 // First pull off the version letter for the form Foo.A.dylib if any.
990 if (a >= 3) {
991 Dot = Name.slice(a-2, a-1);
992 if (Dot == ".")
993 a = a - 2;
994 }
995
996 b = Name.rfind('/', a);
997 if (b == Name.npos)
998 b = 0;
999 else
1000 b = b+1;
1001 // ignore any suffix after an underbar like Foo_profile.A.dylib
1002 Idx = Name.find('_', b);
1003 if (Idx != Name.npos && Idx != b) {
1004 Lib = Name.slice(b, Idx);
1005 Suffix = Name.slice(Idx, a);
1006 }
1007 else
1008 Lib = Name.slice(b, a);
1009 // There are incorrect library names of the form:
1010 // libATS.A_profile.dylib so check for these.
1011 if (Lib.size() >= 3) {
1012 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1013 if (Dot == ".")
1014 Lib = Lib.slice(0, Lib.size()-2);
1015 }
1016 return Lib;
1017
1018guess_qtx:
1019 Qtx = Name.slice(a, Name.npos);
1020 if (Qtx != ".qtx")
1021 return StringRef();
1022 b = Name.rfind('/', a);
1023 if (b == Name.npos)
1024 Lib = Name.slice(0, a);
1025 else
1026 Lib = Name.slice(b+1, a);
1027 // There are library names of the form: QT.A.qtx so check for these.
1028 if (Lib.size() >= 3) {
1029 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1030 if (Dot == ".")
1031 Lib = Lib.slice(0, Lib.size()-2);
1032 }
1033 return Lib;
1034}
1035
1036// getLibraryShortNameByIndex() is used to get the short name of the library
1037// for an undefined symbol in a linked Mach-O binary that was linked with the
1038// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1039// It is passed the index (0 - based) of the library as translated from
1040// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001041std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001042 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001043 if (Index >= Libraries.size())
1044 return object_error::parse_failed;
1045
Kevin Enderby980b2582014-06-05 21:21:57 +00001046 // If the cache of LibrariesShortNames is not built up do that first for
1047 // all the Libraries.
1048 if (LibrariesShortNames.size() == 0) {
1049 for (unsigned i = 0; i < Libraries.size(); i++) {
1050 MachO::dylib_command D =
1051 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001052 if (D.dylib.name >= D.cmdsize)
1053 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001054 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001055 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001056 if (D.dylib.name+Name.size() >= D.cmdsize)
1057 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001058 StringRef Suffix;
1059 bool isFramework;
1060 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001061 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001062 LibrariesShortNames.push_back(Name);
1063 else
1064 LibrariesShortNames.push_back(shortName);
1065 }
1066 }
1067
1068 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00001069 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001070}
1071
Rafael Espindola76ad2322015-07-06 14:55:37 +00001072section_iterator
1073MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
1074 DataRefImpl Sec;
1075 Sec.d.a = Rel->getRawDataRefImpl().d.a;
1076 return section_iterator(SectionRef(Sec, this));
1077}
1078
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001079basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00001080 DataRefImpl DRI;
1081 MachO::symtab_command Symtab = getSymtabLoadCommand();
1082 if (!SymtabLoadCmd || Symtab.nsyms == 0)
1083 return basic_symbol_iterator(SymbolRef(DRI, this));
1084
Lang Hames36072da2014-05-12 21:39:59 +00001085 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001086}
1087
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001088basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001089 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00001090 MachO::symtab_command Symtab = getSymtabLoadCommand();
1091 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001092 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001093
Rafael Espindola75c30362013-04-24 19:47:55 +00001094 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001095 sizeof(MachO::nlist_64) :
1096 sizeof(MachO::nlist);
1097 unsigned Offset = Symtab.symoff +
1098 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001099 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001100 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001101}
1102
Lang Hames36072da2014-05-12 21:39:59 +00001103basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00001104 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00001105 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001106 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001107 unsigned SymbolTableEntrySize =
1108 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00001109 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00001110 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1111 DRI.p += Index * SymbolTableEntrySize;
1112 return basic_symbol_iterator(SymbolRef(DRI, this));
1113}
1114
Kevin Enderby81e8b7d2016-04-20 21:24:34 +00001115uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
1116 MachO::symtab_command Symtab = getSymtabLoadCommand();
1117 if (!SymtabLoadCmd)
1118 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
1119 unsigned SymbolTableEntrySize =
1120 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1121 DataRefImpl DRIstart;
1122 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1123 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
1124 return Index;
1125}
1126
Rafael Espindolab5155a52014-02-10 20:24:04 +00001127section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001128 DataRefImpl DRI;
1129 return section_iterator(SectionRef(DRI, this));
1130}
1131
Rafael Espindolab5155a52014-02-10 20:24:04 +00001132section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001133 DataRefImpl DRI;
1134 DRI.d.a = Sections.size();
1135 return section_iterator(SectionRef(DRI, this));
1136}
1137
Rafael Espindola56f976f2013-04-18 18:08:55 +00001138uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001139 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001140}
1141
Rafael Espindola56f976f2013-04-18 18:08:55 +00001142StringRef MachOObjectFile::getFileFormatName() const {
1143 unsigned CPUType = getCPUType(this);
1144 if (!is64Bit()) {
1145 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001146 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001147 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001148 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001149 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001150 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001151 return "Mach-O 32-bit ppc";
1152 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001153 return "Mach-O 32-bit unknown";
1154 }
1155 }
1156
Rafael Espindola56f976f2013-04-18 18:08:55 +00001157 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001158 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001159 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001160 case llvm::MachO::CPU_TYPE_ARM64:
1161 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001162 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001163 return "Mach-O 64-bit ppc64";
1164 default:
1165 return "Mach-O 64-bit unknown";
1166 }
1167}
1168
Alexey Samsonove6388e62013-06-18 15:03:28 +00001169Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1170 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001171 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001172 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001173 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001174 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001175 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001176 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001177 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001178 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001179 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001180 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001181 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001182 return Triple::ppc64;
1183 default:
1184 return Triple::UnknownArch;
1185 }
1186}
1187
Tim Northover9e8eb412016-04-22 23:21:13 +00001188Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
1189 const char **McpuDefault) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001190 if (McpuDefault)
1191 *McpuDefault = nullptr;
1192
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001193 switch (CPUType) {
1194 case MachO::CPU_TYPE_I386:
1195 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1196 case MachO::CPU_SUBTYPE_I386_ALL:
1197 return Triple("i386-apple-darwin");
1198 default:
1199 return Triple();
1200 }
1201 case MachO::CPU_TYPE_X86_64:
1202 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1203 case MachO::CPU_SUBTYPE_X86_64_ALL:
1204 return Triple("x86_64-apple-darwin");
1205 case MachO::CPU_SUBTYPE_X86_64_H:
1206 return Triple("x86_64h-apple-darwin");
1207 default:
1208 return Triple();
1209 }
1210 case MachO::CPU_TYPE_ARM:
1211 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1212 case MachO::CPU_SUBTYPE_ARM_V4T:
1213 return Triple("armv4t-apple-darwin");
1214 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1215 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001216 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1217 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001218 case MachO::CPU_SUBTYPE_ARM_V6:
1219 return Triple("armv6-apple-darwin");
1220 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001221 if (McpuDefault)
1222 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001223 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001224 case MachO::CPU_SUBTYPE_ARM_V7:
1225 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001226 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001227 if (McpuDefault)
1228 *McpuDefault = "cortex-m4";
Tim Northover9e8eb412016-04-22 23:21:13 +00001229 return Triple("thumbv7em-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001230 case MachO::CPU_SUBTYPE_ARM_V7K:
1231 return Triple("armv7k-apple-darwin");
1232 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001233 if (McpuDefault)
1234 *McpuDefault = "cortex-m3";
Tim Northover9e8eb412016-04-22 23:21:13 +00001235 return Triple("thumbv7m-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001236 case MachO::CPU_SUBTYPE_ARM_V7S:
1237 return Triple("armv7s-apple-darwin");
1238 default:
1239 return Triple();
1240 }
1241 case MachO::CPU_TYPE_ARM64:
1242 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1243 case MachO::CPU_SUBTYPE_ARM64_ALL:
1244 return Triple("arm64-apple-darwin");
1245 default:
1246 return Triple();
1247 }
1248 case MachO::CPU_TYPE_POWERPC:
1249 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1250 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1251 return Triple("ppc-apple-darwin");
1252 default:
1253 return Triple();
1254 }
1255 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001256 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001257 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1258 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001259 default:
1260 return Triple();
1261 }
1262 default:
1263 return Triple();
1264 }
1265}
1266
1267Triple MachOObjectFile::getHostArch() {
1268 return Triple(sys::getDefaultTargetTriple());
1269}
1270
Rafael Espindola72318b42014-08-08 16:30:17 +00001271bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1272 return StringSwitch<bool>(ArchFlag)
1273 .Case("i386", true)
1274 .Case("x86_64", true)
1275 .Case("x86_64h", true)
1276 .Case("armv4t", true)
1277 .Case("arm", true)
1278 .Case("armv5e", true)
1279 .Case("armv6", true)
1280 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001281 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001282 .Case("armv7em", true)
1283 .Case("armv7k", true)
1284 .Case("armv7m", true)
1285 .Case("armv7s", true)
1286 .Case("arm64", true)
1287 .Case("ppc", true)
1288 .Case("ppc64", true)
1289 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001290}
1291
Alexey Samsonove6388e62013-06-18 15:03:28 +00001292unsigned MachOObjectFile::getArch() const {
1293 return getArch(getCPUType(this));
1294}
1295
Tim Northover9e8eb412016-04-22 23:21:13 +00001296Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
1297 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001298}
1299
Rui Ueyamabc654b12013-09-27 21:47:05 +00001300relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001301 DataRefImpl DRI;
1302 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001303 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001304}
1305
Rui Ueyamabc654b12013-09-27 21:47:05 +00001306relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001307 DataRefImpl DRI;
1308 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001309 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001310}
1311
Kevin Enderby273ae012013-06-06 17:20:50 +00001312dice_iterator MachOObjectFile::begin_dices() const {
1313 DataRefImpl DRI;
1314 if (!DataInCodeLoadCmd)
1315 return dice_iterator(DiceRef(DRI, this));
1316
Charles Davis8bdfafd2013-09-01 04:28:48 +00001317 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1318 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001319 return dice_iterator(DiceRef(DRI, this));
1320}
1321
1322dice_iterator MachOObjectFile::end_dices() const {
1323 DataRefImpl DRI;
1324 if (!DataInCodeLoadCmd)
1325 return dice_iterator(DiceRef(DRI, this));
1326
Charles Davis8bdfafd2013-09-01 04:28:48 +00001327 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1328 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001329 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1330 return dice_iterator(DiceRef(DRI, this));
1331}
1332
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001333ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1334 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001335
1336void ExportEntry::moveToFirst() {
1337 pushNode(0);
1338 pushDownUntilBottom();
1339}
1340
1341void ExportEntry::moveToEnd() {
1342 Stack.clear();
1343 Done = true;
1344}
1345
1346bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001347 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001348 if (Done || Other.Done)
1349 return (Done == Other.Done);
1350 // Not equal if different stack sizes.
1351 if (Stack.size() != Other.Stack.size())
1352 return false;
1353 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001354 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001355 return false;
1356 // Equal if all nodes in both stacks match.
1357 for (unsigned i=0; i < Stack.size(); ++i) {
1358 if (Stack[i].Start != Other.Stack[i].Start)
1359 return false;
1360 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001361 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001362}
1363
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001364uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1365 unsigned Count;
1366 uint64_t Result = decodeULEB128(Ptr, &Count);
1367 Ptr += Count;
1368 if (Ptr > Trie.end()) {
1369 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001370 Malformed = true;
1371 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001372 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001373}
1374
1375StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001376 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001377}
1378
1379uint64_t ExportEntry::flags() const {
1380 return Stack.back().Flags;
1381}
1382
1383uint64_t ExportEntry::address() const {
1384 return Stack.back().Address;
1385}
1386
1387uint64_t ExportEntry::other() const {
1388 return Stack.back().Other;
1389}
1390
1391StringRef ExportEntry::otherName() const {
1392 const char* ImportName = Stack.back().ImportName;
1393 if (ImportName)
1394 return StringRef(ImportName);
1395 return StringRef();
1396}
1397
1398uint32_t ExportEntry::nodeOffset() const {
1399 return Stack.back().Start - Trie.begin();
1400}
1401
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001402ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1403 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1404 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1405 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001406
1407void ExportEntry::pushNode(uint64_t offset) {
1408 const uint8_t *Ptr = Trie.begin() + offset;
1409 NodeState State(Ptr);
1410 uint64_t ExportInfoSize = readULEB128(State.Current);
1411 State.IsExportNode = (ExportInfoSize != 0);
1412 const uint8_t* Children = State.Current + ExportInfoSize;
1413 if (State.IsExportNode) {
1414 State.Flags = readULEB128(State.Current);
1415 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1416 State.Address = 0;
1417 State.Other = readULEB128(State.Current); // dylib ordinal
1418 State.ImportName = reinterpret_cast<const char*>(State.Current);
1419 } else {
1420 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001421 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001422 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001423 }
1424 }
1425 State.ChildCount = *Children;
1426 State.Current = Children + 1;
1427 State.NextChildIndex = 0;
1428 State.ParentStringLength = CumulativeString.size();
1429 Stack.push_back(State);
1430}
1431
1432void ExportEntry::pushDownUntilBottom() {
1433 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1434 NodeState &Top = Stack.back();
1435 CumulativeString.resize(Top.ParentStringLength);
1436 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001437 char C = *Top.Current;
1438 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001439 }
1440 Top.Current += 1;
1441 uint64_t childNodeIndex = readULEB128(Top.Current);
1442 Top.NextChildIndex += 1;
1443 pushNode(childNodeIndex);
1444 }
1445 if (!Stack.back().IsExportNode) {
1446 Malformed = true;
1447 moveToEnd();
1448 }
1449}
1450
1451// We have a trie data structure and need a way to walk it that is compatible
1452// with the C++ iterator model. The solution is a non-recursive depth first
1453// traversal where the iterator contains a stack of parent nodes along with a
1454// string that is the accumulation of all edge strings along the parent chain
1455// to this point.
1456//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001457// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001458// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001459// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001460//
1461// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1462// child until hitting a node with no children (which is an export node or
1463// else the trie is malformed). On the way down, each node is pushed on the
1464// stack ivar. If there is no more ways down, it pops up one and tries to go
1465// down a sibling path until a childless node is reached.
1466void ExportEntry::moveNext() {
1467 if (Stack.empty() || !Stack.back().IsExportNode) {
1468 Malformed = true;
1469 moveToEnd();
1470 return;
1471 }
1472
1473 Stack.pop_back();
1474 while (!Stack.empty()) {
1475 NodeState &Top = Stack.back();
1476 if (Top.NextChildIndex < Top.ChildCount) {
1477 pushDownUntilBottom();
1478 // Now at the next export node.
1479 return;
1480 } else {
1481 if (Top.IsExportNode) {
1482 // This node has no children but is itself an export node.
1483 CumulativeString.resize(Top.ParentStringLength);
1484 return;
1485 }
1486 Stack.pop_back();
1487 }
1488 }
1489 Done = true;
1490}
1491
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001492iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00001493MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1494 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001495 if (Trie.size() == 0)
1496 Start.moveToEnd();
1497 else
1498 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001499
1500 ExportEntry Finish(Trie);
1501 Finish.moveToEnd();
1502
Craig Topper15576e12015-12-06 05:08:07 +00001503 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00001504}
1505
1506iterator_range<export_iterator> MachOObjectFile::exports() const {
1507 return exports(getDyldInfoExportsTrie());
1508}
1509
Nick Kledzikac431442014-09-12 21:34:15 +00001510MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1511 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1512 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1513 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1514
1515void MachORebaseEntry::moveToFirst() {
1516 Ptr = Opcodes.begin();
1517 moveNext();
1518}
1519
1520void MachORebaseEntry::moveToEnd() {
1521 Ptr = Opcodes.end();
1522 RemainingLoopCount = 0;
1523 Done = true;
1524}
1525
1526void MachORebaseEntry::moveNext() {
1527 // If in the middle of some loop, move to next rebasing in loop.
1528 SegmentOffset += AdvanceAmount;
1529 if (RemainingLoopCount) {
1530 --RemainingLoopCount;
1531 return;
1532 }
1533 if (Ptr == Opcodes.end()) {
1534 Done = true;
1535 return;
1536 }
1537 bool More = true;
1538 while (More && !Malformed) {
1539 // Parse next opcode and set up next loop.
1540 uint8_t Byte = *Ptr++;
1541 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1542 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1543 switch (Opcode) {
1544 case MachO::REBASE_OPCODE_DONE:
1545 More = false;
1546 Done = true;
1547 moveToEnd();
1548 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1549 break;
1550 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1551 RebaseType = ImmValue;
1552 DEBUG_WITH_TYPE(
1553 "mach-o-rebase",
1554 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1555 << "RebaseType=" << (int) RebaseType << "\n");
1556 break;
1557 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1558 SegmentIndex = ImmValue;
1559 SegmentOffset = readULEB128();
1560 DEBUG_WITH_TYPE(
1561 "mach-o-rebase",
1562 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1563 << "SegmentIndex=" << SegmentIndex << ", "
1564 << format("SegmentOffset=0x%06X", SegmentOffset)
1565 << "\n");
1566 break;
1567 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1568 SegmentOffset += readULEB128();
1569 DEBUG_WITH_TYPE("mach-o-rebase",
1570 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1571 << format("SegmentOffset=0x%06X",
1572 SegmentOffset) << "\n");
1573 break;
1574 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1575 SegmentOffset += ImmValue * PointerSize;
1576 DEBUG_WITH_TYPE("mach-o-rebase",
1577 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1578 << format("SegmentOffset=0x%06X",
1579 SegmentOffset) << "\n");
1580 break;
1581 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1582 AdvanceAmount = PointerSize;
1583 RemainingLoopCount = ImmValue - 1;
1584 DEBUG_WITH_TYPE(
1585 "mach-o-rebase",
1586 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1587 << format("SegmentOffset=0x%06X", SegmentOffset)
1588 << ", AdvanceAmount=" << AdvanceAmount
1589 << ", RemainingLoopCount=" << RemainingLoopCount
1590 << "\n");
1591 return;
1592 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1593 AdvanceAmount = PointerSize;
1594 RemainingLoopCount = readULEB128() - 1;
1595 DEBUG_WITH_TYPE(
1596 "mach-o-rebase",
1597 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1598 << format("SegmentOffset=0x%06X", SegmentOffset)
1599 << ", AdvanceAmount=" << AdvanceAmount
1600 << ", RemainingLoopCount=" << RemainingLoopCount
1601 << "\n");
1602 return;
1603 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1604 AdvanceAmount = readULEB128() + PointerSize;
1605 RemainingLoopCount = 0;
1606 DEBUG_WITH_TYPE(
1607 "mach-o-rebase",
1608 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1609 << format("SegmentOffset=0x%06X", SegmentOffset)
1610 << ", AdvanceAmount=" << AdvanceAmount
1611 << ", RemainingLoopCount=" << RemainingLoopCount
1612 << "\n");
1613 return;
1614 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1615 RemainingLoopCount = readULEB128() - 1;
1616 AdvanceAmount = readULEB128() + PointerSize;
1617 DEBUG_WITH_TYPE(
1618 "mach-o-rebase",
1619 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1620 << format("SegmentOffset=0x%06X", SegmentOffset)
1621 << ", AdvanceAmount=" << AdvanceAmount
1622 << ", RemainingLoopCount=" << RemainingLoopCount
1623 << "\n");
1624 return;
1625 default:
1626 Malformed = true;
1627 }
1628 }
1629}
1630
1631uint64_t MachORebaseEntry::readULEB128() {
1632 unsigned Count;
1633 uint64_t Result = decodeULEB128(Ptr, &Count);
1634 Ptr += Count;
1635 if (Ptr > Opcodes.end()) {
1636 Ptr = Opcodes.end();
1637 Malformed = true;
1638 }
1639 return Result;
1640}
1641
1642uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1643
1644uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1645
1646StringRef MachORebaseEntry::typeName() const {
1647 switch (RebaseType) {
1648 case MachO::REBASE_TYPE_POINTER:
1649 return "pointer";
1650 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1651 return "text abs32";
1652 case MachO::REBASE_TYPE_TEXT_PCREL32:
1653 return "text rel32";
1654 }
1655 return "unknown";
1656}
1657
1658bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1659 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1660 return (Ptr == Other.Ptr) &&
1661 (RemainingLoopCount == Other.RemainingLoopCount) &&
1662 (Done == Other.Done);
1663}
1664
1665iterator_range<rebase_iterator>
1666MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1667 MachORebaseEntry Start(Opcodes, is64);
1668 Start.moveToFirst();
1669
1670 MachORebaseEntry Finish(Opcodes, is64);
1671 Finish.moveToEnd();
1672
Craig Topper15576e12015-12-06 05:08:07 +00001673 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00001674}
1675
1676iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1677 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1678}
1679
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001680MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00001681 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1682 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1683 BindType(0), PointerSize(is64Bit ? 8 : 4),
1684 TableKind(BK), Malformed(false), Done(false) {}
1685
1686void MachOBindEntry::moveToFirst() {
1687 Ptr = Opcodes.begin();
1688 moveNext();
1689}
1690
1691void MachOBindEntry::moveToEnd() {
1692 Ptr = Opcodes.end();
1693 RemainingLoopCount = 0;
1694 Done = true;
1695}
1696
1697void MachOBindEntry::moveNext() {
1698 // If in the middle of some loop, move to next binding in loop.
1699 SegmentOffset += AdvanceAmount;
1700 if (RemainingLoopCount) {
1701 --RemainingLoopCount;
1702 return;
1703 }
1704 if (Ptr == Opcodes.end()) {
1705 Done = true;
1706 return;
1707 }
1708 bool More = true;
1709 while (More && !Malformed) {
1710 // Parse next opcode and set up next loop.
1711 uint8_t Byte = *Ptr++;
1712 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1713 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1714 int8_t SignExtended;
1715 const uint8_t *SymStart;
1716 switch (Opcode) {
1717 case MachO::BIND_OPCODE_DONE:
1718 if (TableKind == Kind::Lazy) {
1719 // Lazying bindings have a DONE opcode between entries. Need to ignore
1720 // it to advance to next entry. But need not if this is last entry.
1721 bool NotLastEntry = false;
1722 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1723 if (*P) {
1724 NotLastEntry = true;
1725 }
1726 }
1727 if (NotLastEntry)
1728 break;
1729 }
1730 More = false;
1731 Done = true;
1732 moveToEnd();
1733 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1734 break;
1735 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1736 Ordinal = ImmValue;
1737 DEBUG_WITH_TYPE(
1738 "mach-o-bind",
1739 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1740 << "Ordinal=" << Ordinal << "\n");
1741 break;
1742 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1743 Ordinal = readULEB128();
1744 DEBUG_WITH_TYPE(
1745 "mach-o-bind",
1746 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1747 << "Ordinal=" << Ordinal << "\n");
1748 break;
1749 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1750 if (ImmValue) {
1751 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1752 Ordinal = SignExtended;
1753 } else
1754 Ordinal = 0;
1755 DEBUG_WITH_TYPE(
1756 "mach-o-bind",
1757 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1758 << "Ordinal=" << Ordinal << "\n");
1759 break;
1760 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1761 Flags = ImmValue;
1762 SymStart = Ptr;
1763 while (*Ptr) {
1764 ++Ptr;
1765 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001766 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1767 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001768 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001769 DEBUG_WITH_TYPE(
1770 "mach-o-bind",
1771 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1772 << "SymbolName=" << SymbolName << "\n");
1773 if (TableKind == Kind::Weak) {
1774 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1775 return;
1776 }
1777 break;
1778 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1779 BindType = ImmValue;
1780 DEBUG_WITH_TYPE(
1781 "mach-o-bind",
1782 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1783 << "BindType=" << (int)BindType << "\n");
1784 break;
1785 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1786 Addend = readSLEB128();
1787 if (TableKind == Kind::Lazy)
1788 Malformed = true;
1789 DEBUG_WITH_TYPE(
1790 "mach-o-bind",
1791 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1792 << "Addend=" << Addend << "\n");
1793 break;
1794 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1795 SegmentIndex = ImmValue;
1796 SegmentOffset = readULEB128();
1797 DEBUG_WITH_TYPE(
1798 "mach-o-bind",
1799 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1800 << "SegmentIndex=" << SegmentIndex << ", "
1801 << format("SegmentOffset=0x%06X", SegmentOffset)
1802 << "\n");
1803 break;
1804 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1805 SegmentOffset += readULEB128();
1806 DEBUG_WITH_TYPE("mach-o-bind",
1807 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1808 << format("SegmentOffset=0x%06X",
1809 SegmentOffset) << "\n");
1810 break;
1811 case MachO::BIND_OPCODE_DO_BIND:
1812 AdvanceAmount = PointerSize;
1813 RemainingLoopCount = 0;
1814 DEBUG_WITH_TYPE("mach-o-bind",
1815 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1816 << format("SegmentOffset=0x%06X",
1817 SegmentOffset) << "\n");
1818 return;
1819 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001820 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001821 RemainingLoopCount = 0;
1822 if (TableKind == Kind::Lazy)
1823 Malformed = true;
1824 DEBUG_WITH_TYPE(
1825 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001826 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001827 << format("SegmentOffset=0x%06X", SegmentOffset)
1828 << ", AdvanceAmount=" << AdvanceAmount
1829 << ", RemainingLoopCount=" << RemainingLoopCount
1830 << "\n");
1831 return;
1832 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001833 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001834 RemainingLoopCount = 0;
1835 if (TableKind == Kind::Lazy)
1836 Malformed = true;
1837 DEBUG_WITH_TYPE("mach-o-bind",
1838 llvm::dbgs()
1839 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1840 << format("SegmentOffset=0x%06X",
1841 SegmentOffset) << "\n");
1842 return;
1843 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1844 RemainingLoopCount = readULEB128() - 1;
1845 AdvanceAmount = readULEB128() + PointerSize;
1846 if (TableKind == Kind::Lazy)
1847 Malformed = true;
1848 DEBUG_WITH_TYPE(
1849 "mach-o-bind",
1850 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1851 << format("SegmentOffset=0x%06X", SegmentOffset)
1852 << ", AdvanceAmount=" << AdvanceAmount
1853 << ", RemainingLoopCount=" << RemainingLoopCount
1854 << "\n");
1855 return;
1856 default:
1857 Malformed = true;
1858 }
1859 }
1860}
1861
1862uint64_t MachOBindEntry::readULEB128() {
1863 unsigned Count;
1864 uint64_t Result = decodeULEB128(Ptr, &Count);
1865 Ptr += Count;
1866 if (Ptr > Opcodes.end()) {
1867 Ptr = Opcodes.end();
1868 Malformed = true;
1869 }
1870 return Result;
1871}
1872
1873int64_t MachOBindEntry::readSLEB128() {
1874 unsigned Count;
1875 int64_t Result = decodeSLEB128(Ptr, &Count);
1876 Ptr += Count;
1877 if (Ptr > Opcodes.end()) {
1878 Ptr = Opcodes.end();
1879 Malformed = true;
1880 }
1881 return Result;
1882}
1883
Nick Kledzik56ebef42014-09-16 01:41:51 +00001884uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1885
1886uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1887
1888StringRef MachOBindEntry::typeName() const {
1889 switch (BindType) {
1890 case MachO::BIND_TYPE_POINTER:
1891 return "pointer";
1892 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1893 return "text abs32";
1894 case MachO::BIND_TYPE_TEXT_PCREL32:
1895 return "text rel32";
1896 }
1897 return "unknown";
1898}
1899
1900StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1901
1902int64_t MachOBindEntry::addend() const { return Addend; }
1903
1904uint32_t MachOBindEntry::flags() const { return Flags; }
1905
1906int MachOBindEntry::ordinal() const { return Ordinal; }
1907
1908bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1909 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1910 return (Ptr == Other.Ptr) &&
1911 (RemainingLoopCount == Other.RemainingLoopCount) &&
1912 (Done == Other.Done);
1913}
1914
1915iterator_range<bind_iterator>
1916MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1917 MachOBindEntry::Kind BKind) {
1918 MachOBindEntry Start(Opcodes, is64, BKind);
1919 Start.moveToFirst();
1920
1921 MachOBindEntry Finish(Opcodes, is64, BKind);
1922 Finish.moveToEnd();
1923
Craig Topper15576e12015-12-06 05:08:07 +00001924 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00001925}
1926
1927iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1928 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1929 MachOBindEntry::Kind::Regular);
1930}
1931
1932iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1933 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1934 MachOBindEntry::Kind::Lazy);
1935}
1936
1937iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1938 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1939 MachOBindEntry::Kind::Weak);
1940}
1941
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001942MachOObjectFile::load_command_iterator
1943MachOObjectFile::begin_load_commands() const {
1944 return LoadCommands.begin();
1945}
1946
1947MachOObjectFile::load_command_iterator
1948MachOObjectFile::end_load_commands() const {
1949 return LoadCommands.end();
1950}
1951
1952iterator_range<MachOObjectFile::load_command_iterator>
1953MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00001954 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001955}
1956
Rafael Espindola56f976f2013-04-18 18:08:55 +00001957StringRef
1958MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1959 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1960 return parseSegmentOrSectionName(Raw.data());
1961}
1962
1963ArrayRef<char>
1964MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001965 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001966 const section_base *Base =
1967 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001968 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001969}
1970
1971ArrayRef<char>
1972MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001973 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001974 const section_base *Base =
1975 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001976 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001977}
1978
1979bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001980MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001981 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001982 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001983 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00001984 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001985}
1986
Eric Christopher1d62c252013-07-22 22:25:07 +00001987unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001988 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001989 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001990 return RE.r_word1 & 0xffffff;
1991 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001992}
1993
Eric Christopher1d62c252013-07-22 22:25:07 +00001994bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00001995 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001996 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00001997 return (RE.r_word1 >> 27) & 1;
1998 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00001999}
2000
Eric Christopher1d62c252013-07-22 22:25:07 +00002001bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002002 const MachO::any_relocation_info &RE) const {
2003 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002004}
2005
Eric Christopher1d62c252013-07-22 22:25:07 +00002006uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002007 const MachO::any_relocation_info &RE) const {
2008 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002009}
2010
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002011uint32_t MachOObjectFile::getScatteredRelocationType(
2012 const MachO::any_relocation_info &RE) const {
2013 return (RE.r_word0 >> 24) & 0xf;
2014}
2015
Eric Christopher1d62c252013-07-22 22:25:07 +00002016unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002017 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002018 if (isRelocationScattered(RE))
2019 return getScatteredRelocationAddress(RE);
2020 return getPlainRelocationAddress(RE);
2021}
2022
Charles Davis8bdfafd2013-09-01 04:28:48 +00002023unsigned MachOObjectFile::getAnyRelocationPCRel(
2024 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002025 if (isRelocationScattered(RE))
2026 return getScatteredRelocationPCRel(this, RE);
2027 return getPlainRelocationPCRel(this, RE);
2028}
2029
Eric Christopher1d62c252013-07-22 22:25:07 +00002030unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002031 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002032 if (isRelocationScattered(RE))
2033 return getScatteredRelocationLength(RE);
2034 return getPlainRelocationLength(this, RE);
2035}
2036
2037unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002038MachOObjectFile::getAnyRelocationType(
2039 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002040 if (isRelocationScattered(RE))
2041 return getScatteredRelocationType(RE);
2042 return getPlainRelocationType(this, RE);
2043}
2044
Rafael Espindola52501032013-04-30 15:40:54 +00002045SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002046MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002047 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002048 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002049 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002050 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2051 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2052 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002053 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002054 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002055 return SectionRef(DRI, this);
2056}
2057
Charles Davis8bdfafd2013-09-01 04:28:48 +00002058MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002059 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002060 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002061}
2062
Charles Davis8bdfafd2013-09-01 04:28:48 +00002063MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002064 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002065 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002066}
2067
Charles Davis8bdfafd2013-09-01 04:28:48 +00002068MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002069 unsigned Index) const {
2070 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002071 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002072}
2073
Charles Davis8bdfafd2013-09-01 04:28:48 +00002074MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2075 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002076 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002077 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002078}
2079
Charles Davis8bdfafd2013-09-01 04:28:48 +00002080MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002081MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002082 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002083 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002084}
2085
Charles Davis8bdfafd2013-09-01 04:28:48 +00002086MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002087MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002088 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002089 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002090}
2091
Charles Davis8bdfafd2013-09-01 04:28:48 +00002092MachO::linkedit_data_command
2093MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2094 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002095}
2096
Charles Davis8bdfafd2013-09-01 04:28:48 +00002097MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002098MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002099 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002100}
2101
Charles Davis8bdfafd2013-09-01 04:28:48 +00002102MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002103MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002104 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002105}
2106
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002107MachO::linker_option_command
2108MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2109 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002110}
2111
Jim Grosbach448334a2014-03-18 22:09:05 +00002112MachO::version_min_command
2113MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2114 return getStruct<MachO::version_min_command>(this, L.Ptr);
2115}
2116
Tim Northover8f9590b2014-06-30 14:40:57 +00002117MachO::dylib_command
2118MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2119 return getStruct<MachO::dylib_command>(this, L.Ptr);
2120}
2121
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002122MachO::dyld_info_command
2123MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2124 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2125}
2126
2127MachO::dylinker_command
2128MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2129 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2130}
2131
2132MachO::uuid_command
2133MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2134 return getStruct<MachO::uuid_command>(this, L.Ptr);
2135}
2136
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002137MachO::rpath_command
2138MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2139 return getStruct<MachO::rpath_command>(this, L.Ptr);
2140}
2141
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002142MachO::source_version_command
2143MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2144 return getStruct<MachO::source_version_command>(this, L.Ptr);
2145}
2146
2147MachO::entry_point_command
2148MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2149 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2150}
2151
Kevin Enderby0804f4672014-12-16 23:25:52 +00002152MachO::encryption_info_command
2153MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2154 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2155}
2156
Kevin Enderby57538292014-12-17 01:01:30 +00002157MachO::encryption_info_command_64
2158MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2159 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2160}
2161
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002162MachO::sub_framework_command
2163MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2164 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2165}
Tim Northover8f9590b2014-06-30 14:40:57 +00002166
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002167MachO::sub_umbrella_command
2168MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2169 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2170}
2171
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002172MachO::sub_library_command
2173MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2174 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2175}
2176
Kevin Enderby186eac32014-12-19 21:06:24 +00002177MachO::sub_client_command
2178MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2179 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2180}
2181
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002182MachO::routines_command
2183MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2184 return getStruct<MachO::routines_command>(this, L.Ptr);
2185}
2186
2187MachO::routines_command_64
2188MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2189 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2190}
2191
Kevin Enderby48ef5342014-12-23 22:56:39 +00002192MachO::thread_command
2193MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2194 return getStruct<MachO::thread_command>(this, L.Ptr);
2195}
2196
Charles Davis8bdfafd2013-09-01 04:28:48 +00002197MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002198MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002199 DataRefImpl Sec;
2200 Sec.d.a = Rel.d.a;
2201 uint32_t Offset;
2202 if (is64Bit()) {
2203 MachO::section_64 Sect = getSection64(Sec);
2204 Offset = Sect.reloff;
2205 } else {
2206 MachO::section Sect = getSection(Sec);
2207 Offset = Sect.reloff;
2208 }
2209
2210 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2211 getPtr(this, Offset)) + Rel.d.b;
2212 return getStruct<MachO::any_relocation_info>(
2213 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002214}
2215
Charles Davis8bdfafd2013-09-01 04:28:48 +00002216MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002217MachOObjectFile::getDice(DataRefImpl Rel) const {
2218 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002219 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002220}
2221
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002222const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002223 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002224}
2225
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002226const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2227 assert(is64Bit());
2228 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002229}
2230
Charles Davis8bdfafd2013-09-01 04:28:48 +00002231uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2232 const MachO::dysymtab_command &DLC,
2233 unsigned Index) const {
2234 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2235 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002236}
2237
Charles Davis8bdfafd2013-09-01 04:28:48 +00002238MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002239MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2240 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002241 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2242 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002243}
2244
Charles Davis8bdfafd2013-09-01 04:28:48 +00002245MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002246 if (SymtabLoadCmd)
2247 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2248
2249 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2250 MachO::symtab_command Cmd;
2251 Cmd.cmd = MachO::LC_SYMTAB;
2252 Cmd.cmdsize = sizeof(MachO::symtab_command);
2253 Cmd.symoff = 0;
2254 Cmd.nsyms = 0;
2255 Cmd.stroff = 0;
2256 Cmd.strsize = 0;
2257 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002258}
2259
Charles Davis8bdfafd2013-09-01 04:28:48 +00002260MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002261 if (DysymtabLoadCmd)
2262 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2263
2264 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2265 MachO::dysymtab_command Cmd;
2266 Cmd.cmd = MachO::LC_DYSYMTAB;
2267 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2268 Cmd.ilocalsym = 0;
2269 Cmd.nlocalsym = 0;
2270 Cmd.iextdefsym = 0;
2271 Cmd.nextdefsym = 0;
2272 Cmd.iundefsym = 0;
2273 Cmd.nundefsym = 0;
2274 Cmd.tocoff = 0;
2275 Cmd.ntoc = 0;
2276 Cmd.modtaboff = 0;
2277 Cmd.nmodtab = 0;
2278 Cmd.extrefsymoff = 0;
2279 Cmd.nextrefsyms = 0;
2280 Cmd.indirectsymoff = 0;
2281 Cmd.nindirectsyms = 0;
2282 Cmd.extreloff = 0;
2283 Cmd.nextrel = 0;
2284 Cmd.locreloff = 0;
2285 Cmd.nlocrel = 0;
2286 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002287}
2288
Charles Davis8bdfafd2013-09-01 04:28:48 +00002289MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002290MachOObjectFile::getDataInCodeLoadCommand() const {
2291 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002292 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002293
2294 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002295 MachO::linkedit_data_command Cmd;
2296 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2297 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2298 Cmd.dataoff = 0;
2299 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002300 return Cmd;
2301}
2302
Kevin Enderby9a509442015-01-27 21:28:24 +00002303MachO::linkedit_data_command
2304MachOObjectFile::getLinkOptHintsLoadCommand() const {
2305 if (LinkOptHintsLoadCmd)
2306 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2307
2308 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2309 // fields.
2310 MachO::linkedit_data_command Cmd;
2311 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2312 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2313 Cmd.dataoff = 0;
2314 Cmd.datasize = 0;
2315 return Cmd;
2316}
2317
Nick Kledzikd04bc352014-08-30 00:20:14 +00002318ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002319 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002320 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002321
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002322 MachO::dyld_info_command DyldInfo =
2323 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2324 const uint8_t *Ptr =
2325 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00002326 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002327}
2328
2329ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002330 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002331 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002332
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002333 MachO::dyld_info_command DyldInfo =
2334 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2335 const uint8_t *Ptr =
2336 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002337 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002338}
2339
2340ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002341 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002342 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002343
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002344 MachO::dyld_info_command DyldInfo =
2345 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2346 const uint8_t *Ptr =
2347 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002348 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002349}
2350
2351ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002352 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002353 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002354
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002355 MachO::dyld_info_command DyldInfo =
2356 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2357 const uint8_t *Ptr =
2358 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002359 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002360}
2361
2362ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002363 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002364 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002365
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002366 MachO::dyld_info_command DyldInfo =
2367 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2368 const uint8_t *Ptr =
2369 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00002370 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002371}
2372
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002373ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2374 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002375 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00002376 // Returning a pointer is fine as uuid doesn't need endian swapping.
2377 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00002378 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002379}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002380
Rafael Espindola6e040c02013-04-26 20:07:33 +00002381StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002382 MachO::symtab_command S = getSymtabLoadCommand();
2383 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002384}
2385
Rafael Espindola56f976f2013-04-18 18:08:55 +00002386bool MachOObjectFile::is64Bit() const {
2387 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002388 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002389}
2390
2391void MachOObjectFile::ReadULEB128s(uint64_t Index,
2392 SmallVectorImpl<uint64_t> &Out) const {
2393 DataExtractor extractor(ObjectFile::getData(), true, 0);
2394
2395 uint32_t offset = Index;
2396 uint64_t data = 0;
2397 while (uint64_t delta = extractor.getULEB128(&offset)) {
2398 data += delta;
2399 Out.push_back(data);
2400 }
2401}
2402
Rafael Espindolac66d7612014-08-17 19:09:37 +00002403bool MachOObjectFile::isRelocatableObject() const {
2404 return getHeader().filetype == MachO::MH_OBJECT;
2405}
2406
Lang Hamesff044b12016-03-25 23:11:52 +00002407Expected<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002408ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2409 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00002410 if (Magic == "\xFE\xED\xFA\xCE")
Lang Hamesff044b12016-03-25 23:11:52 +00002411 return MachOObjectFile::create(Buffer, false, false);
David Blaikieb805f732016-03-28 17:45:48 +00002412 if (Magic == "\xCE\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002413 return MachOObjectFile::create(Buffer, true, false);
David Blaikieb805f732016-03-28 17:45:48 +00002414 if (Magic == "\xFE\xED\xFA\xCF")
Lang Hamesff044b12016-03-25 23:11:52 +00002415 return MachOObjectFile::create(Buffer, false, true);
David Blaikieb805f732016-03-28 17:45:48 +00002416 if (Magic == "\xCF\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002417 return MachOObjectFile::create(Buffer, true, true);
Lang Hamesff044b12016-03-25 23:11:52 +00002418 return malformedError(Buffer.getBufferIdentifier(),
2419 "Unrecognized MachO magic number");
Rafael Espindola56f976f2013-04-18 18:08:55 +00002420}