blob: c6643cb8c0309f38ce82fe8ef9af0bd514953f8d [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);
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000195 if (sizeof(MachOObjectFile::LoadCommandInfo) > Obj->getHeader().sizeofcmds)
196 return malformedError(*Obj, "truncated or malformed object (load command "
197 "0 extends past the end all load commands in the "
198 "file)");
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000199 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
200}
201
Lang Hames9e964f32016-03-25 17:25:34 +0000202static Expected<MachOObjectFile::LoadCommandInfo>
Alexey Samsonov4fdbed32015-06-04 19:34:14 +0000203getNextLoadCommandInfo(const MachOObjectFile *Obj,
204 const MachOObjectFile::LoadCommandInfo &L) {
205 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
206}
207
Alexey Samsonov9f336632015-06-04 19:45:22 +0000208template <typename T>
209static void parseHeader(const MachOObjectFile *Obj, T &Header,
Lang Hames9e964f32016-03-25 17:25:34 +0000210 Error &Err) {
211 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
212 Header = *HeaderOrErr;
Alexey Samsonov9f336632015-06-04 19:45:22 +0000213 else
Lang Hames9e964f32016-03-25 17:25:34 +0000214 Err = HeaderOrErr.takeError();
Alexey Samsonov9f336632015-06-04 19:45:22 +0000215}
216
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000217// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
218// sections to \param Sections, and optionally sets
219// \param IsPageZeroSegment to true.
220template <typename SegmentCmd>
Lang Hames9e964f32016-03-25 17:25:34 +0000221static Error parseSegmentLoadCommand(
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000222 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
223 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
224 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
225 if (Load.C.cmdsize < SegmentLoadSize)
Lang Hames9e964f32016-03-25 17:25:34 +0000226 return malformedError(*Obj,
227 "Mach-O segment load command size is too small",
228 object_error::macho_load_segment_too_small);
229 if (auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr)) {
230 SegmentCmd S = SegOrErr.get();
231 const unsigned SectionSize =
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000232 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
Lang Hames9e964f32016-03-25 17:25:34 +0000233 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
234 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
235 return malformedError(*Obj,
236 "Mach-O segment load command contains too many "
237 "sections",
238 object_error::macho_load_segment_too_many_sections);
239 for (unsigned J = 0; J < S.nsects; ++J) {
240 const char *Sec = getSectionPtr(Obj, Load, J);
241 Sections.push_back(Sec);
242 }
243 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
244 } else
245 return SegOrErr.takeError();
246
247 return Error::success();
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000248}
249
Lang Hames82627642016-03-25 21:59:14 +0000250Expected<std::unique_ptr<MachOObjectFile>>
251MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
252 bool Is64Bits) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000253 Error Err;
Lang Hames82627642016-03-25 21:59:14 +0000254 std::unique_ptr<MachOObjectFile> Obj(
255 new MachOObjectFile(std::move(Object), IsLittleEndian,
256 Is64Bits, Err));
257 if (Err)
258 return std::move(Err);
259 return std::move(Obj);
260}
261
Rafael Espindola48af1c22014-08-19 18:44:46 +0000262MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Lang Hames9e964f32016-03-25 17:25:34 +0000263 bool Is64bits, Error &Err)
Rafael Espindola48af1c22014-08-19 18:44:46 +0000264 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Craig Topper2617dcc2014-04-15 06:32:26 +0000265 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
Kevin Enderby9a509442015-01-27 21:28:24 +0000266 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
267 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
268 HasPageZeroSegment(false) {
Lang Hamesd1af8fc2016-03-25 23:54:32 +0000269 ErrorAsOutParameter ErrAsOutParam(Err);
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000270 if (is64Bit())
Lang Hames9e964f32016-03-25 17:25:34 +0000271 parseHeader(this, Header64, Err);
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000272 else
Lang Hames9e964f32016-03-25 17:25:34 +0000273 parseHeader(this, Header, Err);
274 if (Err)
Alexey Samsonov9f336632015-06-04 19:45:22 +0000275 return;
Alexey Samsonov13415ed2015-06-04 19:22:03 +0000276
277 uint32_t LoadCommandCount = getHeader().ncmds;
Filipe Cabecinhase71bd0c2015-01-06 17:08:26 +0000278 if (LoadCommandCount == 0)
279 return;
280
Lang Hames9e964f32016-03-25 17:25:34 +0000281 LoadCommandInfo Load;
282 if (auto LoadOrErr = getFirstLoadCommandInfo(this))
283 Load = *LoadOrErr;
284 else {
285 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000286 return;
287 }
Lang Hames9e964f32016-03-25 17:25:34 +0000288
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000289 for (unsigned I = 0; I < LoadCommandCount; ++I) {
290 LoadCommands.push_back(Load);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000291 if (Load.C.cmd == MachO::LC_SYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000292 // Multiple symbol tables
293 if (SymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000294 Err = malformedError(*this, "Multiple symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000295 return;
296 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000297 SymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000298 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000299 // Multiple dynamic symbol tables
300 if (DysymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000301 Err = malformedError(*this, "Multiple dynamic symbol tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000302 return;
303 }
Rafael Espindola6e040c02013-04-26 20:07:33 +0000304 DysymtabLoadCmd = Load.Ptr;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000305 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000306 // Multiple data in code tables
307 if (DataInCodeLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000308 Err = malformedError(*this, "Multiple data-in-code tables");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000309 return;
310 }
Kevin Enderby273ae012013-06-06 17:20:50 +0000311 DataInCodeLoadCmd = Load.Ptr;
Kevin Enderby9a509442015-01-27 21:28:24 +0000312 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
313 // Multiple linker optimization hint tables
314 if (LinkOptHintsLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000315 Err = malformedError(*this, "Multiple linker optimization hint tables");
Kevin Enderby9a509442015-01-27 21:28:24 +0000316 return;
317 }
318 LinkOptHintsLoadCmd = Load.Ptr;
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +0000319 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
Nick Kledzikd04bc352014-08-30 00:20:14 +0000320 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000321 // Multiple dyldinfo load commands
322 if (DyldInfoLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000323 Err = malformedError(*this, "Multiple dyldinfo load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000324 return;
325 }
Nick Kledzikd04bc352014-08-30 00:20:14 +0000326 DyldInfoLoadCmd = Load.Ptr;
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000327 } else if (Load.C.cmd == MachO::LC_UUID) {
David Majnemer73cc6ff2014-11-13 19:48:56 +0000328 // Multiple UUID load commands
329 if (UuidLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000330 Err = malformedError(*this, "Multiple UUID load commands");
David Majnemer73cc6ff2014-11-13 19:48:56 +0000331 return;
332 }
Alexander Potapenko6909b5b2014-10-15 23:35:45 +0000333 UuidLoadCmd = Load.Ptr;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000334 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
Lang Hames9e964f32016-03-25 17:25:34 +0000335 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64>(
336 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000337 return;
Alexey Samsonove1a76ab2015-06-04 22:08:37 +0000338 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Lang Hames9e964f32016-03-25 17:25:34 +0000339 if ((Err = parseSegmentLoadCommand<MachO::segment_command>(
340 this, Load, Sections, HasPageZeroSegment)))
Alexey Samsonov074da9b2015-06-04 20:08:52 +0000341 return;
Kevin Enderby980b2582014-06-05 21:21:57 +0000342 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
343 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
344 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
345 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
346 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
347 Libraries.push_back(Load.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000348 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000349 if (I < LoadCommandCount - 1) {
Lang Hames9e964f32016-03-25 17:25:34 +0000350 if (auto LoadOrErr = getNextLoadCommandInfo(this, Load))
351 Load = *LoadOrErr;
352 else {
353 Err = LoadOrErr.takeError();
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000354 return;
355 }
Alexey Samsonovde5a94a2015-06-04 19:57:46 +0000356 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000357 }
Kevin Enderby1829c682016-01-22 22:49:55 +0000358 if (!SymtabLoadCmd) {
359 if (DysymtabLoadCmd) {
Lang Hames9e964f32016-03-25 17:25:34 +0000360 Err = malformedError(*this,
361 "truncated or malformed object (contains "
362 "LC_DYSYMTAB load command without a LC_SYMTAB load "
363 "command)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000364 return;
365 }
366 } else if (DysymtabLoadCmd) {
367 MachO::symtab_command Symtab =
368 getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
369 MachO::dysymtab_command Dysymtab =
370 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
371 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000372 Err = malformedError(*this,
373 "truncated or malformed object (iolocalsym in "
374 "LC_DYSYMTAB load command extends past the end of "
375 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000376 return;
377 }
378 uint64_t big_size = Dysymtab.ilocalsym;
379 big_size += Dysymtab.nlocalsym;
380 if (Dysymtab.nlocalsym != 0 && big_size > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000381 Err = malformedError(*this,
382 "truncated or malformed object (ilocalsym plus "
383 "nlocalsym in LC_DYSYMTAB load command extends past "
384 "the end of the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000385 return;
386 }
387 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000388 Err = malformedError(*this,
389 "truncated or malformed object (nextdefsym in "
390 "LC_DYSYMTAB load command extends past the end of "
391 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000392 return;
393 }
394 big_size = Dysymtab.iextdefsym;
395 big_size += Dysymtab.nextdefsym;
396 if (Dysymtab.nextdefsym != 0 && big_size > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000397 Err = malformedError(*this,
398 "truncated or malformed object (iextdefsym plus "
399 "nextdefsym in LC_DYSYMTAB load command extends "
400 "past the end of the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000401 return;
402 }
403 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000404 Err = malformedError(*this,
405 "truncated or malformed object (nundefsym in "
406 "LC_DYSYMTAB load command extends past the end of "
407 "the symbol table)");
Kevin Enderby1829c682016-01-22 22:49:55 +0000408 return;
409 }
410 big_size = Dysymtab.iundefsym;
411 big_size += Dysymtab.nundefsym;
412 if (Dysymtab.nundefsym != 0 && big_size > Symtab.nsyms) {
Lang Hames9e964f32016-03-25 17:25:34 +0000413 Err = malformedError(*this,
414 "truncated or malformed object (iundefsym plus "
415 "nundefsym in LC_DYSYMTAB load command extends past "
416 "the end of the symbol table");
Kevin Enderby1829c682016-01-22 22:49:55 +0000417 return;
418 }
419 }
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000420 assert(LoadCommands.size() == LoadCommandCount);
Lang Hames9e964f32016-03-25 17:25:34 +0000421
422 Err = Error::success();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000423}
424
Rafael Espindola5e812af2014-01-30 02:49:50 +0000425void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Rafael Espindola75c30362013-04-24 19:47:55 +0000426 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000427 sizeof(MachO::nlist_64) :
428 sizeof(MachO::nlist);
Rafael Espindola75c30362013-04-24 19:47:55 +0000429 Symb.p += SymbolTableEntrySize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000430}
431
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000432ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +0000433 StringRef StringTable = getStringTableData();
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000434 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000435 const char *Start = &StringTable.data()[Entry.n_strx];
Filipe Cabecinhasc552c9a2015-01-15 23:50:44 +0000436 if (Start < getData().begin() || Start >= getData().end())
Kevin Enderbyf681ec52016-01-22 18:47:14 +0000437 return object_error::parse_failed;
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000438 return StringRef(Start);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000439}
440
Rafael Espindola0e77a942014-12-10 20:46:55 +0000441unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
442 DataRefImpl DRI = Sec.getRawDataRefImpl();
443 uint32_t Flags = getSectionFlags(this, DRI);
444 return Flags & MachO::SECTION_TYPE;
445}
446
Rafael Espindola59128922015-06-24 18:14:41 +0000447uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
448 if (is64Bit()) {
449 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
450 return Entry.n_value;
451 }
452 MachO::nlist Entry = getSymbolTableEntry(Sym);
453 return Entry.n_value;
454}
455
Kevin Enderby980b2582014-06-05 21:21:57 +0000456// getIndirectName() returns the name of the alias'ed symbol who's string table
457// index is in the n_value field.
Rafael Espindola3acea392014-06-12 21:46:39 +0000458std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
459 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +0000460 StringRef StringTable = getStringTableData();
Rafael Espindola59128922015-06-24 18:14:41 +0000461 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
462 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
463 return object_error::parse_failed;
464 uint64_t NValue = getNValue(Symb);
Kevin Enderby980b2582014-06-05 21:21:57 +0000465 if (NValue >= StringTable.size())
466 return object_error::parse_failed;
467 const char *Start = &StringTable.data()[NValue];
468 Res = StringRef(Start);
Rui Ueyama7d099192015-06-09 15:20:42 +0000469 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +0000470}
471
Rafael Espindolabe8b0ea2015-07-07 17:12:59 +0000472uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
Rafael Espindola7e7be922015-07-07 15:05:09 +0000473 return getNValue(Sym);
Rafael Espindola991af662015-06-24 19:11:10 +0000474}
475
Rafael Espindolaed067c42015-07-03 18:19:00 +0000476ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
477 return getSymbolValue(Sym);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000478}
479
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000480uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
Rafael Espindola20122a42014-01-31 20:57:12 +0000481 uint32_t flags = getSymbolFlags(DRI);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000482 if (flags & SymbolRef::SF_Common) {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000483 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000484 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000485 }
Rafael Espindolaa4d224722015-05-31 23:52:50 +0000486 return 0;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000487}
488
Rafael Espindolad7a32ea2015-06-24 10:20:30 +0000489uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000490 return getNValue(DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000491}
492
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000493ErrorOr<SymbolRef::Type>
494MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000495 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000496 uint8_t n_type = Entry.n_type;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000497
Rafael Espindola56f976f2013-04-18 18:08:55 +0000498 // If this is a STAB debugging symbol, we can do nothing more.
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000499 if (n_type & MachO::N_STAB)
500 return SymbolRef::ST_Debug;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000501
Charles Davis74ec8b02013-08-27 05:00:13 +0000502 switch (n_type & MachO::N_TYPE) {
503 case MachO::N_UNDF :
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000504 return SymbolRef::ST_Unknown;
Charles Davis74ec8b02013-08-27 05:00:13 +0000505 case MachO::N_SECT :
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000506 ErrorOr<section_iterator> SecOrError = getSymbolSection(Symb);
507 if (!SecOrError)
508 return SecOrError.getError();
509 section_iterator Sec = *SecOrError;
Kuba Breckade833222015-11-12 09:40:29 +0000510 if (Sec->isData() || Sec->isBSS())
511 return SymbolRef::ST_Data;
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000512 return SymbolRef::ST_Function;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000513 }
Rafael Espindola2fa80cc2015-06-26 12:18:49 +0000514 return SymbolRef::ST_Other;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000515}
516
Rafael Espindola20122a42014-01-31 20:57:12 +0000517uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000518 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000519
Charles Davis8bdfafd2013-09-01 04:28:48 +0000520 uint8_t MachOType = Entry.n_type;
521 uint16_t MachOFlags = Entry.n_desc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000522
Rafael Espindola20122a42014-01-31 20:57:12 +0000523 uint32_t Result = SymbolRef::SF_None;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000524
Tim Northovereaef0742014-05-30 13:22:59 +0000525 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
526 Result |= SymbolRef::SF_Indirect;
527
Rafael Espindolaa1356322013-11-02 05:03:24 +0000528 if (MachOType & MachO::N_STAB)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000529 Result |= SymbolRef::SF_FormatSpecific;
530
Charles Davis74ec8b02013-08-27 05:00:13 +0000531 if (MachOType & MachO::N_EXT) {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000532 Result |= SymbolRef::SF_Global;
Charles Davis74ec8b02013-08-27 05:00:13 +0000533 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola05cbccc2015-07-07 13:58:32 +0000534 if (getNValue(DRI))
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000535 Result |= SymbolRef::SF_Common;
Rafael Espindolad8247722015-07-07 14:26:39 +0000536 else
537 Result |= SymbolRef::SF_Undefined;
Rafael Espindolae4dd2e02013-04-29 22:24:22 +0000538 }
Lang Hames7e0692b2015-01-15 22:33:30 +0000539
540 if (!(MachOType & MachO::N_PEXT))
541 Result |= SymbolRef::SF_Exported;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000542 }
543
Charles Davis74ec8b02013-08-27 05:00:13 +0000544 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindola56f976f2013-04-18 18:08:55 +0000545 Result |= SymbolRef::SF_Weak;
546
Kevin Enderbyec5ca032014-08-18 20:21:02 +0000547 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
548 Result |= SymbolRef::SF_Thumb;
549
Charles Davis74ec8b02013-08-27 05:00:13 +0000550 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000551 Result |= SymbolRef::SF_Absolute;
552
Rafael Espindola20122a42014-01-31 20:57:12 +0000553 return Result;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000554}
555
Rafael Espindola8bab8892015-08-07 23:27:14 +0000556ErrorOr<section_iterator>
557MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
Artyom Skrobov78d5daf2014-07-18 09:26:16 +0000558 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000559 uint8_t index = Entry.n_sect;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000560
Rafael Espindola8bab8892015-08-07 23:27:14 +0000561 if (index == 0)
562 return section_end();
563 DataRefImpl DRI;
564 DRI.d.a = index - 1;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000565 if (DRI.d.a >= Sections.size()){
566 // Diagnostic("bad section index (" + index + ") for symbol at index " +
567 // SymbolIndex);
Kevin Enderby1f472ea2016-01-21 21:13:27 +0000568 return object_error::parse_failed;
Kevin Enderby5afbc1c2016-03-23 20:27:00 +0000569 }
Rafael Espindola8bab8892015-08-07 23:27:14 +0000570 return section_iterator(SectionRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000571}
572
Rafael Espindola6bf32212015-06-24 19:57:32 +0000573unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
574 MachO::nlist_base Entry =
575 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
576 return Entry.n_sect - 1;
577}
578
Rafael Espindola5e812af2014-01-30 02:49:50 +0000579void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000580 Sec.d.a++;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000581}
582
Rafael Espindola3acea392014-06-12 21:46:39 +0000583std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
584 StringRef &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000585 ArrayRef<char> Raw = getSectionRawName(Sec);
586 Result = parseSegmentOrSectionName(Raw.data());
Rui Ueyama7d099192015-06-09 15:20:42 +0000587 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000588}
589
Rafael Espindola80291272014-10-08 15:28:58 +0000590uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
591 if (is64Bit())
592 return getSection64(Sec).addr;
593 return getSection(Sec).addr;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000594}
595
Rafael Espindola80291272014-10-08 15:28:58 +0000596uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
Kevin Enderby46e642f2015-10-08 22:50:55 +0000597 // In the case if a malformed Mach-O file where the section offset is past
598 // the end of the file or some part of the section size is past the end of
599 // the file return a size of zero or a size that covers the rest of the file
600 // but does not extend past the end of the file.
601 uint32_t SectOffset, SectType;
602 uint64_t SectSize;
603
604 if (is64Bit()) {
605 MachO::section_64 Sect = getSection64(Sec);
606 SectOffset = Sect.offset;
607 SectSize = Sect.size;
608 SectType = Sect.flags & MachO::SECTION_TYPE;
609 } else {
610 MachO::section Sect = getSection(Sec);
611 SectOffset = Sect.offset;
612 SectSize = Sect.size;
613 SectType = Sect.flags & MachO::SECTION_TYPE;
614 }
615 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
616 return SectSize;
617 uint64_t FileSize = getData().size();
618 if (SectOffset > FileSize)
619 return 0;
620 if (FileSize - SectOffset < SectSize)
621 return FileSize - SectOffset;
622 return SectSize;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000623}
624
Rafael Espindola3acea392014-06-12 21:46:39 +0000625std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
626 StringRef &Res) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000627 uint32_t Offset;
628 uint64_t Size;
629
630 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000631 MachO::section_64 Sect = getSection64(Sec);
632 Offset = Sect.offset;
633 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000634 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000635 MachO::section Sect = getSection(Sec);
636 Offset = Sect.offset;
637 Size = Sect.size;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000638 }
639
640 Res = this->getData().substr(Offset, Size);
Rui Ueyama7d099192015-06-09 15:20:42 +0000641 return std::error_code();
Rafael Espindola56f976f2013-04-18 18:08:55 +0000642}
643
Rafael Espindola80291272014-10-08 15:28:58 +0000644uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000645 uint32_t Align;
646 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000647 MachO::section_64 Sect = getSection64(Sec);
648 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000649 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000650 MachO::section Sect = getSection(Sec);
651 Align = Sect.align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000652 }
653
Rafael Espindola80291272014-10-08 15:28:58 +0000654 return uint64_t(1) << Align;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000655}
656
Rafael Espindola80291272014-10-08 15:28:58 +0000657bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000658 uint32_t Flags = getSectionFlags(this, Sec);
Rafael Espindola80291272014-10-08 15:28:58 +0000659 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000660}
661
Rafael Espindola80291272014-10-08 15:28:58 +0000662bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000663 uint32_t Flags = getSectionFlags(this, Sec);
664 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000665 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
666 !(SectionType == MachO::S_ZEROFILL ||
667 SectionType == MachO::S_GB_ZEROFILL);
Michael J. Spencer800619f2011-09-28 20:57:30 +0000668}
669
Rafael Espindola80291272014-10-08 15:28:58 +0000670bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
Kevin Enderby403258f2014-05-19 20:36:02 +0000671 uint32_t Flags = getSectionFlags(this, Sec);
672 unsigned SectionType = Flags & MachO::SECTION_TYPE;
Rafael Espindola80291272014-10-08 15:28:58 +0000673 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
674 (SectionType == MachO::S_ZEROFILL ||
675 SectionType == MachO::S_GB_ZEROFILL);
Preston Gurd2138ef62012-04-12 20:13:57 +0000676}
677
Rafael Espindola6bf32212015-06-24 19:57:32 +0000678unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
679 return Sec.getRawDataRefImpl().d.a;
680}
681
Rafael Espindola80291272014-10-08 15:28:58 +0000682bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000683 // FIXME: Unimplemented.
Rafael Espindola80291272014-10-08 15:28:58 +0000684 return false;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000685}
686
Steven Wuf2fe0142016-02-29 19:40:10 +0000687bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
688 StringRef SegmentName = getSectionFinalSegmentName(Sec);
689 StringRef SectName;
690 if (!getSectionName(Sec, SectName))
691 return (SegmentName == "__LLVM" && SectName == "__bitcode");
692 return false;
693}
694
Rui Ueyamabc654b12013-09-27 21:47:05 +0000695relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000696 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000697 Ret.d.a = Sec.d.a;
698 Ret.d.b = 0;
Rafael Espindola04d3f492013-04-25 12:45:46 +0000699 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000700}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000701
Rafael Espindola56f976f2013-04-18 18:08:55 +0000702relocation_iterator
Rui Ueyamabc654b12013-09-27 21:47:05 +0000703MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
Rafael Espindola04d3f492013-04-25 12:45:46 +0000704 uint32_t Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000705 if (is64Bit()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000706 MachO::section_64 Sect = getSection64(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000707 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000708 } else {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000709 MachO::section Sect = getSection(Sec);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000710 Num = Sect.nreloc;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000711 }
Eric Christopher7b015c72011-04-22 03:19:48 +0000712
Rafael Espindola56f976f2013-04-18 18:08:55 +0000713 DataRefImpl Ret;
Rafael Espindola128b8112014-04-03 23:51:28 +0000714 Ret.d.a = Sec.d.a;
715 Ret.d.b = Num;
Rafael Espindola56f976f2013-04-18 18:08:55 +0000716 return relocation_iterator(RelocationRef(Ret, this));
717}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000718
Rafael Espindola5e812af2014-01-30 02:49:50 +0000719void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +0000720 ++Rel.d.b;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000721}
Owen Anderson171f4852011-10-24 23:20:07 +0000722
Rafael Espindola96d071c2015-06-29 23:29:12 +0000723uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
Rafael Espindola72475462014-04-04 00:31:12 +0000724 assert(getHeader().filetype == MachO::MH_OBJECT &&
725 "Only implemented for MH_OBJECT");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000726 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000727 return getAnyRelocationAddress(RE);
David Meyer2fc34c52012-03-01 01:36:50 +0000728}
729
Rafael Espindola806f0062013-06-05 01:33:53 +0000730symbol_iterator
731MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000732 MachO::any_relocation_info RE = getRelocation(Rel);
Tim Northover07f99fb2014-07-04 10:57:56 +0000733 if (isRelocationScattered(RE))
734 return symbol_end();
735
Rafael Espindola56f976f2013-04-18 18:08:55 +0000736 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
737 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola806f0062013-06-05 01:33:53 +0000738 if (!isExtern)
Rafael Espindolab5155a52014-02-10 20:24:04 +0000739 return symbol_end();
Rafael Espindola75c30362013-04-24 19:47:55 +0000740
Charles Davis8bdfafd2013-09-01 04:28:48 +0000741 MachO::symtab_command S = getSymtabLoadCommand();
Rafael Espindola75c30362013-04-24 19:47:55 +0000742 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +0000743 sizeof(MachO::nlist_64) :
744 sizeof(MachO::nlist);
745 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +0000746 DataRefImpl Sym;
747 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola806f0062013-06-05 01:33:53 +0000748 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +0000749}
750
Keno Fischerc780e8e2015-05-21 21:24:32 +0000751section_iterator
752MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
753 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
754}
755
Rafael Espindola99c041b2015-06-30 01:53:01 +0000756uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000757 MachO::any_relocation_info RE = getRelocation(Rel);
Rafael Espindola99c041b2015-06-30 01:53:01 +0000758 return getAnyRelocationType(RE);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000759}
760
Rafael Espindola41bb4322015-06-30 04:08:37 +0000761void MachOObjectFile::getRelocationTypeName(
762 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +0000763 StringRef res;
Rafael Espindola99c041b2015-06-30 01:53:01 +0000764 uint64_t RType = getRelocationType(Rel);
Rafael Espindola56f976f2013-04-18 18:08:55 +0000765
766 unsigned Arch = this->getArch();
767
768 switch (Arch) {
769 case Triple::x86: {
770 static const char *const Table[] = {
771 "GENERIC_RELOC_VANILLA",
772 "GENERIC_RELOC_PAIR",
773 "GENERIC_RELOC_SECTDIFF",
774 "GENERIC_RELOC_PB_LA_PTR",
775 "GENERIC_RELOC_LOCAL_SECTDIFF",
776 "GENERIC_RELOC_TLV" };
777
Eric Christopher13250cb2013-12-06 02:33:38 +0000778 if (RType > 5)
Rafael Espindola56f976f2013-04-18 18:08:55 +0000779 res = "Unknown";
780 else
781 res = Table[RType];
782 break;
783 }
784 case Triple::x86_64: {
785 static const char *const Table[] = {
786 "X86_64_RELOC_UNSIGNED",
787 "X86_64_RELOC_SIGNED",
788 "X86_64_RELOC_BRANCH",
789 "X86_64_RELOC_GOT_LOAD",
790 "X86_64_RELOC_GOT",
791 "X86_64_RELOC_SUBTRACTOR",
792 "X86_64_RELOC_SIGNED_1",
793 "X86_64_RELOC_SIGNED_2",
794 "X86_64_RELOC_SIGNED_4",
795 "X86_64_RELOC_TLV" };
796
797 if (RType > 9)
798 res = "Unknown";
799 else
800 res = Table[RType];
801 break;
802 }
803 case Triple::arm: {
804 static const char *const Table[] = {
805 "ARM_RELOC_VANILLA",
806 "ARM_RELOC_PAIR",
807 "ARM_RELOC_SECTDIFF",
808 "ARM_RELOC_LOCAL_SECTDIFF",
809 "ARM_RELOC_PB_LA_PTR",
810 "ARM_RELOC_BR24",
811 "ARM_THUMB_RELOC_BR22",
812 "ARM_THUMB_32BIT_BRANCH",
813 "ARM_RELOC_HALF",
814 "ARM_RELOC_HALF_SECTDIFF" };
815
816 if (RType > 9)
817 res = "Unknown";
818 else
819 res = Table[RType];
820 break;
821 }
Tim Northover00ed9962014-03-29 10:18:08 +0000822 case Triple::aarch64: {
823 static const char *const Table[] = {
824 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
825 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
826 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
827 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
828 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
829 "ARM64_RELOC_ADDEND"
830 };
831
832 if (RType >= array_lengthof(Table))
833 res = "Unknown";
834 else
835 res = Table[RType];
836 break;
837 }
Rafael Espindola56f976f2013-04-18 18:08:55 +0000838 case Triple::ppc: {
839 static const char *const Table[] = {
840 "PPC_RELOC_VANILLA",
841 "PPC_RELOC_PAIR",
842 "PPC_RELOC_BR14",
843 "PPC_RELOC_BR24",
844 "PPC_RELOC_HI16",
845 "PPC_RELOC_LO16",
846 "PPC_RELOC_HA16",
847 "PPC_RELOC_LO14",
848 "PPC_RELOC_SECTDIFF",
849 "PPC_RELOC_PB_LA_PTR",
850 "PPC_RELOC_HI16_SECTDIFF",
851 "PPC_RELOC_LO16_SECTDIFF",
852 "PPC_RELOC_HA16_SECTDIFF",
853 "PPC_RELOC_JBSR",
854 "PPC_RELOC_LO14_SECTDIFF",
855 "PPC_RELOC_LOCAL_SECTDIFF" };
856
Eric Christopher13250cb2013-12-06 02:33:38 +0000857 if (RType > 15)
858 res = "Unknown";
859 else
860 res = Table[RType];
Rafael Espindola56f976f2013-04-18 18:08:55 +0000861 break;
862 }
863 case Triple::UnknownArch:
864 res = "Unknown";
865 break;
866 }
867 Result.append(res.begin(), res.end());
Rafael Espindola56f976f2013-04-18 18:08:55 +0000868}
869
Keno Fischer281b6942015-05-30 19:44:53 +0000870uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
871 MachO::any_relocation_info RE = getRelocation(Rel);
872 return getAnyRelocationLength(RE);
873}
874
Kevin Enderby980b2582014-06-05 21:21:57 +0000875//
876// guessLibraryShortName() is passed a name of a dynamic library and returns a
877// guess on what the short name is. Then name is returned as a substring of the
878// StringRef Name passed in. The name of the dynamic library is recognized as
879// a framework if it has one of the two following forms:
880// Foo.framework/Versions/A/Foo
881// Foo.framework/Foo
882// Where A and Foo can be any string. And may contain a trailing suffix
883// starting with an underbar. If the Name is recognized as a framework then
884// isFramework is set to true else it is set to false. If the Name has a
885// suffix then Suffix is set to the substring in Name that contains the suffix
886// else it is set to a NULL StringRef.
887//
888// The Name of the dynamic library is recognized as a library name if it has
889// one of the two following forms:
890// libFoo.A.dylib
891// libFoo.dylib
892// The library may have a suffix trailing the name Foo of the form:
893// libFoo_profile.A.dylib
894// libFoo_profile.dylib
895//
896// The Name of the dynamic library is also recognized as a library name if it
897// has the following form:
898// Foo.qtx
899//
900// If the Name of the dynamic library is none of the forms above then a NULL
901// StringRef is returned.
902//
903StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
904 bool &isFramework,
905 StringRef &Suffix) {
906 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
907 size_t a, b, c, d, Idx;
908
909 isFramework = false;
910 Suffix = StringRef();
911
912 // Pull off the last component and make Foo point to it
913 a = Name.rfind('/');
914 if (a == Name.npos || a == 0)
915 goto guess_library;
916 Foo = Name.slice(a+1, Name.npos);
917
918 // Look for a suffix starting with a '_'
919 Idx = Foo.rfind('_');
920 if (Idx != Foo.npos && Foo.size() >= 2) {
921 Suffix = Foo.slice(Idx, Foo.npos);
922 Foo = Foo.slice(0, Idx);
923 }
924
925 // First look for the form Foo.framework/Foo
926 b = Name.rfind('/', a);
927 if (b == Name.npos)
928 Idx = 0;
929 else
930 Idx = b+1;
931 F = Name.slice(Idx, Idx + Foo.size());
932 DotFramework = Name.slice(Idx + Foo.size(),
933 Idx + Foo.size() + sizeof(".framework/")-1);
934 if (F == Foo && DotFramework == ".framework/") {
935 isFramework = true;
936 return Foo;
937 }
938
939 // Next look for the form Foo.framework/Versions/A/Foo
940 if (b == Name.npos)
941 goto guess_library;
942 c = Name.rfind('/', b);
943 if (c == Name.npos || c == 0)
944 goto guess_library;
945 V = Name.slice(c+1, Name.npos);
946 if (!V.startswith("Versions/"))
947 goto guess_library;
948 d = Name.rfind('/', c);
949 if (d == Name.npos)
950 Idx = 0;
951 else
952 Idx = d+1;
953 F = Name.slice(Idx, Idx + Foo.size());
954 DotFramework = Name.slice(Idx + Foo.size(),
955 Idx + Foo.size() + sizeof(".framework/")-1);
956 if (F == Foo && DotFramework == ".framework/") {
957 isFramework = true;
958 return Foo;
959 }
960
961guess_library:
962 // pull off the suffix after the "." and make a point to it
963 a = Name.rfind('.');
964 if (a == Name.npos || a == 0)
965 return StringRef();
966 Dylib = Name.slice(a, Name.npos);
967 if (Dylib != ".dylib")
968 goto guess_qtx;
969
970 // First pull off the version letter for the form Foo.A.dylib if any.
971 if (a >= 3) {
972 Dot = Name.slice(a-2, a-1);
973 if (Dot == ".")
974 a = a - 2;
975 }
976
977 b = Name.rfind('/', a);
978 if (b == Name.npos)
979 b = 0;
980 else
981 b = b+1;
982 // ignore any suffix after an underbar like Foo_profile.A.dylib
983 Idx = Name.find('_', b);
984 if (Idx != Name.npos && Idx != b) {
985 Lib = Name.slice(b, Idx);
986 Suffix = Name.slice(Idx, a);
987 }
988 else
989 Lib = Name.slice(b, a);
990 // There are incorrect library names of the form:
991 // libATS.A_profile.dylib so check for these.
992 if (Lib.size() >= 3) {
993 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
994 if (Dot == ".")
995 Lib = Lib.slice(0, Lib.size()-2);
996 }
997 return Lib;
998
999guess_qtx:
1000 Qtx = Name.slice(a, Name.npos);
1001 if (Qtx != ".qtx")
1002 return StringRef();
1003 b = Name.rfind('/', a);
1004 if (b == Name.npos)
1005 Lib = Name.slice(0, a);
1006 else
1007 Lib = Name.slice(b+1, a);
1008 // There are library names of the form: QT.A.qtx so check for these.
1009 if (Lib.size() >= 3) {
1010 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1011 if (Dot == ".")
1012 Lib = Lib.slice(0, Lib.size()-2);
1013 }
1014 return Lib;
1015}
1016
1017// getLibraryShortNameByIndex() is used to get the short name of the library
1018// for an undefined symbol in a linked Mach-O binary that was linked with the
1019// normal two-level namespace default (that is MH_TWOLEVEL in the header).
1020// It is passed the index (0 - based) of the library as translated from
1021// GET_LIBRARY_ORDINAL (1 - based).
Rafael Espindola3acea392014-06-12 21:46:39 +00001022std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
Nick Kledzikd04bc352014-08-30 00:20:14 +00001023 StringRef &Res) const {
Kevin Enderby980b2582014-06-05 21:21:57 +00001024 if (Index >= Libraries.size())
1025 return object_error::parse_failed;
1026
Kevin Enderby980b2582014-06-05 21:21:57 +00001027 // If the cache of LibrariesShortNames is not built up do that first for
1028 // all the Libraries.
1029 if (LibrariesShortNames.size() == 0) {
1030 for (unsigned i = 0; i < Libraries.size(); i++) {
1031 MachO::dylib_command D =
1032 getStruct<MachO::dylib_command>(this, Libraries[i]);
Nick Kledzik30061302014-09-17 00:25:22 +00001033 if (D.dylib.name >= D.cmdsize)
1034 return object_error::parse_failed;
Kevin Enderby4eff6cd2014-06-20 18:07:34 +00001035 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
Kevin Enderby980b2582014-06-05 21:21:57 +00001036 StringRef Name = StringRef(P);
Nick Kledzik30061302014-09-17 00:25:22 +00001037 if (D.dylib.name+Name.size() >= D.cmdsize)
1038 return object_error::parse_failed;
Kevin Enderby980b2582014-06-05 21:21:57 +00001039 StringRef Suffix;
1040 bool isFramework;
1041 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
Nick Kledzik30061302014-09-17 00:25:22 +00001042 if (shortName.empty())
Kevin Enderby980b2582014-06-05 21:21:57 +00001043 LibrariesShortNames.push_back(Name);
1044 else
1045 LibrariesShortNames.push_back(shortName);
1046 }
1047 }
1048
1049 Res = LibrariesShortNames[Index];
Rui Ueyama7d099192015-06-09 15:20:42 +00001050 return std::error_code();
Kevin Enderby980b2582014-06-05 21:21:57 +00001051}
1052
Rafael Espindola76ad2322015-07-06 14:55:37 +00001053section_iterator
1054MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
1055 DataRefImpl Sec;
1056 Sec.d.a = Rel->getRawDataRefImpl().d.a;
1057 return section_iterator(SectionRef(Sec, this));
1058}
1059
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001060basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
Kevin Enderby1829c682016-01-22 22:49:55 +00001061 DataRefImpl DRI;
1062 MachO::symtab_command Symtab = getSymtabLoadCommand();
1063 if (!SymtabLoadCmd || Symtab.nsyms == 0)
1064 return basic_symbol_iterator(SymbolRef(DRI, this));
1065
Lang Hames36072da2014-05-12 21:39:59 +00001066 return getSymbolByIndex(0);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001067}
1068
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001069basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001070 DataRefImpl DRI;
Kevin Enderby1829c682016-01-22 22:49:55 +00001071 MachO::symtab_command Symtab = getSymtabLoadCommand();
1072 if (!SymtabLoadCmd || Symtab.nsyms == 0)
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001073 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola75c30362013-04-24 19:47:55 +00001074
Rafael Espindola75c30362013-04-24 19:47:55 +00001075 unsigned SymbolTableEntrySize = is64Bit() ?
Charles Davis8bdfafd2013-09-01 04:28:48 +00001076 sizeof(MachO::nlist_64) :
1077 sizeof(MachO::nlist);
1078 unsigned Offset = Symtab.symoff +
1079 Symtab.nsyms * SymbolTableEntrySize;
Rafael Espindola75c30362013-04-24 19:47:55 +00001080 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001081 return basic_symbol_iterator(SymbolRef(DRI, this));
Rafael Espindola56f976f2013-04-18 18:08:55 +00001082}
1083
Lang Hames36072da2014-05-12 21:39:59 +00001084basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
Lang Hames36072da2014-05-12 21:39:59 +00001085 MachO::symtab_command Symtab = getSymtabLoadCommand();
Kevin Enderby1829c682016-01-22 22:49:55 +00001086 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
Filipe Cabecinhas40139502015-01-15 22:52:38 +00001087 report_fatal_error("Requested symbol index is out of range.");
Lang Hames36072da2014-05-12 21:39:59 +00001088 unsigned SymbolTableEntrySize =
1089 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Kevin Enderby1829c682016-01-22 22:49:55 +00001090 DataRefImpl DRI;
Lang Hames36072da2014-05-12 21:39:59 +00001091 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1092 DRI.p += Index * SymbolTableEntrySize;
1093 return basic_symbol_iterator(SymbolRef(DRI, this));
1094}
1095
Rafael Espindolab5155a52014-02-10 20:24:04 +00001096section_iterator MachOObjectFile::section_begin() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001097 DataRefImpl DRI;
1098 return section_iterator(SectionRef(DRI, this));
1099}
1100
Rafael Espindolab5155a52014-02-10 20:24:04 +00001101section_iterator MachOObjectFile::section_end() const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00001102 DataRefImpl DRI;
1103 DRI.d.a = Sections.size();
1104 return section_iterator(SectionRef(DRI, this));
1105}
1106
Rafael Espindola56f976f2013-04-18 18:08:55 +00001107uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +00001108 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +00001109}
1110
Rafael Espindola56f976f2013-04-18 18:08:55 +00001111StringRef MachOObjectFile::getFileFormatName() const {
1112 unsigned CPUType = getCPUType(this);
1113 if (!is64Bit()) {
1114 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001115 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001116 return "Mach-O 32-bit i386";
Charles Davis74ec8b02013-08-27 05:00:13 +00001117 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001118 return "Mach-O arm";
Charles Davis74ec8b02013-08-27 05:00:13 +00001119 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001120 return "Mach-O 32-bit ppc";
1121 default:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001122 return "Mach-O 32-bit unknown";
1123 }
1124 }
1125
Rafael Espindola56f976f2013-04-18 18:08:55 +00001126 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001127 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001128 return "Mach-O 64-bit x86-64";
Tim Northover00ed9962014-03-29 10:18:08 +00001129 case llvm::MachO::CPU_TYPE_ARM64:
1130 return "Mach-O arm64";
Charles Davis74ec8b02013-08-27 05:00:13 +00001131 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001132 return "Mach-O 64-bit ppc64";
1133 default:
1134 return "Mach-O 64-bit unknown";
1135 }
1136}
1137
Alexey Samsonove6388e62013-06-18 15:03:28 +00001138Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1139 switch (CPUType) {
Charles Davis74ec8b02013-08-27 05:00:13 +00001140 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001141 return Triple::x86;
Charles Davis74ec8b02013-08-27 05:00:13 +00001142 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001143 return Triple::x86_64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001144 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001145 return Triple::arm;
Tim Northover00ed9962014-03-29 10:18:08 +00001146 case llvm::MachO::CPU_TYPE_ARM64:
Tim Northovere19bed72014-07-23 12:32:47 +00001147 return Triple::aarch64;
Charles Davis74ec8b02013-08-27 05:00:13 +00001148 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001149 return Triple::ppc;
Charles Davis74ec8b02013-08-27 05:00:13 +00001150 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindola56f976f2013-04-18 18:08:55 +00001151 return Triple::ppc64;
1152 default:
1153 return Triple::UnknownArch;
1154 }
1155}
1156
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001157Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1158 const char **McpuDefault) {
1159 if (McpuDefault)
1160 *McpuDefault = nullptr;
1161
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001162 switch (CPUType) {
1163 case MachO::CPU_TYPE_I386:
1164 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1165 case MachO::CPU_SUBTYPE_I386_ALL:
1166 return Triple("i386-apple-darwin");
1167 default:
1168 return Triple();
1169 }
1170 case MachO::CPU_TYPE_X86_64:
1171 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1172 case MachO::CPU_SUBTYPE_X86_64_ALL:
1173 return Triple("x86_64-apple-darwin");
1174 case MachO::CPU_SUBTYPE_X86_64_H:
1175 return Triple("x86_64h-apple-darwin");
1176 default:
1177 return Triple();
1178 }
1179 case MachO::CPU_TYPE_ARM:
1180 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1181 case MachO::CPU_SUBTYPE_ARM_V4T:
1182 return Triple("armv4t-apple-darwin");
1183 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1184 return Triple("armv5e-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001185 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1186 return Triple("xscale-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001187 case MachO::CPU_SUBTYPE_ARM_V6:
1188 return Triple("armv6-apple-darwin");
1189 case MachO::CPU_SUBTYPE_ARM_V6M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001190 if (McpuDefault)
1191 *McpuDefault = "cortex-m0";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001192 return Triple("armv6m-apple-darwin");
Kevin Enderbyae2a9a22014-08-07 21:30:25 +00001193 case MachO::CPU_SUBTYPE_ARM_V7:
1194 return Triple("armv7-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001195 case MachO::CPU_SUBTYPE_ARM_V7EM:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001196 if (McpuDefault)
1197 *McpuDefault = "cortex-m4";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001198 return Triple("armv7em-apple-darwin");
1199 case MachO::CPU_SUBTYPE_ARM_V7K:
1200 return Triple("armv7k-apple-darwin");
1201 case MachO::CPU_SUBTYPE_ARM_V7M:
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001202 if (McpuDefault)
1203 *McpuDefault = "cortex-m3";
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001204 return Triple("armv7m-apple-darwin");
1205 case MachO::CPU_SUBTYPE_ARM_V7S:
1206 return Triple("armv7s-apple-darwin");
1207 default:
1208 return Triple();
1209 }
1210 case MachO::CPU_TYPE_ARM64:
1211 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1212 case MachO::CPU_SUBTYPE_ARM64_ALL:
1213 return Triple("arm64-apple-darwin");
1214 default:
1215 return Triple();
1216 }
1217 case MachO::CPU_TYPE_POWERPC:
1218 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1219 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1220 return Triple("ppc-apple-darwin");
1221 default:
1222 return Triple();
1223 }
1224 case MachO::CPU_TYPE_POWERPC64:
Reid Kleckner4da3d572014-06-30 20:12:59 +00001225 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001226 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1227 return Triple("ppc64-apple-darwin");
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001228 default:
1229 return Triple();
1230 }
1231 default:
1232 return Triple();
1233 }
1234}
1235
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001236Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1237 const char **McpuDefault) {
1238 if (McpuDefault)
1239 *McpuDefault = nullptr;
1240
1241 switch (CPUType) {
1242 case MachO::CPU_TYPE_ARM:
1243 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1244 case MachO::CPU_SUBTYPE_ARM_V4T:
1245 return Triple("thumbv4t-apple-darwin");
1246 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1247 return Triple("thumbv5e-apple-darwin");
1248 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1249 return Triple("xscale-apple-darwin");
1250 case MachO::CPU_SUBTYPE_ARM_V6:
1251 return Triple("thumbv6-apple-darwin");
1252 case MachO::CPU_SUBTYPE_ARM_V6M:
1253 if (McpuDefault)
1254 *McpuDefault = "cortex-m0";
1255 return Triple("thumbv6m-apple-darwin");
1256 case MachO::CPU_SUBTYPE_ARM_V7:
1257 return Triple("thumbv7-apple-darwin");
1258 case MachO::CPU_SUBTYPE_ARM_V7EM:
1259 if (McpuDefault)
1260 *McpuDefault = "cortex-m4";
1261 return Triple("thumbv7em-apple-darwin");
1262 case MachO::CPU_SUBTYPE_ARM_V7K:
1263 return Triple("thumbv7k-apple-darwin");
1264 case MachO::CPU_SUBTYPE_ARM_V7M:
1265 if (McpuDefault)
1266 *McpuDefault = "cortex-m3";
1267 return Triple("thumbv7m-apple-darwin");
1268 case MachO::CPU_SUBTYPE_ARM_V7S:
1269 return Triple("thumbv7s-apple-darwin");
1270 default:
1271 return Triple();
1272 }
1273 default:
1274 return Triple();
1275 }
1276}
1277
1278Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
NAKAMURA Takumi0a7d0ad2015-09-22 11:15:07 +00001279 const char **McpuDefault, Triple *ThumbTriple) {
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001280 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1281 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1282 McpuDefault);
1283 return T;
1284}
1285
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001286Triple MachOObjectFile::getHostArch() {
1287 return Triple(sys::getDefaultTargetTriple());
1288}
1289
Rafael Espindola72318b42014-08-08 16:30:17 +00001290bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1291 return StringSwitch<bool>(ArchFlag)
1292 .Case("i386", true)
1293 .Case("x86_64", true)
1294 .Case("x86_64h", true)
1295 .Case("armv4t", true)
1296 .Case("arm", true)
1297 .Case("armv5e", true)
1298 .Case("armv6", true)
1299 .Case("armv6m", true)
Frederic Riss40baa0a2015-06-16 17:37:03 +00001300 .Case("armv7", true)
Rafael Espindola72318b42014-08-08 16:30:17 +00001301 .Case("armv7em", true)
1302 .Case("armv7k", true)
1303 .Case("armv7m", true)
1304 .Case("armv7s", true)
1305 .Case("arm64", true)
1306 .Case("ppc", true)
1307 .Case("ppc64", true)
1308 .Default(false);
Kevin Enderby4c8dfe42014-06-30 18:45:23 +00001309}
1310
Alexey Samsonove6388e62013-06-18 15:03:28 +00001311unsigned MachOObjectFile::getArch() const {
1312 return getArch(getCPUType(this));
1313}
1314
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001315Triple MachOObjectFile::getArch(const char **McpuDefault,
1316 Triple *ThumbTriple) const {
Alexey Samsonov13415ed2015-06-04 19:22:03 +00001317 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1318 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
Kevin Enderbyec5ca032014-08-18 20:21:02 +00001319}
1320
Rui Ueyamabc654b12013-09-27 21:47:05 +00001321relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001322 DataRefImpl DRI;
1323 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001324 return section_rel_begin(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001325}
1326
Rui Ueyamabc654b12013-09-27 21:47:05 +00001327relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00001328 DataRefImpl DRI;
1329 DRI.d.a = Index;
Rui Ueyamabc654b12013-09-27 21:47:05 +00001330 return section_rel_end(DRI);
Rafael Espindola6e040c02013-04-26 20:07:33 +00001331}
1332
Kevin Enderby273ae012013-06-06 17:20:50 +00001333dice_iterator MachOObjectFile::begin_dices() const {
1334 DataRefImpl DRI;
1335 if (!DataInCodeLoadCmd)
1336 return dice_iterator(DiceRef(DRI, this));
1337
Charles Davis8bdfafd2013-09-01 04:28:48 +00001338 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1339 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
Kevin Enderby273ae012013-06-06 17:20:50 +00001340 return dice_iterator(DiceRef(DRI, this));
1341}
1342
1343dice_iterator MachOObjectFile::end_dices() const {
1344 DataRefImpl DRI;
1345 if (!DataInCodeLoadCmd)
1346 return dice_iterator(DiceRef(DRI, this));
1347
Charles Davis8bdfafd2013-09-01 04:28:48 +00001348 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1349 unsigned Offset = DicLC.dataoff + DicLC.datasize;
Kevin Enderby273ae012013-06-06 17:20:50 +00001350 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1351 return dice_iterator(DiceRef(DRI, this));
1352}
1353
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001354ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1355 : Trie(T), Malformed(false), Done(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001356
1357void ExportEntry::moveToFirst() {
1358 pushNode(0);
1359 pushDownUntilBottom();
1360}
1361
1362void ExportEntry::moveToEnd() {
1363 Stack.clear();
1364 Done = true;
1365}
1366
1367bool ExportEntry::operator==(const ExportEntry &Other) const {
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001368 // Common case, one at end, other iterating from begin.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001369 if (Done || Other.Done)
1370 return (Done == Other.Done);
1371 // Not equal if different stack sizes.
1372 if (Stack.size() != Other.Stack.size())
1373 return false;
1374 // Not equal if different cumulative strings.
Yaron Keren075759a2015-03-30 15:42:36 +00001375 if (!CumulativeString.equals(Other.CumulativeString))
Nick Kledzikd04bc352014-08-30 00:20:14 +00001376 return false;
1377 // Equal if all nodes in both stacks match.
1378 for (unsigned i=0; i < Stack.size(); ++i) {
1379 if (Stack[i].Start != Other.Stack[i].Start)
1380 return false;
1381 }
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001382 return true;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001383}
1384
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001385uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1386 unsigned Count;
1387 uint64_t Result = decodeULEB128(Ptr, &Count);
1388 Ptr += Count;
1389 if (Ptr > Trie.end()) {
1390 Ptr = Trie.end();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001391 Malformed = true;
1392 }
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001393 return Result;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001394}
1395
1396StringRef ExportEntry::name() const {
Yaron Keren075759a2015-03-30 15:42:36 +00001397 return CumulativeString;
Nick Kledzikd04bc352014-08-30 00:20:14 +00001398}
1399
1400uint64_t ExportEntry::flags() const {
1401 return Stack.back().Flags;
1402}
1403
1404uint64_t ExportEntry::address() const {
1405 return Stack.back().Address;
1406}
1407
1408uint64_t ExportEntry::other() const {
1409 return Stack.back().Other;
1410}
1411
1412StringRef ExportEntry::otherName() const {
1413 const char* ImportName = Stack.back().ImportName;
1414 if (ImportName)
1415 return StringRef(ImportName);
1416 return StringRef();
1417}
1418
1419uint32_t ExportEntry::nodeOffset() const {
1420 return Stack.back().Start - Trie.begin();
1421}
1422
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001423ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1424 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1425 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1426 ParentStringLength(0), IsExportNode(false) {}
Nick Kledzikd04bc352014-08-30 00:20:14 +00001427
1428void ExportEntry::pushNode(uint64_t offset) {
1429 const uint8_t *Ptr = Trie.begin() + offset;
1430 NodeState State(Ptr);
1431 uint64_t ExportInfoSize = readULEB128(State.Current);
1432 State.IsExportNode = (ExportInfoSize != 0);
1433 const uint8_t* Children = State.Current + ExportInfoSize;
1434 if (State.IsExportNode) {
1435 State.Flags = readULEB128(State.Current);
1436 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1437 State.Address = 0;
1438 State.Other = readULEB128(State.Current); // dylib ordinal
1439 State.ImportName = reinterpret_cast<const char*>(State.Current);
1440 } else {
1441 State.Address = readULEB128(State.Current);
Nick Kledzik1b591bd2014-08-30 01:57:34 +00001442 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001443 State.Other = readULEB128(State.Current);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001444 }
1445 }
1446 State.ChildCount = *Children;
1447 State.Current = Children + 1;
1448 State.NextChildIndex = 0;
1449 State.ParentStringLength = CumulativeString.size();
1450 Stack.push_back(State);
1451}
1452
1453void ExportEntry::pushDownUntilBottom() {
1454 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1455 NodeState &Top = Stack.back();
1456 CumulativeString.resize(Top.ParentStringLength);
1457 for (;*Top.Current != 0; Top.Current++) {
Nick Kledzikac7cbdc2014-09-02 18:50:24 +00001458 char C = *Top.Current;
1459 CumulativeString.push_back(C);
Nick Kledzikd04bc352014-08-30 00:20:14 +00001460 }
1461 Top.Current += 1;
1462 uint64_t childNodeIndex = readULEB128(Top.Current);
1463 Top.NextChildIndex += 1;
1464 pushNode(childNodeIndex);
1465 }
1466 if (!Stack.back().IsExportNode) {
1467 Malformed = true;
1468 moveToEnd();
1469 }
1470}
1471
1472// We have a trie data structure and need a way to walk it that is compatible
1473// with the C++ iterator model. The solution is a non-recursive depth first
1474// traversal where the iterator contains a stack of parent nodes along with a
1475// string that is the accumulation of all edge strings along the parent chain
1476// to this point.
1477//
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001478// There is one "export" node for each exported symbol. But because some
Nick Kledzikd04bc352014-08-30 00:20:14 +00001479// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
NAKAMURA Takumi84965032015-09-22 11:14:12 +00001480// node may have child nodes too.
Nick Kledzikd04bc352014-08-30 00:20:14 +00001481//
1482// The algorithm for moveNext() is to keep moving down the leftmost unvisited
1483// child until hitting a node with no children (which is an export node or
1484// else the trie is malformed). On the way down, each node is pushed on the
1485// stack ivar. If there is no more ways down, it pops up one and tries to go
1486// down a sibling path until a childless node is reached.
1487void ExportEntry::moveNext() {
1488 if (Stack.empty() || !Stack.back().IsExportNode) {
1489 Malformed = true;
1490 moveToEnd();
1491 return;
1492 }
1493
1494 Stack.pop_back();
1495 while (!Stack.empty()) {
1496 NodeState &Top = Stack.back();
1497 if (Top.NextChildIndex < Top.ChildCount) {
1498 pushDownUntilBottom();
1499 // Now at the next export node.
1500 return;
1501 } else {
1502 if (Top.IsExportNode) {
1503 // This node has no children but is itself an export node.
1504 CumulativeString.resize(Top.ParentStringLength);
1505 return;
1506 }
1507 Stack.pop_back();
1508 }
1509 }
1510 Done = true;
1511}
1512
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00001513iterator_range<export_iterator>
Nick Kledzikd04bc352014-08-30 00:20:14 +00001514MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1515 ExportEntry Start(Trie);
Juergen Ributzka4d7f70d2014-12-19 02:31:01 +00001516 if (Trie.size() == 0)
1517 Start.moveToEnd();
1518 else
1519 Start.moveToFirst();
Nick Kledzikd04bc352014-08-30 00:20:14 +00001520
1521 ExportEntry Finish(Trie);
1522 Finish.moveToEnd();
1523
Craig Topper15576e12015-12-06 05:08:07 +00001524 return make_range(export_iterator(Start), export_iterator(Finish));
Nick Kledzikd04bc352014-08-30 00:20:14 +00001525}
1526
1527iterator_range<export_iterator> MachOObjectFile::exports() const {
1528 return exports(getDyldInfoExportsTrie());
1529}
1530
Nick Kledzikac431442014-09-12 21:34:15 +00001531MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1532 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1533 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1534 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1535
1536void MachORebaseEntry::moveToFirst() {
1537 Ptr = Opcodes.begin();
1538 moveNext();
1539}
1540
1541void MachORebaseEntry::moveToEnd() {
1542 Ptr = Opcodes.end();
1543 RemainingLoopCount = 0;
1544 Done = true;
1545}
1546
1547void MachORebaseEntry::moveNext() {
1548 // If in the middle of some loop, move to next rebasing in loop.
1549 SegmentOffset += AdvanceAmount;
1550 if (RemainingLoopCount) {
1551 --RemainingLoopCount;
1552 return;
1553 }
1554 if (Ptr == Opcodes.end()) {
1555 Done = true;
1556 return;
1557 }
1558 bool More = true;
1559 while (More && !Malformed) {
1560 // Parse next opcode and set up next loop.
1561 uint8_t Byte = *Ptr++;
1562 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1563 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1564 switch (Opcode) {
1565 case MachO::REBASE_OPCODE_DONE:
1566 More = false;
1567 Done = true;
1568 moveToEnd();
1569 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1570 break;
1571 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1572 RebaseType = ImmValue;
1573 DEBUG_WITH_TYPE(
1574 "mach-o-rebase",
1575 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1576 << "RebaseType=" << (int) RebaseType << "\n");
1577 break;
1578 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1579 SegmentIndex = ImmValue;
1580 SegmentOffset = readULEB128();
1581 DEBUG_WITH_TYPE(
1582 "mach-o-rebase",
1583 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1584 << "SegmentIndex=" << SegmentIndex << ", "
1585 << format("SegmentOffset=0x%06X", SegmentOffset)
1586 << "\n");
1587 break;
1588 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1589 SegmentOffset += readULEB128();
1590 DEBUG_WITH_TYPE("mach-o-rebase",
1591 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1592 << format("SegmentOffset=0x%06X",
1593 SegmentOffset) << "\n");
1594 break;
1595 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1596 SegmentOffset += ImmValue * PointerSize;
1597 DEBUG_WITH_TYPE("mach-o-rebase",
1598 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1599 << format("SegmentOffset=0x%06X",
1600 SegmentOffset) << "\n");
1601 break;
1602 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1603 AdvanceAmount = PointerSize;
1604 RemainingLoopCount = ImmValue - 1;
1605 DEBUG_WITH_TYPE(
1606 "mach-o-rebase",
1607 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1608 << format("SegmentOffset=0x%06X", SegmentOffset)
1609 << ", AdvanceAmount=" << AdvanceAmount
1610 << ", RemainingLoopCount=" << RemainingLoopCount
1611 << "\n");
1612 return;
1613 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1614 AdvanceAmount = PointerSize;
1615 RemainingLoopCount = readULEB128() - 1;
1616 DEBUG_WITH_TYPE(
1617 "mach-o-rebase",
1618 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1619 << format("SegmentOffset=0x%06X", SegmentOffset)
1620 << ", AdvanceAmount=" << AdvanceAmount
1621 << ", RemainingLoopCount=" << RemainingLoopCount
1622 << "\n");
1623 return;
1624 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1625 AdvanceAmount = readULEB128() + PointerSize;
1626 RemainingLoopCount = 0;
1627 DEBUG_WITH_TYPE(
1628 "mach-o-rebase",
1629 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1630 << format("SegmentOffset=0x%06X", SegmentOffset)
1631 << ", AdvanceAmount=" << AdvanceAmount
1632 << ", RemainingLoopCount=" << RemainingLoopCount
1633 << "\n");
1634 return;
1635 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1636 RemainingLoopCount = readULEB128() - 1;
1637 AdvanceAmount = readULEB128() + PointerSize;
1638 DEBUG_WITH_TYPE(
1639 "mach-o-rebase",
1640 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1641 << format("SegmentOffset=0x%06X", SegmentOffset)
1642 << ", AdvanceAmount=" << AdvanceAmount
1643 << ", RemainingLoopCount=" << RemainingLoopCount
1644 << "\n");
1645 return;
1646 default:
1647 Malformed = true;
1648 }
1649 }
1650}
1651
1652uint64_t MachORebaseEntry::readULEB128() {
1653 unsigned Count;
1654 uint64_t Result = decodeULEB128(Ptr, &Count);
1655 Ptr += Count;
1656 if (Ptr > Opcodes.end()) {
1657 Ptr = Opcodes.end();
1658 Malformed = true;
1659 }
1660 return Result;
1661}
1662
1663uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1664
1665uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1666
1667StringRef MachORebaseEntry::typeName() const {
1668 switch (RebaseType) {
1669 case MachO::REBASE_TYPE_POINTER:
1670 return "pointer";
1671 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1672 return "text abs32";
1673 case MachO::REBASE_TYPE_TEXT_PCREL32:
1674 return "text rel32";
1675 }
1676 return "unknown";
1677}
1678
1679bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1680 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1681 return (Ptr == Other.Ptr) &&
1682 (RemainingLoopCount == Other.RemainingLoopCount) &&
1683 (Done == Other.Done);
1684}
1685
1686iterator_range<rebase_iterator>
1687MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1688 MachORebaseEntry Start(Opcodes, is64);
1689 Start.moveToFirst();
1690
1691 MachORebaseEntry Finish(Opcodes, is64);
1692 Finish.moveToEnd();
1693
Craig Topper15576e12015-12-06 05:08:07 +00001694 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
Nick Kledzikac431442014-09-12 21:34:15 +00001695}
1696
1697iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1698 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1699}
1700
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00001701MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
Nick Kledzik56ebef42014-09-16 01:41:51 +00001702 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1703 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1704 BindType(0), PointerSize(is64Bit ? 8 : 4),
1705 TableKind(BK), Malformed(false), Done(false) {}
1706
1707void MachOBindEntry::moveToFirst() {
1708 Ptr = Opcodes.begin();
1709 moveNext();
1710}
1711
1712void MachOBindEntry::moveToEnd() {
1713 Ptr = Opcodes.end();
1714 RemainingLoopCount = 0;
1715 Done = true;
1716}
1717
1718void MachOBindEntry::moveNext() {
1719 // If in the middle of some loop, move to next binding in loop.
1720 SegmentOffset += AdvanceAmount;
1721 if (RemainingLoopCount) {
1722 --RemainingLoopCount;
1723 return;
1724 }
1725 if (Ptr == Opcodes.end()) {
1726 Done = true;
1727 return;
1728 }
1729 bool More = true;
1730 while (More && !Malformed) {
1731 // Parse next opcode and set up next loop.
1732 uint8_t Byte = *Ptr++;
1733 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1734 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1735 int8_t SignExtended;
1736 const uint8_t *SymStart;
1737 switch (Opcode) {
1738 case MachO::BIND_OPCODE_DONE:
1739 if (TableKind == Kind::Lazy) {
1740 // Lazying bindings have a DONE opcode between entries. Need to ignore
1741 // it to advance to next entry. But need not if this is last entry.
1742 bool NotLastEntry = false;
1743 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1744 if (*P) {
1745 NotLastEntry = true;
1746 }
1747 }
1748 if (NotLastEntry)
1749 break;
1750 }
1751 More = false;
1752 Done = true;
1753 moveToEnd();
1754 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1755 break;
1756 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1757 Ordinal = ImmValue;
1758 DEBUG_WITH_TYPE(
1759 "mach-o-bind",
1760 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1761 << "Ordinal=" << Ordinal << "\n");
1762 break;
1763 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1764 Ordinal = readULEB128();
1765 DEBUG_WITH_TYPE(
1766 "mach-o-bind",
1767 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1768 << "Ordinal=" << Ordinal << "\n");
1769 break;
1770 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1771 if (ImmValue) {
1772 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1773 Ordinal = SignExtended;
1774 } else
1775 Ordinal = 0;
1776 DEBUG_WITH_TYPE(
1777 "mach-o-bind",
1778 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1779 << "Ordinal=" << Ordinal << "\n");
1780 break;
1781 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1782 Flags = ImmValue;
1783 SymStart = Ptr;
1784 while (*Ptr) {
1785 ++Ptr;
1786 }
Nick Kledzik56ebef42014-09-16 01:41:51 +00001787 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1788 Ptr-SymStart);
Nick Kledzika6375362014-09-17 01:51:43 +00001789 ++Ptr;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001790 DEBUG_WITH_TYPE(
1791 "mach-o-bind",
1792 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1793 << "SymbolName=" << SymbolName << "\n");
1794 if (TableKind == Kind::Weak) {
1795 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1796 return;
1797 }
1798 break;
1799 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1800 BindType = ImmValue;
1801 DEBUG_WITH_TYPE(
1802 "mach-o-bind",
1803 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1804 << "BindType=" << (int)BindType << "\n");
1805 break;
1806 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1807 Addend = readSLEB128();
1808 if (TableKind == Kind::Lazy)
1809 Malformed = true;
1810 DEBUG_WITH_TYPE(
1811 "mach-o-bind",
1812 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1813 << "Addend=" << Addend << "\n");
1814 break;
1815 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1816 SegmentIndex = ImmValue;
1817 SegmentOffset = readULEB128();
1818 DEBUG_WITH_TYPE(
1819 "mach-o-bind",
1820 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1821 << "SegmentIndex=" << SegmentIndex << ", "
1822 << format("SegmentOffset=0x%06X", SegmentOffset)
1823 << "\n");
1824 break;
1825 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1826 SegmentOffset += readULEB128();
1827 DEBUG_WITH_TYPE("mach-o-bind",
1828 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1829 << format("SegmentOffset=0x%06X",
1830 SegmentOffset) << "\n");
1831 break;
1832 case MachO::BIND_OPCODE_DO_BIND:
1833 AdvanceAmount = PointerSize;
1834 RemainingLoopCount = 0;
1835 DEBUG_WITH_TYPE("mach-o-bind",
1836 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1837 << format("SegmentOffset=0x%06X",
1838 SegmentOffset) << "\n");
1839 return;
1840 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001841 AdvanceAmount = readULEB128() + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001842 RemainingLoopCount = 0;
1843 if (TableKind == Kind::Lazy)
1844 Malformed = true;
1845 DEBUG_WITH_TYPE(
1846 "mach-o-bind",
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001847 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
Nick Kledzik56ebef42014-09-16 01:41:51 +00001848 << format("SegmentOffset=0x%06X", SegmentOffset)
1849 << ", AdvanceAmount=" << AdvanceAmount
1850 << ", RemainingLoopCount=" << RemainingLoopCount
1851 << "\n");
1852 return;
1853 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
Nick Kledzik3b2aa052014-10-18 01:21:02 +00001854 AdvanceAmount = ImmValue * PointerSize + PointerSize;
Nick Kledzik56ebef42014-09-16 01:41:51 +00001855 RemainingLoopCount = 0;
1856 if (TableKind == Kind::Lazy)
1857 Malformed = true;
1858 DEBUG_WITH_TYPE("mach-o-bind",
1859 llvm::dbgs()
1860 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1861 << format("SegmentOffset=0x%06X",
1862 SegmentOffset) << "\n");
1863 return;
1864 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1865 RemainingLoopCount = readULEB128() - 1;
1866 AdvanceAmount = readULEB128() + PointerSize;
1867 if (TableKind == Kind::Lazy)
1868 Malformed = true;
1869 DEBUG_WITH_TYPE(
1870 "mach-o-bind",
1871 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1872 << format("SegmentOffset=0x%06X", SegmentOffset)
1873 << ", AdvanceAmount=" << AdvanceAmount
1874 << ", RemainingLoopCount=" << RemainingLoopCount
1875 << "\n");
1876 return;
1877 default:
1878 Malformed = true;
1879 }
1880 }
1881}
1882
1883uint64_t MachOBindEntry::readULEB128() {
1884 unsigned Count;
1885 uint64_t Result = decodeULEB128(Ptr, &Count);
1886 Ptr += Count;
1887 if (Ptr > Opcodes.end()) {
1888 Ptr = Opcodes.end();
1889 Malformed = true;
1890 }
1891 return Result;
1892}
1893
1894int64_t MachOBindEntry::readSLEB128() {
1895 unsigned Count;
1896 int64_t Result = decodeSLEB128(Ptr, &Count);
1897 Ptr += Count;
1898 if (Ptr > Opcodes.end()) {
1899 Ptr = Opcodes.end();
1900 Malformed = true;
1901 }
1902 return Result;
1903}
1904
Nick Kledzik56ebef42014-09-16 01:41:51 +00001905uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1906
1907uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1908
1909StringRef MachOBindEntry::typeName() const {
1910 switch (BindType) {
1911 case MachO::BIND_TYPE_POINTER:
1912 return "pointer";
1913 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1914 return "text abs32";
1915 case MachO::BIND_TYPE_TEXT_PCREL32:
1916 return "text rel32";
1917 }
1918 return "unknown";
1919}
1920
1921StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1922
1923int64_t MachOBindEntry::addend() const { return Addend; }
1924
1925uint32_t MachOBindEntry::flags() const { return Flags; }
1926
1927int MachOBindEntry::ordinal() const { return Ordinal; }
1928
1929bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1930 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1931 return (Ptr == Other.Ptr) &&
1932 (RemainingLoopCount == Other.RemainingLoopCount) &&
1933 (Done == Other.Done);
1934}
1935
1936iterator_range<bind_iterator>
1937MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1938 MachOBindEntry::Kind BKind) {
1939 MachOBindEntry Start(Opcodes, is64, BKind);
1940 Start.moveToFirst();
1941
1942 MachOBindEntry Finish(Opcodes, is64, BKind);
1943 Finish.moveToEnd();
1944
Craig Topper15576e12015-12-06 05:08:07 +00001945 return make_range(bind_iterator(Start), bind_iterator(Finish));
Nick Kledzik56ebef42014-09-16 01:41:51 +00001946}
1947
1948iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1949 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1950 MachOBindEntry::Kind::Regular);
1951}
1952
1953iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1954 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1955 MachOBindEntry::Kind::Lazy);
1956}
1957
1958iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1959 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1960 MachOBindEntry::Kind::Weak);
1961}
1962
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001963MachOObjectFile::load_command_iterator
1964MachOObjectFile::begin_load_commands() const {
1965 return LoadCommands.begin();
1966}
1967
1968MachOObjectFile::load_command_iterator
1969MachOObjectFile::end_load_commands() const {
1970 return LoadCommands.end();
1971}
1972
1973iterator_range<MachOObjectFile::load_command_iterator>
1974MachOObjectFile::load_commands() const {
Craig Topper15576e12015-12-06 05:08:07 +00001975 return make_range(begin_load_commands(), end_load_commands());
Alexey Samsonovd319c4f2015-06-03 22:19:36 +00001976}
1977
Rafael Espindola56f976f2013-04-18 18:08:55 +00001978StringRef
1979MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1980 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1981 return parseSegmentOrSectionName(Raw.data());
1982}
1983
1984ArrayRef<char>
1985MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001986 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001987 const section_base *Base =
1988 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001989 return makeArrayRef(Base->sectname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001990}
1991
1992ArrayRef<char>
1993MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
Rafael Espindola0d85d102015-05-22 14:59:27 +00001994 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00001995 const section_base *Base =
1996 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
Craig Toppere1d12942014-08-27 05:25:25 +00001997 return makeArrayRef(Base->segname);
Rafael Espindola56f976f2013-04-18 18:08:55 +00001998}
1999
2000bool
Charles Davis8bdfafd2013-09-01 04:28:48 +00002001MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002002 const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002003 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
Rafael Espindola56f976f2013-04-18 18:08:55 +00002004 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +00002005 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002006}
2007
Eric Christopher1d62c252013-07-22 22:25:07 +00002008unsigned MachOObjectFile::getPlainRelocationSymbolNum(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002009 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002010 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002011 return RE.r_word1 & 0xffffff;
2012 return RE.r_word1 >> 8;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002013}
2014
Eric Christopher1d62c252013-07-22 22:25:07 +00002015bool MachOObjectFile::getPlainRelocationExternal(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002016 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002017 if (isLittleEndian())
Charles Davis8bdfafd2013-09-01 04:28:48 +00002018 return (RE.r_word1 >> 27) & 1;
2019 return (RE.r_word1 >> 4) & 1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002020}
2021
Eric Christopher1d62c252013-07-22 22:25:07 +00002022bool MachOObjectFile::getScatteredRelocationScattered(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002023 const MachO::any_relocation_info &RE) const {
2024 return RE.r_word0 >> 31;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002025}
2026
Eric Christopher1d62c252013-07-22 22:25:07 +00002027uint32_t MachOObjectFile::getScatteredRelocationValue(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002028 const MachO::any_relocation_info &RE) const {
2029 return RE.r_word1;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002030}
2031
Kevin Enderby9907d0a2014-11-04 00:43:16 +00002032uint32_t MachOObjectFile::getScatteredRelocationType(
2033 const MachO::any_relocation_info &RE) const {
2034 return (RE.r_word0 >> 24) & 0xf;
2035}
2036
Eric Christopher1d62c252013-07-22 22:25:07 +00002037unsigned MachOObjectFile::getAnyRelocationAddress(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002038 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002039 if (isRelocationScattered(RE))
2040 return getScatteredRelocationAddress(RE);
2041 return getPlainRelocationAddress(RE);
2042}
2043
Charles Davis8bdfafd2013-09-01 04:28:48 +00002044unsigned MachOObjectFile::getAnyRelocationPCRel(
2045 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002046 if (isRelocationScattered(RE))
2047 return getScatteredRelocationPCRel(this, RE);
2048 return getPlainRelocationPCRel(this, RE);
2049}
2050
Eric Christopher1d62c252013-07-22 22:25:07 +00002051unsigned MachOObjectFile::getAnyRelocationLength(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002052 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002053 if (isRelocationScattered(RE))
2054 return getScatteredRelocationLength(RE);
2055 return getPlainRelocationLength(this, RE);
2056}
2057
2058unsigned
Charles Davis8bdfafd2013-09-01 04:28:48 +00002059MachOObjectFile::getAnyRelocationType(
2060 const MachO::any_relocation_info &RE) const {
Rafael Espindola56f976f2013-04-18 18:08:55 +00002061 if (isRelocationScattered(RE))
2062 return getScatteredRelocationType(RE);
2063 return getPlainRelocationType(this, RE);
2064}
2065
Rafael Espindola52501032013-04-30 15:40:54 +00002066SectionRef
Keno Fischerc780e8e2015-05-21 21:24:32 +00002067MachOObjectFile::getAnyRelocationSection(
Charles Davis8bdfafd2013-09-01 04:28:48 +00002068 const MachO::any_relocation_info &RE) const {
Rafael Espindola52501032013-04-30 15:40:54 +00002069 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
Rafael Espindolab5155a52014-02-10 20:24:04 +00002070 return *section_end();
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002071 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2072 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2073 return *section_end();
Rafael Espindola52501032013-04-30 15:40:54 +00002074 DataRefImpl DRI;
Rafael Espindola9ac06a02015-06-18 22:38:20 +00002075 DRI.d.a = SecNum - 1;
Rafael Espindola52501032013-04-30 15:40:54 +00002076 return SectionRef(DRI, this);
2077}
2078
Charles Davis8bdfafd2013-09-01 04:28:48 +00002079MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002080 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002081 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002082}
2083
Charles Davis8bdfafd2013-09-01 04:28:48 +00002084MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola62a07cb2015-05-22 15:43:00 +00002085 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
Charles Davis8bdfafd2013-09-01 04:28:48 +00002086 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002087}
2088
Charles Davis8bdfafd2013-09-01 04:28:48 +00002089MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
Rafael Espindola6e040c02013-04-26 20:07:33 +00002090 unsigned Index) const {
2091 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002092 return getStruct<MachO::section>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002093}
2094
Charles Davis8bdfafd2013-09-01 04:28:48 +00002095MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2096 unsigned Index) const {
Rafael Espindola6e040c02013-04-26 20:07:33 +00002097 const char *Sec = getSectionPtr(this, L, Index);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002098 return getStruct<MachO::section_64>(this, Sec);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002099}
2100
Charles Davis8bdfafd2013-09-01 04:28:48 +00002101MachO::nlist
Rafael Espindola56f976f2013-04-18 18:08:55 +00002102MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002103 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002104 return getStruct<MachO::nlist>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002105}
2106
Charles Davis8bdfafd2013-09-01 04:28:48 +00002107MachO::nlist_64
Rafael Espindola56f976f2013-04-18 18:08:55 +00002108MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola75c30362013-04-24 19:47:55 +00002109 const char *P = reinterpret_cast<const char *>(DRI.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002110 return getStruct<MachO::nlist_64>(this, P);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002111}
2112
Charles Davis8bdfafd2013-09-01 04:28:48 +00002113MachO::linkedit_data_command
2114MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2115 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002116}
2117
Charles Davis8bdfafd2013-09-01 04:28:48 +00002118MachO::segment_command
Rafael Espindola6e040c02013-04-26 20:07:33 +00002119MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002120 return getStruct<MachO::segment_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002121}
2122
Charles Davis8bdfafd2013-09-01 04:28:48 +00002123MachO::segment_command_64
Rafael Espindola6e040c02013-04-26 20:07:33 +00002124MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002125 return getStruct<MachO::segment_command_64>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002126}
2127
Kevin Enderbyd0b6b7f2014-12-18 00:53:40 +00002128MachO::linker_option_command
2129MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2130 return getStruct<MachO::linker_option_command>(this, L.Ptr);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002131}
2132
Jim Grosbach448334a2014-03-18 22:09:05 +00002133MachO::version_min_command
2134MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2135 return getStruct<MachO::version_min_command>(this, L.Ptr);
2136}
2137
Tim Northover8f9590b2014-06-30 14:40:57 +00002138MachO::dylib_command
2139MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2140 return getStruct<MachO::dylib_command>(this, L.Ptr);
2141}
2142
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002143MachO::dyld_info_command
2144MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2145 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2146}
2147
2148MachO::dylinker_command
2149MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2150 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2151}
2152
2153MachO::uuid_command
2154MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2155 return getStruct<MachO::uuid_command>(this, L.Ptr);
2156}
2157
Jean-Daniel Dupas00cc1f52014-12-04 07:37:02 +00002158MachO::rpath_command
2159MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2160 return getStruct<MachO::rpath_command>(this, L.Ptr);
2161}
2162
Kevin Enderby8ae63c12014-09-04 16:54:47 +00002163MachO::source_version_command
2164MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2165 return getStruct<MachO::source_version_command>(this, L.Ptr);
2166}
2167
2168MachO::entry_point_command
2169MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2170 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2171}
2172
Kevin Enderby0804f4672014-12-16 23:25:52 +00002173MachO::encryption_info_command
2174MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2175 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2176}
2177
Kevin Enderby57538292014-12-17 01:01:30 +00002178MachO::encryption_info_command_64
2179MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2180 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2181}
2182
Kevin Enderbyb4b79312014-12-18 19:24:35 +00002183MachO::sub_framework_command
2184MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2185 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2186}
Tim Northover8f9590b2014-06-30 14:40:57 +00002187
Kevin Enderbya2bd8d92014-12-18 23:13:26 +00002188MachO::sub_umbrella_command
2189MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2190 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2191}
2192
Kevin Enderby36c8d3a2014-12-19 19:48:16 +00002193MachO::sub_library_command
2194MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2195 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2196}
2197
Kevin Enderby186eac32014-12-19 21:06:24 +00002198MachO::sub_client_command
2199MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2200 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2201}
2202
Kevin Enderby52e4ce42014-12-19 22:25:22 +00002203MachO::routines_command
2204MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2205 return getStruct<MachO::routines_command>(this, L.Ptr);
2206}
2207
2208MachO::routines_command_64
2209MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2210 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2211}
2212
Kevin Enderby48ef5342014-12-23 22:56:39 +00002213MachO::thread_command
2214MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2215 return getStruct<MachO::thread_command>(this, L.Ptr);
2216}
2217
Charles Davis8bdfafd2013-09-01 04:28:48 +00002218MachO::any_relocation_info
Rafael Espindola56f976f2013-04-18 18:08:55 +00002219MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola128b8112014-04-03 23:51:28 +00002220 DataRefImpl Sec;
2221 Sec.d.a = Rel.d.a;
2222 uint32_t Offset;
2223 if (is64Bit()) {
2224 MachO::section_64 Sect = getSection64(Sec);
2225 Offset = Sect.reloff;
2226 } else {
2227 MachO::section Sect = getSection(Sec);
2228 Offset = Sect.reloff;
2229 }
2230
2231 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2232 getPtr(this, Offset)) + Rel.d.b;
2233 return getStruct<MachO::any_relocation_info>(
2234 this, reinterpret_cast<const char *>(P));
Rafael Espindola56f976f2013-04-18 18:08:55 +00002235}
2236
Charles Davis8bdfafd2013-09-01 04:28:48 +00002237MachO::data_in_code_entry
Kevin Enderby273ae012013-06-06 17:20:50 +00002238MachOObjectFile::getDice(DataRefImpl Rel) const {
2239 const char *P = reinterpret_cast<const char *>(Rel.p);
Charles Davis8bdfafd2013-09-01 04:28:48 +00002240 return getStruct<MachO::data_in_code_entry>(this, P);
Kevin Enderby273ae012013-06-06 17:20:50 +00002241}
2242
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002243const MachO::mach_header &MachOObjectFile::getHeader() const {
Alexey Samsonovfa5edc52015-06-04 22:49:55 +00002244 return Header;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002245}
2246
Alexey Samsonov13415ed2015-06-04 19:22:03 +00002247const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2248 assert(is64Bit());
2249 return Header64;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002250}
2251
Charles Davis8bdfafd2013-09-01 04:28:48 +00002252uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2253 const MachO::dysymtab_command &DLC,
2254 unsigned Index) const {
2255 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2256 return getStruct<uint32_t>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002257}
2258
Charles Davis8bdfafd2013-09-01 04:28:48 +00002259MachO::data_in_code_entry
Rafael Espindola6e040c02013-04-26 20:07:33 +00002260MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2261 unsigned Index) const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002262 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2263 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
Rafael Espindola6e040c02013-04-26 20:07:33 +00002264}
2265
Charles Davis8bdfafd2013-09-01 04:28:48 +00002266MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002267 if (SymtabLoadCmd)
2268 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2269
2270 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2271 MachO::symtab_command Cmd;
2272 Cmd.cmd = MachO::LC_SYMTAB;
2273 Cmd.cmdsize = sizeof(MachO::symtab_command);
2274 Cmd.symoff = 0;
2275 Cmd.nsyms = 0;
2276 Cmd.stroff = 0;
2277 Cmd.strsize = 0;
2278 return Cmd;
Rafael Espindola56f976f2013-04-18 18:08:55 +00002279}
2280
Charles Davis8bdfafd2013-09-01 04:28:48 +00002281MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
Kevin Enderby6f326ce2014-10-23 19:37:31 +00002282 if (DysymtabLoadCmd)
2283 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2284
2285 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2286 MachO::dysymtab_command Cmd;
2287 Cmd.cmd = MachO::LC_DYSYMTAB;
2288 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2289 Cmd.ilocalsym = 0;
2290 Cmd.nlocalsym = 0;
2291 Cmd.iextdefsym = 0;
2292 Cmd.nextdefsym = 0;
2293 Cmd.iundefsym = 0;
2294 Cmd.nundefsym = 0;
2295 Cmd.tocoff = 0;
2296 Cmd.ntoc = 0;
2297 Cmd.modtaboff = 0;
2298 Cmd.nmodtab = 0;
2299 Cmd.extrefsymoff = 0;
2300 Cmd.nextrefsyms = 0;
2301 Cmd.indirectsymoff = 0;
2302 Cmd.nindirectsyms = 0;
2303 Cmd.extreloff = 0;
2304 Cmd.nextrel = 0;
2305 Cmd.locreloff = 0;
2306 Cmd.nlocrel = 0;
2307 return Cmd;
Rafael Espindola6e040c02013-04-26 20:07:33 +00002308}
2309
Charles Davis8bdfafd2013-09-01 04:28:48 +00002310MachO::linkedit_data_command
Kevin Enderby273ae012013-06-06 17:20:50 +00002311MachOObjectFile::getDataInCodeLoadCommand() const {
2312 if (DataInCodeLoadCmd)
Charles Davis8bdfafd2013-09-01 04:28:48 +00002313 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
Kevin Enderby273ae012013-06-06 17:20:50 +00002314
2315 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
Charles Davis8bdfafd2013-09-01 04:28:48 +00002316 MachO::linkedit_data_command Cmd;
2317 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2318 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2319 Cmd.dataoff = 0;
2320 Cmd.datasize = 0;
Kevin Enderby273ae012013-06-06 17:20:50 +00002321 return Cmd;
2322}
2323
Kevin Enderby9a509442015-01-27 21:28:24 +00002324MachO::linkedit_data_command
2325MachOObjectFile::getLinkOptHintsLoadCommand() const {
2326 if (LinkOptHintsLoadCmd)
2327 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2328
2329 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2330 // fields.
2331 MachO::linkedit_data_command Cmd;
2332 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2333 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2334 Cmd.dataoff = 0;
2335 Cmd.datasize = 0;
2336 return Cmd;
2337}
2338
Nick Kledzikd04bc352014-08-30 00:20:14 +00002339ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002340 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002341 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002342
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002343 MachO::dyld_info_command DyldInfo =
2344 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2345 const uint8_t *Ptr =
2346 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
Craig Topper0013be12015-09-21 05:32:41 +00002347 return makeArrayRef(Ptr, DyldInfo.rebase_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002348}
2349
2350ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002351 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002352 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002353
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002354 MachO::dyld_info_command DyldInfo =
2355 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2356 const uint8_t *Ptr =
2357 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002358 return makeArrayRef(Ptr, DyldInfo.bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002359}
2360
2361ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002362 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002363 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002364
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002365 MachO::dyld_info_command DyldInfo =
2366 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2367 const uint8_t *Ptr =
2368 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002369 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002370}
2371
2372ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002373 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002374 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002375
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002376 MachO::dyld_info_command DyldInfo =
2377 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2378 const uint8_t *Ptr =
2379 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
Craig Topper0013be12015-09-21 05:32:41 +00002380 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002381}
2382
2383ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
NAKAMURA Takumi10c80e72015-09-22 11:19:03 +00002384 if (!DyldInfoLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002385 return None;
Nick Kledzikd04bc352014-08-30 00:20:14 +00002386
NAKAMURA Takumi70ad98a2015-09-22 11:13:55 +00002387 MachO::dyld_info_command DyldInfo =
2388 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2389 const uint8_t *Ptr =
2390 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
Craig Topper0013be12015-09-21 05:32:41 +00002391 return makeArrayRef(Ptr, DyldInfo.export_size);
Nick Kledzikd04bc352014-08-30 00:20:14 +00002392}
2393
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002394ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2395 if (!UuidLoadCmd)
Craig Topper0013be12015-09-21 05:32:41 +00002396 return None;
Benjamin Kramer014601d2014-10-24 15:52:05 +00002397 // Returning a pointer is fine as uuid doesn't need endian swapping.
2398 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
Craig Topper0013be12015-09-21 05:32:41 +00002399 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
Alexander Potapenko6909b5b2014-10-15 23:35:45 +00002400}
Nick Kledzikd04bc352014-08-30 00:20:14 +00002401
Rafael Espindola6e040c02013-04-26 20:07:33 +00002402StringRef MachOObjectFile::getStringTableData() const {
Charles Davis8bdfafd2013-09-01 04:28:48 +00002403 MachO::symtab_command S = getSymtabLoadCommand();
2404 return getData().substr(S.stroff, S.strsize);
Rafael Espindola6e040c02013-04-26 20:07:33 +00002405}
2406
Rafael Espindola56f976f2013-04-18 18:08:55 +00002407bool MachOObjectFile::is64Bit() const {
2408 return getType() == getMachOType(false, true) ||
Lang Hames84bc8182014-07-15 19:35:22 +00002409 getType() == getMachOType(true, true);
Rafael Espindola56f976f2013-04-18 18:08:55 +00002410}
2411
2412void MachOObjectFile::ReadULEB128s(uint64_t Index,
2413 SmallVectorImpl<uint64_t> &Out) const {
2414 DataExtractor extractor(ObjectFile::getData(), true, 0);
2415
2416 uint32_t offset = Index;
2417 uint64_t data = 0;
2418 while (uint64_t delta = extractor.getULEB128(&offset)) {
2419 data += delta;
2420 Out.push_back(data);
2421 }
2422}
2423
Rafael Espindolac66d7612014-08-17 19:09:37 +00002424bool MachOObjectFile::isRelocatableObject() const {
2425 return getHeader().filetype == MachO::MH_OBJECT;
2426}
2427
Lang Hamesff044b12016-03-25 23:11:52 +00002428Expected<std::unique_ptr<MachOObjectFile>>
Rafael Espindola48af1c22014-08-19 18:44:46 +00002429ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2430 StringRef Magic = Buffer.getBuffer().slice(0, 4);
Lang Hames82627642016-03-25 21:59:14 +00002431 if (Magic == "\xFE\xED\xFA\xCE")
Lang Hamesff044b12016-03-25 23:11:52 +00002432 return MachOObjectFile::create(Buffer, false, false);
David Blaikieb805f732016-03-28 17:45:48 +00002433 if (Magic == "\xCE\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002434 return MachOObjectFile::create(Buffer, true, false);
David Blaikieb805f732016-03-28 17:45:48 +00002435 if (Magic == "\xFE\xED\xFA\xCF")
Lang Hamesff044b12016-03-25 23:11:52 +00002436 return MachOObjectFile::create(Buffer, false, true);
David Blaikieb805f732016-03-28 17:45:48 +00002437 if (Magic == "\xCF\xFA\xED\xFE")
Lang Hamesff044b12016-03-25 23:11:52 +00002438 return MachOObjectFile::create(Buffer, true, true);
Lang Hamesff044b12016-03-25 23:11:52 +00002439 return malformedError(Buffer.getBufferIdentifier(),
2440 "Unrecognized MachO magic number");
Rafael Espindola56f976f2013-04-18 18:08:55 +00002441}