blob: 864d76f7112e12b5a3158d780b812fb76bc98ab2 [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
49
50// FIXME: Remove ECOverride once Error has been plumbed down to obj tool code.
51static Error
52malformedError(const MachOObjectFile &Obj, std::string Msg,
53 object_error ECOverride = object_error::parse_failed) {
54 return malformedError(Obj.getFileName(), std::move(Msg), ECOverride);
55}
56
Alexey Samsonov9f336632015-06-04 19:45:22 +000057// FIXME: Replace all uses of this function with getStructOrErr.
Filipe Cabecinhas40139502015-01-15 22:52:38 +000058template <typename T>
Artyom Skrobov7d602f72014-07-20 12:08:28 +000059static T getStruct(const MachOObjectFile *O, const char *P) {
Filipe Cabecinhas40139502015-01-15 22:52:38 +000060 // Don't read before the beginning or past the end of the file
61 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
62 report_fatal_error("Malformed MachO file.");
63
Rafael Espindola3cdeb172013-04-19 13:45:05 +000064 T Cmd;
65 memcpy(&Cmd, P, sizeof(T));
66 if (O->isLittleEndian() != sys::IsLittleEndianHost)
Artyom Skrobov78d5daf2014-07-18 09:26:16 +000067 MachO::swapStruct(Cmd);
Rafael Espindola3cdeb172013-04-19 13:45:05 +000068 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +000069}
70
Alexey Samsonov9f336632015-06-04 19:45:22 +000071template <typename T>
Lang Hames9e964f32016-03-25 17:25:34 +000072static Expected<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
Alexey Samsonov9f336632015-06-04 19:45:22 +000073 // Don't read before the beginning or past the end of the file
74 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
Lang Hames9e964f32016-03-25 17:25:34 +000075 return malformedError(*O, "Structure read out-of-range");
Alexey Samsonov9f336632015-06-04 19:45:22 +000076
77 T Cmd;
78 memcpy(&Cmd, P, sizeof(T));
79 if (O->isLittleEndian() != sys::IsLittleEndianHost)
80 MachO::swapStruct(Cmd);
81 return Cmd;
82}
83
Rafael Espindola6e040c02013-04-26 20:07:33 +000084static const char *
85getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
86 unsigned Sec) {
Rafael Espindola56f976f2013-04-18 18:08:55 +000087 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
88
89 bool Is64 = O->is64Bit();
Charles Davis8bdfafd2013-09-01 04:28:48 +000090 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
91 sizeof(MachO::segment_command);
92 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
93 sizeof(MachO::section);
Rafael Espindola56f976f2013-04-18 18:08:55 +000094
95 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Charles Davis1827bd82013-08-27 05:38:30 +000096 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola60689982013-04-07 19:05:30 +000097}
98
Rafael Espindola56f976f2013-04-18 18:08:55 +000099static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
100 return O->getData().substr(Offset, 1).data();
Rafael Espindola60689982013-04-07 19:05:30 +0000101}
102
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000103static MachO::nlist_base
Rafael Espindola56f976f2013-04-18 18:08:55 +0000104getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola75c30362013-04-24 19:47:55 +0000105 const char *P = reinterpret_cast<const char *>(DRI.p);
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000106 return getStruct<MachO::nlist_base>(O, P);
Eric Christopher7b015c72011-04-22 03:19:48 +0000107}
108
Rafael Espindola56f976f2013-04-18 18:08:55 +0000109static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000110 if (P[15] == 0)
111 // Null terminated.
112 return P;
113 // Not null terminated, so this is a 16 char string.
114 return StringRef(P, 16);
115}
116
Rafael Espindola56f976f2013-04-18 18:08:55 +0000117// Helper to advance a section or symbol iterator multiple increments at a time.
118template<class T>
Rafael Espindola5e812af2014-01-30 02:49:50 +0000119static void advance(T &it, size_t Val) {
120 while (Val--)
121 ++it;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000122}
123
124static unsigned getCPUType(const MachOObjectFile *O) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000125 return O->getHeader().cputype;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000126}
127
Charles Davis8bdfafd2013-09-01 04:28:48 +0000128static uint32_t
129getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
130 return RE.r_word0;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000131}
132
133static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000134getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
135 return RE.r_word0 & 0xffffff;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000136}
137
138static bool getPlainRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000139 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000140 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000141 return (RE.r_word1 >> 24) & 1;
142 return (RE.r_word1 >> 7) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000143}
144
145static bool
146getScatteredRelocationPCRel(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000147 const MachO::any_relocation_info &RE) {
148 return (RE.r_word0 >> 30) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000149}
150
151static unsigned getPlainRelocationLength(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000152 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000153 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000154 return (RE.r_word1 >> 25) & 3;
155 return (RE.r_word1 >> 5) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000156}
157
158static unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +0000159getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
160 return (RE.r_word0 >> 28) & 3;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000161}
162
163static unsigned getPlainRelocationType(const MachOObjectFile *O,
Charles Davis8bdfafd2013-09-01 04:28:48 +0000164 const MachO::any_relocation_info &RE) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000165 if (O->isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +0000166 return RE.r_word1 >> 28;
167 return RE.r_word1 & 0xf;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000168}
169
Rafael Espindola56f976f2013-04-18 18:08:55 +0000170static uint32_t getSectionFlags(const MachOObjectFile *O,
171 DataRefImpl Sec) {
172 if (O->is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000173 MachO::section_64 Sect = O->getSection64(Sec);
174 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000175 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000176 MachO::section Sect = O->getSection(Sec);
177 return Sect.flags;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000178}
179
Lang Hames9e964f32016-03-25 17:25:34 +0000180static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000181getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
Lang Hames9e964f32016-03-25 17:25:34 +0000182 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
183 if (CmdOrErr->cmdsize < 8)
184 return malformedError(*Obj, "Mach-O load command with size < 8 bytes",
185 object_error::macho_small_load_command);
186 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
187 } else
188 return CmdOrErr.takeError();
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000189}
190
Lang Hames9e964f32016-03-25 17:25:34 +0000191static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000192getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
193 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
194 : sizeof(MachO::mach_header);
195 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
196}
197
Lang Hames9e964f32016-03-25 17:25:34 +0000198static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000199getNextLoadCommandInfo(const MachOObjectFile *Obj,
200 const MachOObjectFile::LoadCommandInfo &L) {
201 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
202}
203
Alexey Samsonov9f336632015-06-04 19:45:22 +0000204template <typename T>
205static void parseHeader(const MachOObjectFile *Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000206 Error &Err) {
207 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
208 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000209 else
Lang Hames9e964f32016-03-25 17:25:34 +0000210 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000211}
212
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000213// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
214// sections to \param Sections, and optionally sets
215// \param IsPageZeroSegment to true.
216template <typename SegmentCmd>
Lang Hames9e964f32016-03-25 17:25:34 +0000217static Error parseSegmentLoadCommand(
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000218 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
219 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
220 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
221 if (Load.C.cmdsize < SegmentLoadSize)
Lang Hames9e964f32016-03-25 17:25:34 +0000222 return malformedError(*Obj,
223 "Mach-O segment load command size is too small",
224 object_error::macho_load_segment_too_small);
225 if (auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr)) {
226 SegmentCmd S = SegOrErr.get();
227 const unsigned SectionSize =
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000228 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
Lang Hames9e964f32016-03-25 17:25:34 +0000229 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
230 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
231 return malformedError(*Obj,
232 "Mach-O segment load command contains too many "
233 "sections",
234 object_error::macho_load_segment_too_many_sections);
235 for (unsigned J = 0; J < S.nsects; ++J) {
236 const char *Sec = getSectionPtr(Obj, Load, J);
237 Sections.push_back(Sec);
238 }
239 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
240 } else
241 return SegOrErr.takeError();
242
243 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000244}
245
Lang Hames82627642016-03-25 21:59:14 +0000246Expected<std::unique_ptr<MachOObjectFile>>
247MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
248 bool Is64Bits) {
249 Error Err = Error::errorForOutParameter();
250 std::unique_ptr<MachOObjectFile> Obj(
251 new MachOObjectFile(std::move(Object), IsLittleEndian,
252 Is64Bits, Err));
253 if (Err)
254 return std::move(Err);
255 return std::move(Obj);
256}
257
Rafael Espindola48af1c22014-08-19 18:44:46 +0000258MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Lang Hames9e964f32016-03-25 17:25:34 +0000259 bool Is64bits, Error &Err)
Rafael Espindola48af1c22014-08-19 18:44:46 +0000260 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000261 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000262 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
263 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
264 HasPageZeroSegment(false) {
Lang Hames9e964f32016-03-25 17:25:34 +0000265
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000266 if (is64Bit())
Lang Hames9e964f32016-03-25 17:25:34 +0000267 parseHeader(this, Header64, Err);
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000268 else
Lang Hames9e964f32016-03-25 17:25:34 +0000269 parseHeader(this, Header, Err);
270 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +0000271 return;
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000272
273 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000274 if (LoadCommandCount == 0)
275 return;
276
Lang Hames9e964f32016-03-25 17:25:34 +0000277 LoadCommandInfo Load;
278 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
279 Load = *LoadOrErr;
280 else {
281 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000282 return;
283 }
Lang Hames9e964f32016-03-25 17:25:34 +0000284
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000285 for (unsigned I = 0; I < LoadCommandCount; ++I) {
286 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000287 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000288 // Multiple symbol tables
289 if (SymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000290 Err = malformedError(*this, "Multiple symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000291 return;
292 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000293 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000294 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000295 // Multiple dynamic symbol tables
296 if (DysymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000297 Err = malformedError(*this, "Multiple dynamic symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000298 return;
299 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000300 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000301 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000302 // Multiple data in code tables
303 if (DataInCodeLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000304 Err = malformedError(*this, "Multiple data-in-code tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000305 return;
306 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000307 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000308 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
309 // Multiple linker optimization hint tables
310 if (LinkOptHintsLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000311 Err = malformedError(*this, "Multiple linker optimization hint tables");
Kevin Enderby9a509442015-01-27 21:28:24 +0000312 return;
313 }
314 LinkOptHintsLoadCmd = Load.Ptr;
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +0000315 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Nick Kledzikd04bc352014-08-30 00:20:14 +0000316 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000317 // Multiple dyldinfo load commands
318 if (DyldInfoLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000319 Err = malformedError(*this, "Multiple dyldinfo load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000320 return;
321 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000322 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000323 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000324 // Multiple UUID load commands
325 if (UuidLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000326 Err = malformedError(*this, "Multiple UUID load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000327 return;
328 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000329 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000330 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Lang Hames9e964f32016-03-25 17:25:34 +0000331 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64>(
332 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000333 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000334 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Lang Hames9e964f32016-03-25 17:25:34 +0000335 if ((Err = parseSegmentLoadCommand<MachO::segment_command>(
336 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000337 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000338 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
339 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
340 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
341 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
342 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
343 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000344 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000345 if (I < LoadCommandCount - 1) {
Lang Hames9e964f32016-03-25 17:25:34 +0000346 if (auto LoadOrErr = getNextLoadCommandInfo(this, Load))
347 Load = *LoadOrErr;
348 else {
349 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000350 return;
351 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000352 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000353 }
Kevin Enderby1829c682016-01-22 22:49:55 +0000354 if (!SymtabLoadCmd) {
355 if (DysymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000356 Err = malformedError(*this,
357 "truncated or malformed object (contains "
358 "LC_DYSYMTAB load command without a LC_SYMTAB load "
359 "command)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000360 return;
361 }
362 } else if (DysymtabLoadCmd) {
363 MachO::symtab_command Symtab =
364 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
365 MachO::dysymtab_command Dysymtab =
366 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
367 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000368 Err = malformedError(*this,
369 "truncated or malformed object (iolocalsym in "
370 "LC_DYSYMTAB load command extends past the end of "
371 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000372 return;
373 }
374 uint64_t big_size = Dysymtab.ilocalsym;
375 big_size += Dysymtab.nlocalsym;
376 if (Dysymtab.nlocalsym != 0 && big_size > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000377 Err = malformedError(*this,
378 "truncated or malformed object (ilocalsym plus "
379 "nlocalsym in LC_DYSYMTAB load command extends past "
380 "the end of the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000381 return;
382 }
383 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000384 Err = malformedError(*this,
385 "truncated or malformed object (nextdefsym in "
386 "LC_DYSYMTAB load command extends past the end of "
387 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000388 return;
389 }
390 big_size = Dysymtab.iextdefsym;
391 big_size += Dysymtab.nextdefsym;
392 if (Dysymtab.nextdefsym != 0 && big_size > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000393 Err = malformedError(*this,
394 "truncated or malformed object (iextdefsym plus "
395 "nextdefsym in LC_DYSYMTAB load command extends "
396 "past the end of the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000397 return;
398 }
399 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000400 Err = malformedError(*this,
401 "truncated or malformed object (nundefsym in "
402 "LC_DYSYMTAB load command extends past the end of "
403 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000404 return;
405 }
406 big_size = Dysymtab.iundefsym;
407 big_size += Dysymtab.nundefsym;
408 if (Dysymtab.nundefsym != 0 && big_size > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000409 Err = malformedError(*this,
410 "truncated or malformed object (iundefsym plus "
411 "nundefsym in LC_DYSYMTAB load command extends past "
412 "the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000413 return;
414 }
415 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000416 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +0000417
418 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000419}
420
Rafael Espindola5e812af2014-01-30 02:49:50 +0000421void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000422 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000423 sizeof(MachO::nlist_64) :
424 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000425 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000426}
427
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000428ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000429 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000430 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000431 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000432 if (Start < getData().begin() || Start >= getData().end())
Kevin Enderbyf681ec52016-01-22 18:47:14 +0000433 return object_error::parse_failed;
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000434 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000435}
436
Rafael Espindola0e77a942014-12-10 20:46:55 +0000437unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
438 DataRefImpl DRI = Sec.getRawDataRefImpl();
439 uint32_t Flags = getSectionFlags(this, DRI);
440 return Flags & MachO::SECTION_TYPE;
441}
442
Rafael Espindola59128922015-06-24 18:14:41 +0000443uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
444 if (is64Bit()) {
445 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
446 return Entry.n_value;
447 }
448 MachO::nlist Entry = getSymbolTableEntry(Sym);
449 return Entry.n_value;
450}
451
Kevin Enderby980b2582014-06-05 21:21:57 +0000452// getIndirectName() returns the name of the alias'ed symbol who's string table
453// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000454std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
455 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000456 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000457 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
458 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
459 return object_error::parse_failed;
460 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000461 if (NValue >= StringTable.size())
462 return object_error::parse_failed;
463 const char *Start = &StringTable.data()[NValue];
464 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000465 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000466}
467
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +0000468uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +0000469 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +0000470}
471
Rafael Espindolaed067c42015-07-03 18:19:00 +0000472ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
473 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000474}
475
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000476uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000477 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000478 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000479 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000480 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000481 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000482 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000483}
484
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000485uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000486 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000487}
488
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000489ErrorOr<SymbolRef::Type>
490MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000491 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000492 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000493
Rafael Espindola56f976f2013-04-18 18:08:55 +0000494 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000495 if (n_type & MachO::N_STAB)
496 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000497
Charles Davis74ec8b02013-08-27 05:00:13 +0000498 switch (n_type & MachO::N_TYPE) {
499 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000500 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +0000501 case MachO::N_SECT :
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000502 ErrorOr<section_iterator> SecOrError = getSymbolSection(Symb);
503 if (!SecOrError)
504 return SecOrError.getError();
505 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +0000506 if (Sec->isData() || Sec->isBSS())
507 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000508 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000509 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000510 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000511}
512
Rafael Espindola20122a42014-01-31 20:57:12 +0000513uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000514 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000515
Charles Davis8bdfafd2013-09-01 04:28:48 +0000516 uint8_t MachOType = Entry.n_type;
517 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000518
Rafael Espindola20122a42014-01-31 20:57:12 +0000519 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000520
Tim Northovereaef0742014-05-30 13:22:59 +0000521 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
522 Result |= SymbolRef::SF_Indirect;
523
Rafael Espindolaa1356322013-11-02 05:03:24 +0000524 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000525 Result |= SymbolRef::SF_FormatSpecific;
526
Charles Davis74ec8b02013-08-27 05:00:13 +0000527 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000528 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000529 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000530 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000531 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +0000532 else
533 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000534 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000535
536 if (!(MachOType & MachO::N_PEXT))
537 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000538 }
539
Charles Davis74ec8b02013-08-27 05:00:13 +0000540 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000541 Result |= SymbolRef::SF_Weak;
542
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000543 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
544 Result |= SymbolRef::SF_Thumb;
545
Charles Davis74ec8b02013-08-27 05:00:13 +0000546 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000547 Result |= SymbolRef::SF_Absolute;
548
Rafael Espindola20122a42014-01-31 20:57:12 +0000549 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000550}
551
Rafael Espindola8bab8892015-08-07 23:27:14 +0000552ErrorOr<section_iterator>
553MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000554 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000555 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000556
Rafael Espindola8bab8892015-08-07 23:27:14 +0000557 if (index == 0)
558 return section_end();
559 DataRefImpl DRI;
560 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000561 if (DRI.d.a >= Sections.size()){
562 // Diagnostic("bad section index (" + index + ") for symbol at index " +
563 // SymbolIndex);
Kevin Enderby1f472ea2016-01-21 21:13:27 +0000564 return object_error::parse_failed;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000565 }
Rafael Espindola8bab8892015-08-07 23:27:14 +0000566 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000567}
568
Rafael Espindola6bf32212015-06-24 19:57:32 +0000569unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
570 MachO::nlist_base Entry =
571 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
572 return Entry.n_sect - 1;
573}
574
Rafael Espindola5e812af2014-01-30 02:49:50 +0000575void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000576 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000577}
578
Rafael Espindola3acea392014-06-12 21:46:39 +0000579std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
580 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000581 ArrayRef<char> Raw = getSectionRawName(Sec);
582 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000583 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000584}
585
Rafael Espindola80291272014-10-08 15:28:58 +0000586uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
587 if (is64Bit())
588 return getSection64(Sec).addr;
589 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000590}
591
Rafael Espindola80291272014-10-08 15:28:58 +0000592uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +0000593 // In the case if a malformed Mach-O file where the section offset is past
594 // the end of the file or some part of the section size is past the end of
595 // the file return a size of zero or a size that covers the rest of the file
596 // but does not extend past the end of the file.
597 uint32_t SectOffset, SectType;
598 uint64_t SectSize;
599
600 if (is64Bit()) {
601 MachO::section_64 Sect = getSection64(Sec);
602 SectOffset = Sect.offset;
603 SectSize = Sect.size;
604 SectType = Sect.flags & MachO::SECTION_TYPE;
605 } else {
606 MachO::section Sect = getSection(Sec);
607 SectOffset = Sect.offset;
608 SectSize = Sect.size;
609 SectType = Sect.flags & MachO::SECTION_TYPE;
610 }
611 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
612 return SectSize;
613 uint64_t FileSize = getData().size();
614 if (SectOffset > FileSize)
615 return 0;
616 if (FileSize - SectOffset < SectSize)
617 return FileSize - SectOffset;
618 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000619}
620
Rafael Espindola3acea392014-06-12 21:46:39 +0000621std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
622 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000623 uint32_t Offset;
624 uint64_t Size;
625
626 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000627 MachO::section_64 Sect = getSection64(Sec);
628 Offset = Sect.offset;
629 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000630 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000631 MachO::section Sect = getSection(Sec);
632 Offset = Sect.offset;
633 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000634 }
635
636 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000637 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000638}
639
Rafael Espindola80291272014-10-08 15:28:58 +0000640uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000641 uint32_t Align;
642 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000643 MachO::section_64 Sect = getSection64(Sec);
644 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000645 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000646 MachO::section Sect = getSection(Sec);
647 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000648 }
649
Rafael Espindola80291272014-10-08 15:28:58 +0000650 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000651}
652
Rafael Espindola80291272014-10-08 15:28:58 +0000653bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000654 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000655 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000656}
657
Rafael Espindola80291272014-10-08 15:28:58 +0000658bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000659 uint32_t Flags = getSectionFlags(this, Sec);
660 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000661 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
662 !(SectionType == MachO::S_ZEROFILL ||
663 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000664}
665
Rafael Espindola80291272014-10-08 15:28:58 +0000666bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000667 uint32_t Flags = getSectionFlags(this, Sec);
668 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000669 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
670 (SectionType == MachO::S_ZEROFILL ||
671 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000672}
673
Rafael Espindola6bf32212015-06-24 19:57:32 +0000674unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
675 return Sec.getRawDataRefImpl().d.a;
676}
677
Rafael Espindola80291272014-10-08 15:28:58 +0000678bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000679 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000680 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000681}
682
Steven Wuf2fe0142016-02-29 19:40:10 +0000683bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
684 StringRef SegmentName = getSectionFinalSegmentName(Sec);
685 StringRef SectName;
686 if (!getSectionName(Sec, SectName))
687 return (SegmentName == "__LLVM" && SectName == "__bitcode");
688 return false;
689}
690
Rui Ueyamabc654b12013-09-27 21:47:05 +0000691relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000692 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000693 Ret.d.a = Sec.d.a;
694 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000695 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000696}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000697
Rafael Espindola56f976f2013-04-18 18:08:55 +0000698relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000699MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000700 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000701 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000702 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000703 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000704 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000705 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000706 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000707 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000708
Rafael Espindola56f976f2013-04-18 18:08:55 +0000709 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000710 Ret.d.a = Sec.d.a;
711 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000712 return relocation_iterator(RelocationRef(Ret, this));
713}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000714
Rafael Espindola5e812af2014-01-30 02:49:50 +0000715void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000716 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000717}
Owen Anderson171f4852011-10-24 23:20:07 +0000718
Rafael Espindola96d071c2015-06-29 23:29:12 +0000719uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000720 assert(getHeader().filetype == MachO::MH_OBJECT &&
721 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000722 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000723 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +0000724}
725
Rafael Espindola806f0062013-06-05 01:33:53 +0000726symbol_iterator
727MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000728 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000729 if (isRelocationScattered(RE))
730 return symbol_end();
731
Rafael Espindola56f976f2013-04-18 18:08:55 +0000732 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
733 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000734 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000735 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000736
Charles Davis8bdfafd2013-09-01 04:28:48 +0000737 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000738 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000739 sizeof(MachO::nlist_64) :
740 sizeof(MachO::nlist);
741 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000742 DataRefImpl Sym;
743 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000744 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000745}
746
Keno Fischerc780e8e2015-05-21 21:24:32 +0000747section_iterator
748MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
749 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
750}
751
Rafael Espindola99c041b2015-06-30 01:53:01 +0000752uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000753 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +0000754 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000755}
756
Rafael Espindola41bb4322015-06-30 04:08:37 +0000757void MachOObjectFile::getRelocationTypeName(
758 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000759 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +0000760 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000761
762 unsigned Arch = this->getArch();
763
764 switch (Arch) {
765 case Triple::x86: {
766 static const char *const Table[] = {
767 "GENERIC_RELOC_VANILLA",
768 "GENERIC_RELOC_PAIR",
769 "GENERIC_RELOC_SECTDIFF",
770 "GENERIC_RELOC_PB_LA_PTR",
771 "GENERIC_RELOC_LOCAL_SECTDIFF",
772 "GENERIC_RELOC_TLV" };
773
Eric Christopher13250cb2013-12-06 02:33:38 +0000774 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000775 res = "Unknown";
776 else
777 res = Table[RType];
778 break;
779 }
780 case Triple::x86_64: {
781 static const char *const Table[] = {
782 "X86_64_RELOC_UNSIGNED",
783 "X86_64_RELOC_SIGNED",
784 "X86_64_RELOC_BRANCH",
785 "X86_64_RELOC_GOT_LOAD",
786 "X86_64_RELOC_GOT",
787 "X86_64_RELOC_SUBTRACTOR",
788 "X86_64_RELOC_SIGNED_1",
789 "X86_64_RELOC_SIGNED_2",
790 "X86_64_RELOC_SIGNED_4",
791 "X86_64_RELOC_TLV" };
792
793 if (RType > 9)
794 res = "Unknown";
795 else
796 res = Table[RType];
797 break;
798 }
799 case Triple::arm: {
800 static const char *const Table[] = {
801 "ARM_RELOC_VANILLA",
802 "ARM_RELOC_PAIR",
803 "ARM_RELOC_SECTDIFF",
804 "ARM_RELOC_LOCAL_SECTDIFF",
805 "ARM_RELOC_PB_LA_PTR",
806 "ARM_RELOC_BR24",
807 "ARM_THUMB_RELOC_BR22",
808 "ARM_THUMB_32BIT_BRANCH",
809 "ARM_RELOC_HALF",
810 "ARM_RELOC_HALF_SECTDIFF" };
811
812 if (RType > 9)
813 res = "Unknown";
814 else
815 res = Table[RType];
816 break;
817 }
Tim Northover00ed9962014-03-29 10:18:08 +0000818 case Triple::aarch64: {
819 static const char *const Table[] = {
820 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
821 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
822 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
823 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
824 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
825 "ARM64_RELOC_ADDEND"
826 };
827
828 if (RType >= array_lengthof(Table))
829 res = "Unknown";
830 else
831 res = Table[RType];
832 break;
833 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000834 case Triple::ppc: {
835 static const char *const Table[] = {
836 "PPC_RELOC_VANILLA",
837 "PPC_RELOC_PAIR",
838 "PPC_RELOC_BR14",
839 "PPC_RELOC_BR24",
840 "PPC_RELOC_HI16",
841 "PPC_RELOC_LO16",
842 "PPC_RELOC_HA16",
843 "PPC_RELOC_LO14",
844 "PPC_RELOC_SECTDIFF",
845 "PPC_RELOC_PB_LA_PTR",
846 "PPC_RELOC_HI16_SECTDIFF",
847 "PPC_RELOC_LO16_SECTDIFF",
848 "PPC_RELOC_HA16_SECTDIFF",
849 "PPC_RELOC_JBSR",
850 "PPC_RELOC_LO14_SECTDIFF",
851 "PPC_RELOC_LOCAL_SECTDIFF" };
852
Eric Christopher13250cb2013-12-06 02:33:38 +0000853 if (RType > 15)
854 res = "Unknown";
855 else
856 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000857 break;
858 }
859 case Triple::UnknownArch:
860 res = "Unknown";
861 break;
862 }
863 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +0000864}
865
Keno Fischer281b6942015-05-30 19:44:53 +0000866uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
867 MachO::any_relocation_info RE = getRelocation(Rel);
868 return getAnyRelocationLength(RE);
869}
870
Kevin Enderby980b2582014-06-05 21:21:57 +0000871//
872// guessLibraryShortName() is passed a name of a dynamic library and returns a
873// guess on what the short name is. Then name is returned as a substring of the
874// StringRef Name passed in. The name of the dynamic library is recognized as
875// a framework if it has one of the two following forms:
876// Foo.framework/Versions/A/Foo
877// Foo.framework/Foo
878// Where A and Foo can be any string. And may contain a trailing suffix
879// starting with an underbar. If the Name is recognized as a framework then
880// isFramework is set to true else it is set to false. If the Name has a
881// suffix then Suffix is set to the substring in Name that contains the suffix
882// else it is set to a NULL StringRef.
883//
884// The Name of the dynamic library is recognized as a library name if it has
885// one of the two following forms:
886// libFoo.A.dylib
887// libFoo.dylib
888// The library may have a suffix trailing the name Foo of the form:
889// libFoo_profile.A.dylib
890// libFoo_profile.dylib
891//
892// The Name of the dynamic library is also recognized as a library name if it
893// has the following form:
894// Foo.qtx
895//
896// If the Name of the dynamic library is none of the forms above then a NULL
897// StringRef is returned.
898//
899StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
900 bool &isFramework,
901 StringRef &Suffix) {
902 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
903 size_t a, b, c, d, Idx;
904
905 isFramework = false;
906 Suffix = StringRef();
907
908 // Pull off the last component and make Foo point to it
909 a = Name.rfind('/');
910 if (a == Name.npos || a == 0)
911 goto guess_library;
912 Foo = Name.slice(a+1, Name.npos);
913
914 // Look for a suffix starting with a '_'
915 Idx = Foo.rfind('_');
916 if (Idx != Foo.npos && Foo.size() >= 2) {
917 Suffix = Foo.slice(Idx, Foo.npos);
918 Foo = Foo.slice(0, Idx);
919 }
920
921 // First look for the form Foo.framework/Foo
922 b = Name.rfind('/', a);
923 if (b == Name.npos)
924 Idx = 0;
925 else
926 Idx = b+1;
927 F = Name.slice(Idx, Idx + Foo.size());
928 DotFramework = Name.slice(Idx + Foo.size(),
929 Idx + Foo.size() + sizeof(".framework/")-1);
930 if (F == Foo && DotFramework == ".framework/") {
931 isFramework = true;
932 return Foo;
933 }
934
935 // Next look for the form Foo.framework/Versions/A/Foo
936 if (b == Name.npos)
937 goto guess_library;
938 c = Name.rfind('/', b);
939 if (c == Name.npos || c == 0)
940 goto guess_library;
941 V = Name.slice(c+1, Name.npos);
942 if (!V.startswith("Versions/"))
943 goto guess_library;
944 d = Name.rfind('/', c);
945 if (d == Name.npos)
946 Idx = 0;
947 else
948 Idx = d+1;
949 F = Name.slice(Idx, Idx + Foo.size());
950 DotFramework = Name.slice(Idx + Foo.size(),
951 Idx + Foo.size() + sizeof(".framework/")-1);
952 if (F == Foo && DotFramework == ".framework/") {
953 isFramework = true;
954 return Foo;
955 }
956
957guess_library:
958 // pull off the suffix after the "." and make a point to it
959 a = Name.rfind('.');
960 if (a == Name.npos || a == 0)
961 return StringRef();
962 Dylib = Name.slice(a, Name.npos);
963 if (Dylib != ".dylib")
964 goto guess_qtx;
965
966 // First pull off the version letter for the form Foo.A.dylib if any.
967 if (a >= 3) {
968 Dot = Name.slice(a-2, a-1);
969 if (Dot == ".")
970 a = a - 2;
971 }
972
973 b = Name.rfind('/', a);
974 if (b == Name.npos)
975 b = 0;
976 else
977 b = b+1;
978 // ignore any suffix after an underbar like Foo_profile.A.dylib
979 Idx = Name.find('_', b);
980 if (Idx != Name.npos && Idx != b) {
981 Lib = Name.slice(b, Idx);
982 Suffix = Name.slice(Idx, a);
983 }
984 else
985 Lib = Name.slice(b, a);
986 // There are incorrect library names of the form:
987 // libATS.A_profile.dylib so check for these.
988 if (Lib.size() >= 3) {
989 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
990 if (Dot == ".")
991 Lib = Lib.slice(0, Lib.size()-2);
992 }
993 return Lib;
994
995guess_qtx:
996 Qtx = Name.slice(a, Name.npos);
997 if (Qtx != ".qtx")
998 return StringRef();
999 b = Name.rfind('/', a);
1000 if (b == Name.npos)
1001 Lib = Name.slice(0, a);
1002 else
1003 Lib = Name.slice(b+1, a);
1004 // There are library names of the form: QT.A.qtx so check for these.
1005 if (Lib.size() >= 3) {
1006 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1007 if (Dot == ".")
1008 Lib = Lib.slice(0, Lib.size()-2);
1009 }
1010 return Lib;
1011}
1012
1013// getLibraryShortNameByIndex() is used to get the short name of the library
1014// for an undefined symbol in a linked Mach-O binary that was linked with the
1015// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1016// It is passed the index (0 - based) of the library as translated from
1017// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001018std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001019 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001020 if (Index >= Libraries.size())
1021 return object_error::parse_failed;
1022
Kevin Enderby980b2582014-06-05 21:21:57 +00001023 // If the cache of LibrariesShortNames is not built up do that first for
1024 // all the Libraries.
1025 if (LibrariesShortNames.size() == 0) {
1026 for (unsigned i = 0; i < Libraries.size(); i++) {
1027 MachO::dylib_command D =
1028 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001029 if (D.dylib.name >= D.cmdsize)
1030 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001031 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001032 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001033 if (D.dylib.name+Name.size() >= D.cmdsize)
1034 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001035 StringRef Suffix;
1036 bool isFramework;
1037 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001038 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001039 LibrariesShortNames.push_back(Name);
1040 else
1041 LibrariesShortNames.push_back(shortName);
1042 }
1043 }
1044
1045 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00001046 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001047}
1048
Rafael Espindola76ad2322015-07-06 14:55:37 +00001049section_iterator
1050MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
1051 DataRefImpl Sec;
1052 Sec.d.a = Rel->getRawDataRefImpl().d.a;
1053 return section_iterator(SectionRef(Sec, this));
1054}
1055
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001056basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00001057 DataRefImpl DRI;
1058 MachO::symtab_command Symtab = getSymtabLoadCommand();
1059 if (!SymtabLoadCmd || Symtab.nsyms == 0)
1060 return basic_symbol_iterator(SymbolRef(DRI, this));
1061
Lang Hames36072da2014-05-12 21:39:59 +00001062 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001063}
1064
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001065basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001066 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00001067 MachO::symtab_command Symtab = getSymtabLoadCommand();
1068 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001069 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001070
Rafael Espindola75c30362013-04-24 19:47:55 +00001071 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001072 sizeof(MachO::nlist_64) :
1073 sizeof(MachO::nlist);
1074 unsigned Offset = Symtab.symoff +
1075 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001076 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001077 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001078}
1079
Lang Hames36072da2014-05-12 21:39:59 +00001080basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00001081 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00001082 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001083 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001084 unsigned SymbolTableEntrySize =
1085 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00001086 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00001087 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1088 DRI.p += Index * SymbolTableEntrySize;
1089 return basic_symbol_iterator(SymbolRef(DRI, this));
1090}
1091
Rafael Espindolab5155a52014-02-10 20:24:04 +00001092section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001093 DataRefImpl DRI;
1094 return section_iterator(SectionRef(DRI, this));
1095}
1096
Rafael Espindolab5155a52014-02-10 20:24:04 +00001097section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001098 DataRefImpl DRI;
1099 DRI.d.a = Sections.size();
1100 return section_iterator(SectionRef(DRI, this));
1101}
1102
Rafael Espindola56f976f2013-04-18 18:08:55 +00001103uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001104 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001105}
1106
Rafael Espindola56f976f2013-04-18 18:08:55 +00001107StringRef MachOObjectFile::getFileFormatName() const {
1108 unsigned CPUType = getCPUType(this);
1109 if (!is64Bit()) {
1110 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001111 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001112 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001113 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001114 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001115 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001116 return "Mach-O 32-bit ppc";
1117 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001118 return "Mach-O 32-bit unknown";
1119 }
1120 }
1121
Rafael Espindola56f976f2013-04-18 18:08:55 +00001122 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001123 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001124 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001125 case llvm::MachO::CPU_TYPE_ARM64:
1126 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001127 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001128 return "Mach-O 64-bit ppc64";
1129 default:
1130 return "Mach-O 64-bit unknown";
1131 }
1132}
1133
Alexey Samsonove6388e62013-06-18 15:03:28 +00001134Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1135 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001136 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001137 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001138 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001139 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001140 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001141 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001142 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001143 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001144 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001145 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001146 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001147 return Triple::ppc64;
1148 default:
1149 return Triple::UnknownArch;
1150 }
1151}
1152
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001153Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1154 const char **McpuDefault) {
1155 if (McpuDefault)
1156 *McpuDefault = nullptr;
1157
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001158 switch (CPUType) {
1159 case MachO::CPU_TYPE_I386:
1160 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1161 case MachO::CPU_SUBTYPE_I386_ALL:
1162 return Triple("i386-apple-darwin");
1163 default:
1164 return Triple();
1165 }
1166 case MachO::CPU_TYPE_X86_64:
1167 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1168 case MachO::CPU_SUBTYPE_X86_64_ALL:
1169 return Triple("x86_64-apple-darwin");
1170 case MachO::CPU_SUBTYPE_X86_64_H:
1171 return Triple("x86_64h-apple-darwin");
1172 default:
1173 return Triple();
1174 }
1175 case MachO::CPU_TYPE_ARM:
1176 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1177 case MachO::CPU_SUBTYPE_ARM_V4T:
1178 return Triple("armv4t-apple-darwin");
1179 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1180 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001181 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1182 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001183 case MachO::CPU_SUBTYPE_ARM_V6:
1184 return Triple("armv6-apple-darwin");
1185 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001186 if (McpuDefault)
1187 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001188 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001189 case MachO::CPU_SUBTYPE_ARM_V7:
1190 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001191 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001192 if (McpuDefault)
1193 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001194 return Triple("armv7em-apple-darwin");
1195 case MachO::CPU_SUBTYPE_ARM_V7K:
1196 return Triple("armv7k-apple-darwin");
1197 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001198 if (McpuDefault)
1199 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001200 return Triple("armv7m-apple-darwin");
1201 case MachO::CPU_SUBTYPE_ARM_V7S:
1202 return Triple("armv7s-apple-darwin");
1203 default:
1204 return Triple();
1205 }
1206 case MachO::CPU_TYPE_ARM64:
1207 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1208 case MachO::CPU_SUBTYPE_ARM64_ALL:
1209 return Triple("arm64-apple-darwin");
1210 default:
1211 return Triple();
1212 }
1213 case MachO::CPU_TYPE_POWERPC:
1214 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1215 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1216 return Triple("ppc-apple-darwin");
1217 default:
1218 return Triple();
1219 }
1220 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001221 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001222 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1223 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001224 default:
1225 return Triple();
1226 }
1227 default:
1228 return Triple();
1229 }
1230}
1231
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001232Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1233 const char **McpuDefault) {
1234 if (McpuDefault)
1235 *McpuDefault = nullptr;
1236
1237 switch (CPUType) {
1238 case MachO::CPU_TYPE_ARM:
1239 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1240 case MachO::CPU_SUBTYPE_ARM_V4T:
1241 return Triple("thumbv4t-apple-darwin");
1242 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1243 return Triple("thumbv5e-apple-darwin");
1244 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1245 return Triple("xscale-apple-darwin");
1246 case MachO::CPU_SUBTYPE_ARM_V6:
1247 return Triple("thumbv6-apple-darwin");
1248 case MachO::CPU_SUBTYPE_ARM_V6M:
1249 if (McpuDefault)
1250 *McpuDefault = "cortex-m0";
1251 return Triple("thumbv6m-apple-darwin");
1252 case MachO::CPU_SUBTYPE_ARM_V7:
1253 return Triple("thumbv7-apple-darwin");
1254 case MachO::CPU_SUBTYPE_ARM_V7EM:
1255 if (McpuDefault)
1256 *McpuDefault = "cortex-m4";
1257 return Triple("thumbv7em-apple-darwin");
1258 case MachO::CPU_SUBTYPE_ARM_V7K:
1259 return Triple("thumbv7k-apple-darwin");
1260 case MachO::CPU_SUBTYPE_ARM_V7M:
1261 if (McpuDefault)
1262 *McpuDefault = "cortex-m3";
1263 return Triple("thumbv7m-apple-darwin");
1264 case MachO::CPU_SUBTYPE_ARM_V7S:
1265 return Triple("thumbv7s-apple-darwin");
1266 default:
1267 return Triple();
1268 }
1269 default:
1270 return Triple();
1271 }
1272}
1273
1274Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
NAKAMURA Takumi0a7d0ad2015-09-22 11:15:07 +00001275 const char **McpuDefault, Triple *ThumbTriple) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001276 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1277 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1278 McpuDefault);
1279 return T;
1280}
1281
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001282Triple MachOObjectFile::getHostArch() {
1283 return Triple(sys::getDefaultTargetTriple());
1284}
1285
Rafael Espindola72318b42014-08-08 16:30:17 +00001286bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1287 return StringSwitch<bool>(ArchFlag)
1288 .Case("i386", true)
1289 .Case("x86_64", true)
1290 .Case("x86_64h", true)
1291 .Case("armv4t", true)
1292 .Case("arm", true)
1293 .Case("armv5e", true)
1294 .Case("armv6", true)
1295 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001296 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001297 .Case("armv7em", true)
1298 .Case("armv7k", true)
1299 .Case("armv7m", true)
1300 .Case("armv7s", true)
1301 .Case("arm64", true)
1302 .Case("ppc", true)
1303 .Case("ppc64", true)
1304 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001305}
1306
Alexey Samsonove6388e62013-06-18 15:03:28 +00001307unsigned MachOObjectFile::getArch() const {
1308 return getArch(getCPUType(this));
1309}
1310
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001311Triple MachOObjectFile::getArch(const char **McpuDefault,
1312 Triple *ThumbTriple) const {
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001313 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1314 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001315}
1316
Rui Ueyamabc654b12013-09-27 21:47:05 +00001317relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001318 DataRefImpl DRI;
1319 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001320 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001321}
1322
Rui Ueyamabc654b12013-09-27 21:47:05 +00001323relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001324 DataRefImpl DRI;
1325 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001326 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001327}
1328
Kevin Enderby273ae012013-06-06 17:20:50 +00001329dice_iterator MachOObjectFile::begin_dices() const {
1330 DataRefImpl DRI;
1331 if (!DataInCodeLoadCmd)
1332 return dice_iterator(DiceRef(DRI, this));
1333
Charles Davis8bdfafd2013-09-01 04:28:48 +00001334 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1335 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001336 return dice_iterator(DiceRef(DRI, this));
1337}
1338
1339dice_iterator MachOObjectFile::end_dices() const {
1340 DataRefImpl DRI;
1341 if (!DataInCodeLoadCmd)
1342 return dice_iterator(DiceRef(DRI, this));
1343
Charles Davis8bdfafd2013-09-01 04:28:48 +00001344 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1345 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001346 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1347 return dice_iterator(DiceRef(DRI, this));
1348}
1349
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001350ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1351 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001352
1353void ExportEntry::moveToFirst() {
1354 pushNode(0);
1355 pushDownUntilBottom();
1356}
1357
1358void ExportEntry::moveToEnd() {
1359 Stack.clear();
1360 Done = true;
1361}
1362
1363bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001364 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001365 if (Done || Other.Done)
1366 return (Done == Other.Done);
1367 // Not equal if different stack sizes.
1368 if (Stack.size() != Other.Stack.size())
1369 return false;
1370 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001371 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001372 return false;
1373 // Equal if all nodes in both stacks match.
1374 for (unsigned i=0; i < Stack.size(); ++i) {
1375 if (Stack[i].Start != Other.Stack[i].Start)
1376 return false;
1377 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001378 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001379}
1380
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001381uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1382 unsigned Count;
1383 uint64_t Result = decodeULEB128(Ptr, &Count);
1384 Ptr += Count;
1385 if (Ptr > Trie.end()) {
1386 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001387 Malformed = true;
1388 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001389 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001390}
1391
1392StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001393 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001394}
1395
1396uint64_t ExportEntry::flags() const {
1397 return Stack.back().Flags;
1398}
1399
1400uint64_t ExportEntry::address() const {
1401 return Stack.back().Address;
1402}
1403
1404uint64_t ExportEntry::other() const {
1405 return Stack.back().Other;
1406}
1407
1408StringRef ExportEntry::otherName() const {
1409 const char* ImportName = Stack.back().ImportName;
1410 if (ImportName)
1411 return StringRef(ImportName);
1412 return StringRef();
1413}
1414
1415uint32_t ExportEntry::nodeOffset() const {
1416 return Stack.back().Start - Trie.begin();
1417}
1418
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001419ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1420 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1421 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1422 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001423
1424void ExportEntry::pushNode(uint64_t offset) {
1425 const uint8_t *Ptr = Trie.begin() + offset;
1426 NodeState State(Ptr);
1427 uint64_t ExportInfoSize = readULEB128(State.Current);
1428 State.IsExportNode = (ExportInfoSize != 0);
1429 const uint8_t* Children = State.Current + ExportInfoSize;
1430 if (State.IsExportNode) {
1431 State.Flags = readULEB128(State.Current);
1432 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1433 State.Address = 0;
1434 State.Other = readULEB128(State.Current); // dylib ordinal
1435 State.ImportName = reinterpret_cast<const char*>(State.Current);
1436 } else {
1437 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001438 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001439 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001440 }
1441 }
1442 State.ChildCount = *Children;
1443 State.Current = Children + 1;
1444 State.NextChildIndex = 0;
1445 State.ParentStringLength = CumulativeString.size();
1446 Stack.push_back(State);
1447}
1448
1449void ExportEntry::pushDownUntilBottom() {
1450 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1451 NodeState &Top = Stack.back();
1452 CumulativeString.resize(Top.ParentStringLength);
1453 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001454 char C = *Top.Current;
1455 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001456 }
1457 Top.Current += 1;
1458 uint64_t childNodeIndex = readULEB128(Top.Current);
1459 Top.NextChildIndex += 1;
1460 pushNode(childNodeIndex);
1461 }
1462 if (!Stack.back().IsExportNode) {
1463 Malformed = true;
1464 moveToEnd();
1465 }
1466}
1467
1468// We have a trie data structure and need a way to walk it that is compatible
1469// with the C++ iterator model. The solution is a non-recursive depth first
1470// traversal where the iterator contains a stack of parent nodes along with a
1471// string that is the accumulation of all edge strings along the parent chain
1472// to this point.
1473//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001474// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001475// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001476// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001477//
1478// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1479// child until hitting a node with no children (which is an export node or
1480// else the trie is malformed). On the way down, each node is pushed on the
1481// stack ivar. If there is no more ways down, it pops up one and tries to go
1482// down a sibling path until a childless node is reached.
1483void ExportEntry::moveNext() {
1484 if (Stack.empty() || !Stack.back().IsExportNode) {
1485 Malformed = true;
1486 moveToEnd();
1487 return;
1488 }
1489
1490 Stack.pop_back();
1491 while (!Stack.empty()) {
1492 NodeState &Top = Stack.back();
1493 if (Top.NextChildIndex < Top.ChildCount) {
1494 pushDownUntilBottom();
1495 // Now at the next export node.
1496 return;
1497 } else {
1498 if (Top.IsExportNode) {
1499 // This node has no children but is itself an export node.
1500 CumulativeString.resize(Top.ParentStringLength);
1501 return;
1502 }
1503 Stack.pop_back();
1504 }
1505 }
1506 Done = true;
1507}
1508
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001509iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00001510MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1511 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001512 if (Trie.size() == 0)
1513 Start.moveToEnd();
1514 else
1515 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001516
1517 ExportEntry Finish(Trie);
1518 Finish.moveToEnd();
1519
Craig Topper15576e12015-12-06 05:08:07 +00001520 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00001521}
1522
1523iterator_range<export_iterator> MachOObjectFile::exports() const {
1524 return exports(getDyldInfoExportsTrie());
1525}
1526
Nick Kledzikac431442014-09-12 21:34:15 +00001527MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1528 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1529 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1530 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1531
1532void MachORebaseEntry::moveToFirst() {
1533 Ptr = Opcodes.begin();
1534 moveNext();
1535}
1536
1537void MachORebaseEntry::moveToEnd() {
1538 Ptr = Opcodes.end();
1539 RemainingLoopCount = 0;
1540 Done = true;
1541}
1542
1543void MachORebaseEntry::moveNext() {
1544 // If in the middle of some loop, move to next rebasing in loop.
1545 SegmentOffset += AdvanceAmount;
1546 if (RemainingLoopCount) {
1547 --RemainingLoopCount;
1548 return;
1549 }
1550 if (Ptr == Opcodes.end()) {
1551 Done = true;
1552 return;
1553 }
1554 bool More = true;
1555 while (More && !Malformed) {
1556 // Parse next opcode and set up next loop.
1557 uint8_t Byte = *Ptr++;
1558 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1559 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1560 switch (Opcode) {
1561 case MachO::REBASE_OPCODE_DONE:
1562 More = false;
1563 Done = true;
1564 moveToEnd();
1565 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1566 break;
1567 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1568 RebaseType = ImmValue;
1569 DEBUG_WITH_TYPE(
1570 "mach-o-rebase",
1571 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1572 << "RebaseType=" << (int) RebaseType << "\n");
1573 break;
1574 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1575 SegmentIndex = ImmValue;
1576 SegmentOffset = readULEB128();
1577 DEBUG_WITH_TYPE(
1578 "mach-o-rebase",
1579 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1580 << "SegmentIndex=" << SegmentIndex << ", "
1581 << format("SegmentOffset=0x%06X", SegmentOffset)
1582 << "\n");
1583 break;
1584 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1585 SegmentOffset += readULEB128();
1586 DEBUG_WITH_TYPE("mach-o-rebase",
1587 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1588 << format("SegmentOffset=0x%06X",
1589 SegmentOffset) << "\n");
1590 break;
1591 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1592 SegmentOffset += ImmValue * PointerSize;
1593 DEBUG_WITH_TYPE("mach-o-rebase",
1594 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1595 << format("SegmentOffset=0x%06X",
1596 SegmentOffset) << "\n");
1597 break;
1598 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1599 AdvanceAmount = PointerSize;
1600 RemainingLoopCount = ImmValue - 1;
1601 DEBUG_WITH_TYPE(
1602 "mach-o-rebase",
1603 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1604 << format("SegmentOffset=0x%06X", SegmentOffset)
1605 << ", AdvanceAmount=" << AdvanceAmount
1606 << ", RemainingLoopCount=" << RemainingLoopCount
1607 << "\n");
1608 return;
1609 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1610 AdvanceAmount = PointerSize;
1611 RemainingLoopCount = readULEB128() - 1;
1612 DEBUG_WITH_TYPE(
1613 "mach-o-rebase",
1614 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1615 << format("SegmentOffset=0x%06X", SegmentOffset)
1616 << ", AdvanceAmount=" << AdvanceAmount
1617 << ", RemainingLoopCount=" << RemainingLoopCount
1618 << "\n");
1619 return;
1620 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1621 AdvanceAmount = readULEB128() + PointerSize;
1622 RemainingLoopCount = 0;
1623 DEBUG_WITH_TYPE(
1624 "mach-o-rebase",
1625 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1626 << format("SegmentOffset=0x%06X", SegmentOffset)
1627 << ", AdvanceAmount=" << AdvanceAmount
1628 << ", RemainingLoopCount=" << RemainingLoopCount
1629 << "\n");
1630 return;
1631 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1632 RemainingLoopCount = readULEB128() - 1;
1633 AdvanceAmount = readULEB128() + PointerSize;
1634 DEBUG_WITH_TYPE(
1635 "mach-o-rebase",
1636 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1637 << format("SegmentOffset=0x%06X", SegmentOffset)
1638 << ", AdvanceAmount=" << AdvanceAmount
1639 << ", RemainingLoopCount=" << RemainingLoopCount
1640 << "\n");
1641 return;
1642 default:
1643 Malformed = true;
1644 }
1645 }
1646}
1647
1648uint64_t MachORebaseEntry::readULEB128() {
1649 unsigned Count;
1650 uint64_t Result = decodeULEB128(Ptr, &Count);
1651 Ptr += Count;
1652 if (Ptr > Opcodes.end()) {
1653 Ptr = Opcodes.end();
1654 Malformed = true;
1655 }
1656 return Result;
1657}
1658
1659uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1660
1661uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1662
1663StringRef MachORebaseEntry::typeName() const {
1664 switch (RebaseType) {
1665 case MachO::REBASE_TYPE_POINTER:
1666 return "pointer";
1667 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1668 return "text abs32";
1669 case MachO::REBASE_TYPE_TEXT_PCREL32:
1670 return "text rel32";
1671 }
1672 return "unknown";
1673}
1674
1675bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1676 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1677 return (Ptr == Other.Ptr) &&
1678 (RemainingLoopCount == Other.RemainingLoopCount) &&
1679 (Done == Other.Done);
1680}
1681
1682iterator_range<rebase_iterator>
1683MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1684 MachORebaseEntry Start(Opcodes, is64);
1685 Start.moveToFirst();
1686
1687 MachORebaseEntry Finish(Opcodes, is64);
1688 Finish.moveToEnd();
1689
Craig Topper15576e12015-12-06 05:08:07 +00001690 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00001691}
1692
1693iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1694 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1695}
1696
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001697MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00001698 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1699 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1700 BindType(0), PointerSize(is64Bit ? 8 : 4),
1701 TableKind(BK), Malformed(false), Done(false) {}
1702
1703void MachOBindEntry::moveToFirst() {
1704 Ptr = Opcodes.begin();
1705 moveNext();
1706}
1707
1708void MachOBindEntry::moveToEnd() {
1709 Ptr = Opcodes.end();
1710 RemainingLoopCount = 0;
1711 Done = true;
1712}
1713
1714void MachOBindEntry::moveNext() {
1715 // If in the middle of some loop, move to next binding in loop.
1716 SegmentOffset += AdvanceAmount;
1717 if (RemainingLoopCount) {
1718 --RemainingLoopCount;
1719 return;
1720 }
1721 if (Ptr == Opcodes.end()) {
1722 Done = true;
1723 return;
1724 }
1725 bool More = true;
1726 while (More && !Malformed) {
1727 // Parse next opcode and set up next loop.
1728 uint8_t Byte = *Ptr++;
1729 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1730 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1731 int8_t SignExtended;
1732 const uint8_t *SymStart;
1733 switch (Opcode) {
1734 case MachO::BIND_OPCODE_DONE:
1735 if (TableKind == Kind::Lazy) {
1736 // Lazying bindings have a DONE opcode between entries. Need to ignore
1737 // it to advance to next entry. But need not if this is last entry.
1738 bool NotLastEntry = false;
1739 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1740 if (*P) {
1741 NotLastEntry = true;
1742 }
1743 }
1744 if (NotLastEntry)
1745 break;
1746 }
1747 More = false;
1748 Done = true;
1749 moveToEnd();
1750 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1751 break;
1752 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1753 Ordinal = ImmValue;
1754 DEBUG_WITH_TYPE(
1755 "mach-o-bind",
1756 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1757 << "Ordinal=" << Ordinal << "\n");
1758 break;
1759 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1760 Ordinal = readULEB128();
1761 DEBUG_WITH_TYPE(
1762 "mach-o-bind",
1763 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1764 << "Ordinal=" << Ordinal << "\n");
1765 break;
1766 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1767 if (ImmValue) {
1768 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1769 Ordinal = SignExtended;
1770 } else
1771 Ordinal = 0;
1772 DEBUG_WITH_TYPE(
1773 "mach-o-bind",
1774 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1775 << "Ordinal=" << Ordinal << "\n");
1776 break;
1777 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1778 Flags = ImmValue;
1779 SymStart = Ptr;
1780 while (*Ptr) {
1781 ++Ptr;
1782 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001783 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1784 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001785 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001786 DEBUG_WITH_TYPE(
1787 "mach-o-bind",
1788 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1789 << "SymbolName=" << SymbolName << "\n");
1790 if (TableKind == Kind::Weak) {
1791 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1792 return;
1793 }
1794 break;
1795 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1796 BindType = ImmValue;
1797 DEBUG_WITH_TYPE(
1798 "mach-o-bind",
1799 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1800 << "BindType=" << (int)BindType << "\n");
1801 break;
1802 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1803 Addend = readSLEB128();
1804 if (TableKind == Kind::Lazy)
1805 Malformed = true;
1806 DEBUG_WITH_TYPE(
1807 "mach-o-bind",
1808 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1809 << "Addend=" << Addend << "\n");
1810 break;
1811 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1812 SegmentIndex = ImmValue;
1813 SegmentOffset = readULEB128();
1814 DEBUG_WITH_TYPE(
1815 "mach-o-bind",
1816 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1817 << "SegmentIndex=" << SegmentIndex << ", "
1818 << format("SegmentOffset=0x%06X", SegmentOffset)
1819 << "\n");
1820 break;
1821 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1822 SegmentOffset += readULEB128();
1823 DEBUG_WITH_TYPE("mach-o-bind",
1824 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1825 << format("SegmentOffset=0x%06X",
1826 SegmentOffset) << "\n");
1827 break;
1828 case MachO::BIND_OPCODE_DO_BIND:
1829 AdvanceAmount = PointerSize;
1830 RemainingLoopCount = 0;
1831 DEBUG_WITH_TYPE("mach-o-bind",
1832 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1833 << format("SegmentOffset=0x%06X",
1834 SegmentOffset) << "\n");
1835 return;
1836 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001837 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001838 RemainingLoopCount = 0;
1839 if (TableKind == Kind::Lazy)
1840 Malformed = true;
1841 DEBUG_WITH_TYPE(
1842 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001843 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001844 << format("SegmentOffset=0x%06X", SegmentOffset)
1845 << ", AdvanceAmount=" << AdvanceAmount
1846 << ", RemainingLoopCount=" << RemainingLoopCount
1847 << "\n");
1848 return;
1849 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001850 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001851 RemainingLoopCount = 0;
1852 if (TableKind == Kind::Lazy)
1853 Malformed = true;
1854 DEBUG_WITH_TYPE("mach-o-bind",
1855 llvm::dbgs()
1856 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1857 << format("SegmentOffset=0x%06X",
1858 SegmentOffset) << "\n");
1859 return;
1860 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1861 RemainingLoopCount = readULEB128() - 1;
1862 AdvanceAmount = readULEB128() + PointerSize;
1863 if (TableKind == Kind::Lazy)
1864 Malformed = true;
1865 DEBUG_WITH_TYPE(
1866 "mach-o-bind",
1867 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1868 << format("SegmentOffset=0x%06X", SegmentOffset)
1869 << ", AdvanceAmount=" << AdvanceAmount
1870 << ", RemainingLoopCount=" << RemainingLoopCount
1871 << "\n");
1872 return;
1873 default:
1874 Malformed = true;
1875 }
1876 }
1877}
1878
1879uint64_t MachOBindEntry::readULEB128() {
1880 unsigned Count;
1881 uint64_t Result = decodeULEB128(Ptr, &Count);
1882 Ptr += Count;
1883 if (Ptr > Opcodes.end()) {
1884 Ptr = Opcodes.end();
1885 Malformed = true;
1886 }
1887 return Result;
1888}
1889
1890int64_t MachOBindEntry::readSLEB128() {
1891 unsigned Count;
1892 int64_t Result = decodeSLEB128(Ptr, &Count);
1893 Ptr += Count;
1894 if (Ptr > Opcodes.end()) {
1895 Ptr = Opcodes.end();
1896 Malformed = true;
1897 }
1898 return Result;
1899}
1900
Nick Kledzik56ebef42014-09-16 01:41:51 +00001901uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1902
1903uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1904
1905StringRef MachOBindEntry::typeName() const {
1906 switch (BindType) {
1907 case MachO::BIND_TYPE_POINTER:
1908 return "pointer";
1909 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1910 return "text abs32";
1911 case MachO::BIND_TYPE_TEXT_PCREL32:
1912 return "text rel32";
1913 }
1914 return "unknown";
1915}
1916
1917StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1918
1919int64_t MachOBindEntry::addend() const { return Addend; }
1920
1921uint32_t MachOBindEntry::flags() const { return Flags; }
1922
1923int MachOBindEntry::ordinal() const { return Ordinal; }
1924
1925bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1926 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1927 return (Ptr == Other.Ptr) &&
1928 (RemainingLoopCount == Other.RemainingLoopCount) &&
1929 (Done == Other.Done);
1930}
1931
1932iterator_range<bind_iterator>
1933MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1934 MachOBindEntry::Kind BKind) {
1935 MachOBindEntry Start(Opcodes, is64, BKind);
1936 Start.moveToFirst();
1937
1938 MachOBindEntry Finish(Opcodes, is64, BKind);
1939 Finish.moveToEnd();
1940
Craig Topper15576e12015-12-06 05:08:07 +00001941 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00001942}
1943
1944iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1945 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1946 MachOBindEntry::Kind::Regular);
1947}
1948
1949iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1950 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1951 MachOBindEntry::Kind::Lazy);
1952}
1953
1954iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1955 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1956 MachOBindEntry::Kind::Weak);
1957}
1958
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001959MachOObjectFile::load_command_iterator
1960MachOObjectFile::begin_load_commands() const {
1961 return LoadCommands.begin();
1962}
1963
1964MachOObjectFile::load_command_iterator
1965MachOObjectFile::end_load_commands() const {
1966 return LoadCommands.end();
1967}
1968
1969iterator_range<MachOObjectFile::load_command_iterator>
1970MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00001971 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001972}
1973
Rafael Espindola56f976f2013-04-18 18:08:55 +00001974StringRef
1975MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1976 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1977 return parseSegmentOrSectionName(Raw.data());
1978}
1979
1980ArrayRef<char>
1981MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001982 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001983 const section_base *Base =
1984 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001985 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001986}
1987
1988ArrayRef<char>
1989MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001990 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001991 const section_base *Base =
1992 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001993 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001994}
1995
1996bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00001997MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00001998 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00001999 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002000 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002001 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002002}
2003
Eric Christopher1d62c252013-07-22 22:25:07 +00002004unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002005 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002006 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002007 return RE.r_word1 & 0xffffff;
2008 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002009}
2010
Eric Christopher1d62c252013-07-22 22:25:07 +00002011bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002012 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002013 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002014 return (RE.r_word1 >> 27) & 1;
2015 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002016}
2017
Eric Christopher1d62c252013-07-22 22:25:07 +00002018bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002019 const MachO::any_relocation_info &RE) const {
2020 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002021}
2022
Eric Christopher1d62c252013-07-22 22:25:07 +00002023uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002024 const MachO::any_relocation_info &RE) const {
2025 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002026}
2027
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002028uint32_t MachOObjectFile::getScatteredRelocationType(
2029 const MachO::any_relocation_info &RE) const {
2030 return (RE.r_word0 >> 24) & 0xf;
2031}
2032
Eric Christopher1d62c252013-07-22 22:25:07 +00002033unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002034 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002035 if (isRelocationScattered(RE))
2036 return getScatteredRelocationAddress(RE);
2037 return getPlainRelocationAddress(RE);
2038}
2039
Charles Davis8bdfafd2013-09-01 04:28:48 +00002040unsigned MachOObjectFile::getAnyRelocationPCRel(
2041 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002042 if (isRelocationScattered(RE))
2043 return getScatteredRelocationPCRel(this, RE);
2044 return getPlainRelocationPCRel(this, RE);
2045}
2046
Eric Christopher1d62c252013-07-22 22:25:07 +00002047unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002048 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002049 if (isRelocationScattered(RE))
2050 return getScatteredRelocationLength(RE);
2051 return getPlainRelocationLength(this, RE);
2052}
2053
2054unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002055MachOObjectFile::getAnyRelocationType(
2056 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002057 if (isRelocationScattered(RE))
2058 return getScatteredRelocationType(RE);
2059 return getPlainRelocationType(this, RE);
2060}
2061
Rafael Espindola52501032013-04-30 15:40:54 +00002062SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002063MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002064 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002065 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002066 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002067 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2068 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2069 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002070 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002071 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002072 return SectionRef(DRI, this);
2073}
2074
Charles Davis8bdfafd2013-09-01 04:28:48 +00002075MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002076 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002077 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002078}
2079
Charles Davis8bdfafd2013-09-01 04:28:48 +00002080MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002081 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002082 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002083}
2084
Charles Davis8bdfafd2013-09-01 04:28:48 +00002085MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002086 unsigned Index) const {
2087 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002088 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002089}
2090
Charles Davis8bdfafd2013-09-01 04:28:48 +00002091MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2092 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002093 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002094 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002095}
2096
Charles Davis8bdfafd2013-09-01 04:28:48 +00002097MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002098MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002099 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002100 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002101}
2102
Charles Davis8bdfafd2013-09-01 04:28:48 +00002103MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002104MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002105 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002106 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002107}
2108
Charles Davis8bdfafd2013-09-01 04:28:48 +00002109MachO::linkedit_data_command
2110MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2111 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002112}
2113
Charles Davis8bdfafd2013-09-01 04:28:48 +00002114MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002115MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002116 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002117}
2118
Charles Davis8bdfafd2013-09-01 04:28:48 +00002119MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002120MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002121 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002122}
2123
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002124MachO::linker_option_command
2125MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2126 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002127}
2128
Jim Grosbach448334a2014-03-18 22:09:05 +00002129MachO::version_min_command
2130MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2131 return getStruct<MachO::version_min_command>(this, L.Ptr);
2132}
2133
Tim Northover8f9590b2014-06-30 14:40:57 +00002134MachO::dylib_command
2135MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2136 return getStruct<MachO::dylib_command>(this, L.Ptr);
2137}
2138
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002139MachO::dyld_info_command
2140MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2141 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2142}
2143
2144MachO::dylinker_command
2145MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2146 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2147}
2148
2149MachO::uuid_command
2150MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2151 return getStruct<MachO::uuid_command>(this, L.Ptr);
2152}
2153
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002154MachO::rpath_command
2155MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2156 return getStruct<MachO::rpath_command>(this, L.Ptr);
2157}
2158
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002159MachO::source_version_command
2160MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2161 return getStruct<MachO::source_version_command>(this, L.Ptr);
2162}
2163
2164MachO::entry_point_command
2165MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2166 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2167}
2168
Kevin Enderby0804f4672014-12-16 23:25:52 +00002169MachO::encryption_info_command
2170MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2171 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2172}
2173
Kevin Enderby57538292014-12-17 01:01:30 +00002174MachO::encryption_info_command_64
2175MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2176 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2177}
2178
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002179MachO::sub_framework_command
2180MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2181 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2182}
Tim Northover8f9590b2014-06-30 14:40:57 +00002183
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002184MachO::sub_umbrella_command
2185MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2186 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2187}
2188
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002189MachO::sub_library_command
2190MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2191 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2192}
2193
Kevin Enderby186eac32014-12-19 21:06:24 +00002194MachO::sub_client_command
2195MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2196 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2197}
2198
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002199MachO::routines_command
2200MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2201 return getStruct<MachO::routines_command>(this, L.Ptr);
2202}
2203
2204MachO::routines_command_64
2205MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2206 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2207}
2208
Kevin Enderby48ef5342014-12-23 22:56:39 +00002209MachO::thread_command
2210MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2211 return getStruct<MachO::thread_command>(this, L.Ptr);
2212}
2213
Charles Davis8bdfafd2013-09-01 04:28:48 +00002214MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002215MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002216 DataRefImpl Sec;
2217 Sec.d.a = Rel.d.a;
2218 uint32_t Offset;
2219 if (is64Bit()) {
2220 MachO::section_64 Sect = getSection64(Sec);
2221 Offset = Sect.reloff;
2222 } else {
2223 MachO::section Sect = getSection(Sec);
2224 Offset = Sect.reloff;
2225 }
2226
2227 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2228 getPtr(this, Offset)) + Rel.d.b;
2229 return getStruct<MachO::any_relocation_info>(
2230 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002231}
2232
Charles Davis8bdfafd2013-09-01 04:28:48 +00002233MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002234MachOObjectFile::getDice(DataRefImpl Rel) const {
2235 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002236 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002237}
2238
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002239const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002240 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002241}
2242
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002243const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2244 assert(is64Bit());
2245 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002246}
2247
Charles Davis8bdfafd2013-09-01 04:28:48 +00002248uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2249 const MachO::dysymtab_command &DLC,
2250 unsigned Index) const {
2251 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2252 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002253}
2254
Charles Davis8bdfafd2013-09-01 04:28:48 +00002255MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002256MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2257 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002258 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2259 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002260}
2261
Charles Davis8bdfafd2013-09-01 04:28:48 +00002262MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002263 if (SymtabLoadCmd)
2264 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2265
2266 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2267 MachO::symtab_command Cmd;
2268 Cmd.cmd = MachO::LC_SYMTAB;
2269 Cmd.cmdsize = sizeof(MachO::symtab_command);
2270 Cmd.symoff = 0;
2271 Cmd.nsyms = 0;
2272 Cmd.stroff = 0;
2273 Cmd.strsize = 0;
2274 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002275}
2276
Charles Davis8bdfafd2013-09-01 04:28:48 +00002277MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002278 if (DysymtabLoadCmd)
2279 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2280
2281 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2282 MachO::dysymtab_command Cmd;
2283 Cmd.cmd = MachO::LC_DYSYMTAB;
2284 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2285 Cmd.ilocalsym = 0;
2286 Cmd.nlocalsym = 0;
2287 Cmd.iextdefsym = 0;
2288 Cmd.nextdefsym = 0;
2289 Cmd.iundefsym = 0;
2290 Cmd.nundefsym = 0;
2291 Cmd.tocoff = 0;
2292 Cmd.ntoc = 0;
2293 Cmd.modtaboff = 0;
2294 Cmd.nmodtab = 0;
2295 Cmd.extrefsymoff = 0;
2296 Cmd.nextrefsyms = 0;
2297 Cmd.indirectsymoff = 0;
2298 Cmd.nindirectsyms = 0;
2299 Cmd.extreloff = 0;
2300 Cmd.nextrel = 0;
2301 Cmd.locreloff = 0;
2302 Cmd.nlocrel = 0;
2303 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002304}
2305
Charles Davis8bdfafd2013-09-01 04:28:48 +00002306MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002307MachOObjectFile::getDataInCodeLoadCommand() const {
2308 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002309 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002310
2311 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002312 MachO::linkedit_data_command Cmd;
2313 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2314 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2315 Cmd.dataoff = 0;
2316 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002317 return Cmd;
2318}
2319
Kevin Enderby9a509442015-01-27 21:28:24 +00002320MachO::linkedit_data_command
2321MachOObjectFile::getLinkOptHintsLoadCommand() const {
2322 if (LinkOptHintsLoadCmd)
2323 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2324
2325 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2326 // fields.
2327 MachO::linkedit_data_command Cmd;
2328 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2329 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2330 Cmd.dataoff = 0;
2331 Cmd.datasize = 0;
2332 return Cmd;
2333}
2334
Nick Kledzikd04bc352014-08-30 00:20:14 +00002335ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002336 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002337 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002338
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002339 MachO::dyld_info_command DyldInfo =
2340 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2341 const uint8_t *Ptr =
2342 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00002343 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002344}
2345
2346ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002347 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002348 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002349
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002350 MachO::dyld_info_command DyldInfo =
2351 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2352 const uint8_t *Ptr =
2353 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002354 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002355}
2356
2357ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002358 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002359 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002360
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002361 MachO::dyld_info_command DyldInfo =
2362 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2363 const uint8_t *Ptr =
2364 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002365 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002366}
2367
2368ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002369 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002370 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002371
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002372 MachO::dyld_info_command DyldInfo =
2373 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2374 const uint8_t *Ptr =
2375 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002376 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002377}
2378
2379ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002380 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002381 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002382
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002383 MachO::dyld_info_command DyldInfo =
2384 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2385 const uint8_t *Ptr =
2386 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00002387 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002388}
2389
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002390ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2391 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002392 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00002393 // Returning a pointer is fine as uuid doesn't need endian swapping.
2394 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00002395 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002396}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002397
Rafael Espindola6e040c02013-04-26 20:07:33 +00002398StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002399 MachO::symtab_command S = getSymtabLoadCommand();
2400 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002401}
2402
Rafael Espindola56f976f2013-04-18 18:08:55 +00002403bool MachOObjectFile::is64Bit() const {
2404 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002405 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002406}
2407
2408void MachOObjectFile::ReadULEB128s(uint64_t Index,
2409 SmallVectorImpl<uint64_t> &Out) const {
2410 DataExtractor extractor(ObjectFile::getData(), true, 0);
2411
2412 uint32_t offset = Index;
2413 uint64_t data = 0;
2414 while (uint64_t delta = extractor.getULEB128(&offset)) {
2415 data += delta;
2416 Out.push_back(data);
2417 }
2418}
2419
Rafael Espindolac66d7612014-08-17 19:09:37 +00002420bool MachOObjectFile::isRelocatableObject() const {
2421 return getHeader().filetype == MachO::MH_OBJECT;
2422}
2423
Lang Hamesff044b12016-03-25 23:11:52 +00002424Expected<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002425ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2426 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00002427 if (Magic == "\xFE\xED\xFA\xCE")
Lang Hamesff044b12016-03-25 23:11:52 +00002428 return MachOObjectFile::create(Buffer, false, false);
Lang Hames82627642016-03-25 21:59:14 +00002429 else if (Magic == "\xCE\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002430 return MachOObjectFile::create(Buffer, true, false);
Lang Hames82627642016-03-25 21:59:14 +00002431 else if (Magic == "\xFE\xED\xFA\xCF")
Lang Hamesff044b12016-03-25 23:11:52 +00002432 return MachOObjectFile::create(Buffer, false, true);
Lang Hames82627642016-03-25 21:59:14 +00002433 else if (Magic == "\xCF\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002434 return MachOObjectFile::create(Buffer, true, true);
Lang Hames82627642016-03-25 21:59:14 +00002435 //else
Lang Hamesff044b12016-03-25 23:11:52 +00002436 return malformedError(Buffer.getBufferIdentifier(),
2437 "Unrecognized MachO magic number");
Rafael Espindola56f976f2013-04-18 18:08:55 +00002438}