Bug Summary

File:lib/Object/MachOObjectFile.cpp
Warning:line 3962, column 41
The right operand of '-' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name MachOObjectFile.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/lib/Object -I /build/llvm-toolchain-snapshot-7~svn329677/lib/Object -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn329677/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/lib/Object -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-04-11-031539-24776-1 -x c++ /build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp

/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp

1//===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
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
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/None.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/StringSwitch.h"
21#include "llvm/ADT/Triple.h"
22#include "llvm/ADT/Twine.h"
23#include "llvm/BinaryFormat/MachO.h"
24#include "llvm/Object/Error.h"
25#include "llvm/Object/MachO.h"
26#include "llvm/Object/ObjectFile.h"
27#include "llvm/Object/SymbolicFile.h"
28#include "llvm/Support/DataExtractor.h"
29#include "llvm/Support/Debug.h"
30#include "llvm/Support/Error.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/Format.h"
33#include "llvm/Support/Host.h"
34#include "llvm/Support/LEB128.h"
35#include "llvm/Support/MemoryBuffer.h"
36#include "llvm/Support/SwapByteOrder.h"
37#include "llvm/Support/raw_ostream.h"
38#include <algorithm>
39#include <cassert>
40#include <cstddef>
41#include <cstdint>
42#include <cstring>
43#include <limits>
44#include <list>
45#include <memory>
46#include <string>
47#include <system_error>
48
49using namespace llvm;
50using namespace object;
51
52namespace {
53
54 struct section_base {
55 char sectname[16];
56 char segname[16];
57 };
58
59} // end anonymous namespace
60
61static Error malformedError(const Twine &Msg) {
62 return make_error<GenericBinaryError>("truncated or malformed object (" +
63 Msg + ")",
64 object_error::parse_failed);
65}
66
67// FIXME: Replace all uses of this function with getStructOrErr.
68template <typename T>
69static T getStruct(const MachOObjectFile &O, const char *P) {
70 // Don't read before the beginning or past the end of the file
71 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
72 report_fatal_error("Malformed MachO file.");
73
74 T Cmd;
75 memcpy(&Cmd, P, sizeof(T));
76 if (O.isLittleEndian() != sys::IsLittleEndianHost)
77 MachO::swapStruct(Cmd);
78 return Cmd;
79}
80
81template <typename T>
82static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
83 // Don't read before the beginning or past the end of the file
84 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
85 return malformedError("Structure read out-of-range");
86
87 T Cmd;
88 memcpy(&Cmd, P, sizeof(T));
89 if (O.isLittleEndian() != sys::IsLittleEndianHost)
90 MachO::swapStruct(Cmd);
91 return Cmd;
92}
93
94static const char *
95getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
96 unsigned Sec) {
97 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
98
99 bool Is64 = O.is64Bit();
100 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
101 sizeof(MachO::segment_command);
102 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
103 sizeof(MachO::section);
104
105 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
106 return reinterpret_cast<const char*>(SectionAddr);
107}
108
109static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
110 return O.getData().substr(Offset, 1).data();
111}
112
113static MachO::nlist_base
114getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
115 const char *P = reinterpret_cast<const char *>(DRI.p);
116 return getStruct<MachO::nlist_base>(O, P);
117}
118
119static StringRef parseSegmentOrSectionName(const char *P) {
120 if (P[15] == 0)
121 // Null terminated.
122 return P;
123 // Not null terminated, so this is a 16 char string.
124 return StringRef(P, 16);
125}
126
127static unsigned getCPUType(const MachOObjectFile &O) {
128 return O.getHeader().cputype;
129}
130
131static uint32_t
132getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
133 return RE.r_word0;
134}
135
136static unsigned
137getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
138 return RE.r_word0 & 0xffffff;
139}
140
141static bool getPlainRelocationPCRel(const MachOObjectFile &O,
142 const MachO::any_relocation_info &RE) {
143 if (O.isLittleEndian())
144 return (RE.r_word1 >> 24) & 1;
145 return (RE.r_word1 >> 7) & 1;
146}
147
148static bool
149getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
150 return (RE.r_word0 >> 30) & 1;
151}
152
153static unsigned getPlainRelocationLength(const MachOObjectFile &O,
154 const MachO::any_relocation_info &RE) {
155 if (O.isLittleEndian())
156 return (RE.r_word1 >> 25) & 3;
157 return (RE.r_word1 >> 5) & 3;
158}
159
160static unsigned
161getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
162 return (RE.r_word0 >> 28) & 3;
163}
164
165static unsigned getPlainRelocationType(const MachOObjectFile &O,
166 const MachO::any_relocation_info &RE) {
167 if (O.isLittleEndian())
168 return RE.r_word1 >> 28;
169 return RE.r_word1 & 0xf;
170}
171
172static uint32_t getSectionFlags(const MachOObjectFile &O,
173 DataRefImpl Sec) {
174 if (O.is64Bit()) {
175 MachO::section_64 Sect = O.getSection64(Sec);
176 return Sect.flags;
177 }
178 MachO::section Sect = O.getSection(Sec);
179 return Sect.flags;
180}
181
182static Expected<MachOObjectFile::LoadCommandInfo>
183getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
184 uint32_t LoadCommandIndex) {
185 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
186 if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
187 return malformedError("load command " + Twine(LoadCommandIndex) +
188 " extends past end of file");
189 if (CmdOrErr->cmdsize < 8)
190 return malformedError("load command " + Twine(LoadCommandIndex) +
191 " with size less than 8 bytes");
192 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
193 } else
194 return CmdOrErr.takeError();
195}
196
197static Expected<MachOObjectFile::LoadCommandInfo>
198getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
199 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
200 : sizeof(MachO::mach_header);
201 if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
202 return malformedError("load command 0 extends past the end all load "
203 "commands in the file");
204 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
205}
206
207static Expected<MachOObjectFile::LoadCommandInfo>
208getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
209 const MachOObjectFile::LoadCommandInfo &L) {
210 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
211 : sizeof(MachO::mach_header);
212 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
213 Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
214 return malformedError("load command " + Twine(LoadCommandIndex + 1) +
215 " extends past the end all load commands in the file");
216 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
217}
218
219template <typename T>
220static void parseHeader(const MachOObjectFile &Obj, T &Header,
221 Error &Err) {
222 if (sizeof(T) > Obj.getData().size()) {
223 Err = malformedError("the mach header extends past the end of the "
224 "file");
225 return;
226 }
227 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
228 Header = *HeaderOrErr;
229 else
230 Err = HeaderOrErr.takeError();
231}
232
233// This is used to check for overlapping of Mach-O elements.
234struct MachOElement {
235 uint64_t Offset;
236 uint64_t Size;
237 const char *Name;
238};
239
240static Error checkOverlappingElement(std::list<MachOElement> &Elements,
241 uint64_t Offset, uint64_t Size,
242 const char *Name) {
243 if (Size == 0)
244 return Error::success();
245
246 for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
247 auto E = *it;
248 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
249 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
250 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
251 return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
252 " with a size of " + Twine(Size) + ", overlaps " +
253 E.Name + " at offset " + Twine(E.Offset) + " with "
254 "a size of " + Twine(E.Size));
255 auto nt = it;
256 nt++;
257 if (nt != Elements.end()) {
258 auto N = *nt;
259 if (Offset + Size <= N.Offset) {
260 Elements.insert(nt, {Offset, Size, Name});
261 return Error::success();
262 }
263 }
264 }
265 Elements.push_back({Offset, Size, Name});
266 return Error::success();
267}
268
269// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
270// sections to \param Sections, and optionally sets
271// \param IsPageZeroSegment to true.
272template <typename Segment, typename Section>
273static Error parseSegmentLoadCommand(
274 const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
275 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
276 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
277 std::list<MachOElement> &Elements) {
278 const unsigned SegmentLoadSize = sizeof(Segment);
279 if (Load.C.cmdsize < SegmentLoadSize)
280 return malformedError("load command " + Twine(LoadCommandIndex) +
281 " " + CmdName + " cmdsize too small");
282 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
283 Segment S = SegOrErr.get();
284 const unsigned SectionSize = sizeof(Section);
285 uint64_t FileSize = Obj.getData().size();
286 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
287 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
288 return malformedError("load command " + Twine(LoadCommandIndex) +
289 " inconsistent cmdsize in " + CmdName +
290 " for the number of sections");
291 for (unsigned J = 0; J < S.nsects; ++J) {
292 const char *Sec = getSectionPtr(Obj, Load, J);
293 Sections.push_back(Sec);
294 Section s = getStruct<Section>(Obj, Sec);
295 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
296 Obj.getHeader().filetype != MachO::MH_DSYM &&
297 s.flags != MachO::S_ZEROFILL &&
298 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
299 s.offset > FileSize)
300 return malformedError("offset field of section " + Twine(J) + " in " +
301 CmdName + " command " + Twine(LoadCommandIndex) +
302 " extends past the end of the file");
303 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
304 Obj.getHeader().filetype != MachO::MH_DSYM &&
305 s.flags != MachO::S_ZEROFILL &&
306 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
307 s.offset < SizeOfHeaders && s.size != 0)
308 return malformedError("offset field of section " + Twine(J) + " in " +
309 CmdName + " command " + Twine(LoadCommandIndex) +
310 " not past the headers of the file");
311 uint64_t BigSize = s.offset;
312 BigSize += s.size;
313 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
314 Obj.getHeader().filetype != MachO::MH_DSYM &&
315 s.flags != MachO::S_ZEROFILL &&
316 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
317 BigSize > FileSize)
318 return malformedError("offset field plus size field of section " +
319 Twine(J) + " in " + CmdName + " command " +
320 Twine(LoadCommandIndex) +
321 " extends past the end of the file");
322 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
323 Obj.getHeader().filetype != MachO::MH_DSYM &&
324 s.flags != MachO::S_ZEROFILL &&
325 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
326 s.size > S.filesize)
327 return malformedError("size field of section " +
328 Twine(J) + " in " + CmdName + " command " +
329 Twine(LoadCommandIndex) +
330 " greater than the segment");
331 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
332 Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
333 s.addr < S.vmaddr)
334 return malformedError("addr field of section " + Twine(J) + " in " +
335 CmdName + " command " + Twine(LoadCommandIndex) +
336 " less than the segment's vmaddr");
337 BigSize = s.addr;
338 BigSize += s.size;
339 uint64_t BigEnd = S.vmaddr;
340 BigEnd += S.vmsize;
341 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
342 return malformedError("addr field plus size of section " + Twine(J) +
343 " in " + CmdName + " command " +
344 Twine(LoadCommandIndex) +
345 " greater than than "
346 "the segment's vmaddr plus vmsize");
347 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
348 Obj.getHeader().filetype != MachO::MH_DSYM &&
349 s.flags != MachO::S_ZEROFILL &&
350 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
351 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
352 "section contents"))
353 return Err;
354 if (s.reloff > FileSize)
355 return malformedError("reloff field of section " + Twine(J) + " in " +
356 CmdName + " command " + Twine(LoadCommandIndex) +
357 " extends past the end of the file");
358 BigSize = s.nreloc;
359 BigSize *= sizeof(struct MachO::relocation_info);
360 BigSize += s.reloff;
361 if (BigSize > FileSize)
362 return malformedError("reloff field plus nreloc field times sizeof("
363 "struct relocation_info) of section " +
364 Twine(J) + " in " + CmdName + " command " +
365 Twine(LoadCommandIndex) +
366 " extends past the end of the file");
367 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
368 sizeof(struct
369 MachO::relocation_info),
370 "section relocation entries"))
371 return Err;
372 }
373 if (S.fileoff > FileSize)
374 return malformedError("load command " + Twine(LoadCommandIndex) +
375 " fileoff field in " + CmdName +
376 " extends past the end of the file");
377 uint64_t BigSize = S.fileoff;
378 BigSize += S.filesize;
379 if (BigSize > FileSize)
380 return malformedError("load command " + Twine(LoadCommandIndex) +
381 " fileoff field plus filesize field in " +
382 CmdName + " extends past the end of the file");
383 if (S.vmsize != 0 && S.filesize > S.vmsize)
384 return malformedError("load command " + Twine(LoadCommandIndex) +
385 " filesize field in " + CmdName +
386 " greater than vmsize field");
387 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
388 } else
389 return SegOrErr.takeError();
390
391 return Error::success();
392}
393
394static Error checkSymtabCommand(const MachOObjectFile &Obj,
395 const MachOObjectFile::LoadCommandInfo &Load,
396 uint32_t LoadCommandIndex,
397 const char **SymtabLoadCmd,
398 std::list<MachOElement> &Elements) {
399 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
400 return malformedError("load command " + Twine(LoadCommandIndex) +
401 " LC_SYMTAB cmdsize too small");
402 if (*SymtabLoadCmd != nullptr)
403 return malformedError("more than one LC_SYMTAB command");
404 MachO::symtab_command Symtab =
405 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
406 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
407 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
408 " has incorrect cmdsize");
409 uint64_t FileSize = Obj.getData().size();
410 if (Symtab.symoff > FileSize)
411 return malformedError("symoff field of LC_SYMTAB command " +
412 Twine(LoadCommandIndex) + " extends past the end "
413 "of the file");
414 uint64_t SymtabSize = Symtab.nsyms;
415 const char *struct_nlist_name;
416 if (Obj.is64Bit()) {
417 SymtabSize *= sizeof(MachO::nlist_64);
418 struct_nlist_name = "struct nlist_64";
419 } else {
420 SymtabSize *= sizeof(MachO::nlist);
421 struct_nlist_name = "struct nlist";
422 }
423 uint64_t BigSize = SymtabSize;
424 BigSize += Symtab.symoff;
425 if (BigSize > FileSize)
426 return malformedError("symoff field plus nsyms field times sizeof(" +
427 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
428 Twine(LoadCommandIndex) + " extends past the end "
429 "of the file");
430 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
431 "symbol table"))
432 return Err;
433 if (Symtab.stroff > FileSize)
434 return malformedError("stroff field of LC_SYMTAB command " +
435 Twine(LoadCommandIndex) + " extends past the end "
436 "of the file");
437 BigSize = Symtab.stroff;
438 BigSize += Symtab.strsize;
439 if (BigSize > FileSize)
440 return malformedError("stroff field plus strsize field of LC_SYMTAB "
441 "command " + Twine(LoadCommandIndex) + " extends "
442 "past the end of the file");
443 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
444 Symtab.strsize, "string table"))
445 return Err;
446 *SymtabLoadCmd = Load.Ptr;
447 return Error::success();
448}
449
450static Error checkDysymtabCommand(const MachOObjectFile &Obj,
451 const MachOObjectFile::LoadCommandInfo &Load,
452 uint32_t LoadCommandIndex,
453 const char **DysymtabLoadCmd,
454 std::list<MachOElement> &Elements) {
455 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
456 return malformedError("load command " + Twine(LoadCommandIndex) +
457 " LC_DYSYMTAB cmdsize too small");
458 if (*DysymtabLoadCmd != nullptr)
459 return malformedError("more than one LC_DYSYMTAB command");
460 MachO::dysymtab_command Dysymtab =
461 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
462 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
463 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
464 " has incorrect cmdsize");
465 uint64_t FileSize = Obj.getData().size();
466 if (Dysymtab.tocoff > FileSize)
467 return malformedError("tocoff field of LC_DYSYMTAB command " +
468 Twine(LoadCommandIndex) + " extends past the end of "
469 "the file");
470 uint64_t BigSize = Dysymtab.ntoc;
471 BigSize *= sizeof(MachO::dylib_table_of_contents);
472 BigSize += Dysymtab.tocoff;
473 if (BigSize > FileSize)
474 return malformedError("tocoff field plus ntoc field times sizeof(struct "
475 "dylib_table_of_contents) of LC_DYSYMTAB command " +
476 Twine(LoadCommandIndex) + " extends past the end of "
477 "the file");
478 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
479 Dysymtab.ntoc * sizeof(struct
480 MachO::dylib_table_of_contents),
481 "table of contents"))
482 return Err;
483 if (Dysymtab.modtaboff > FileSize)
484 return malformedError("modtaboff field of LC_DYSYMTAB command " +
485 Twine(LoadCommandIndex) + " extends past the end of "
486 "the file");
487 BigSize = Dysymtab.nmodtab;
488 const char *struct_dylib_module_name;
489 uint64_t sizeof_modtab;
490 if (Obj.is64Bit()) {
491 sizeof_modtab = sizeof(MachO::dylib_module_64);
492 struct_dylib_module_name = "struct dylib_module_64";
493 } else {
494 sizeof_modtab = sizeof(MachO::dylib_module);
495 struct_dylib_module_name = "struct dylib_module";
496 }
497 BigSize *= sizeof_modtab;
498 BigSize += Dysymtab.modtaboff;
499 if (BigSize > FileSize)
500 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
501 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
502 "command " + Twine(LoadCommandIndex) + " extends "
503 "past the end of the file");
504 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
505 Dysymtab.nmodtab * sizeof_modtab,
506 "module table"))
507 return Err;
508 if (Dysymtab.extrefsymoff > FileSize)
509 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
510 Twine(LoadCommandIndex) + " extends past the end of "
511 "the file");
512 BigSize = Dysymtab.nextrefsyms;
513 BigSize *= sizeof(MachO::dylib_reference);
514 BigSize += Dysymtab.extrefsymoff;
515 if (BigSize > FileSize)
516 return malformedError("extrefsymoff field plus nextrefsyms field times "
517 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
518 "command " + Twine(LoadCommandIndex) + " extends "
519 "past the end of the file");
520 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
521 Dysymtab.nextrefsyms *
522 sizeof(MachO::dylib_reference),
523 "reference table"))
524 return Err;
525 if (Dysymtab.indirectsymoff > FileSize)
526 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
527 Twine(LoadCommandIndex) + " extends past the end of "
528 "the file");
529 BigSize = Dysymtab.nindirectsyms;
530 BigSize *= sizeof(uint32_t);
531 BigSize += Dysymtab.indirectsymoff;
532 if (BigSize > FileSize)
533 return malformedError("indirectsymoff field plus nindirectsyms field times "
534 "sizeof(uint32_t) of LC_DYSYMTAB command " +
535 Twine(LoadCommandIndex) + " extends past the end of "
536 "the file");
537 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
538 Dysymtab.nindirectsyms *
539 sizeof(uint32_t),
540 "indirect table"))
541 return Err;
542 if (Dysymtab.extreloff > FileSize)
543 return malformedError("extreloff field of LC_DYSYMTAB command " +
544 Twine(LoadCommandIndex) + " extends past the end of "
545 "the file");
546 BigSize = Dysymtab.nextrel;
547 BigSize *= sizeof(MachO::relocation_info);
548 BigSize += Dysymtab.extreloff;
549 if (BigSize > FileSize)
550 return malformedError("extreloff field plus nextrel field times sizeof"
551 "(struct relocation_info) of LC_DYSYMTAB command " +
552 Twine(LoadCommandIndex) + " extends past the end of "
553 "the file");
554 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
555 Dysymtab.nextrel *
556 sizeof(MachO::relocation_info),
557 "external relocation table"))
558 return Err;
559 if (Dysymtab.locreloff > FileSize)
560 return malformedError("locreloff field of LC_DYSYMTAB command " +
561 Twine(LoadCommandIndex) + " extends past the end of "
562 "the file");
563 BigSize = Dysymtab.nlocrel;
564 BigSize *= sizeof(MachO::relocation_info);
565 BigSize += Dysymtab.locreloff;
566 if (BigSize > FileSize)
567 return malformedError("locreloff field plus nlocrel field times sizeof"
568 "(struct relocation_info) of LC_DYSYMTAB command " +
569 Twine(LoadCommandIndex) + " extends past the end of "
570 "the file");
571 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
572 Dysymtab.nlocrel *
573 sizeof(MachO::relocation_info),
574 "local relocation table"))
575 return Err;
576 *DysymtabLoadCmd = Load.Ptr;
577 return Error::success();
578}
579
580static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
581 const MachOObjectFile::LoadCommandInfo &Load,
582 uint32_t LoadCommandIndex,
583 const char **LoadCmd, const char *CmdName,
584 std::list<MachOElement> &Elements,
585 const char *ElementName) {
586 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
587 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
588 CmdName + " cmdsize too small");
589 if (*LoadCmd != nullptr)
590 return malformedError("more than one " + Twine(CmdName) + " command");
591 MachO::linkedit_data_command LinkData =
592 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
593 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
594 return malformedError(Twine(CmdName) + " command " +
595 Twine(LoadCommandIndex) + " has incorrect cmdsize");
596 uint64_t FileSize = Obj.getData().size();
597 if (LinkData.dataoff > FileSize)
598 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
599 Twine(LoadCommandIndex) + " extends past the end of "
600 "the file");
601 uint64_t BigSize = LinkData.dataoff;
602 BigSize += LinkData.datasize;
603 if (BigSize > FileSize)
604 return malformedError("dataoff field plus datasize field of " +
605 Twine(CmdName) + " command " +
606 Twine(LoadCommandIndex) + " extends past the end of "
607 "the file");
608 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
609 LinkData.datasize, ElementName))
610 return Err;
611 *LoadCmd = Load.Ptr;
612 return Error::success();
613}
614
615static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
616 const MachOObjectFile::LoadCommandInfo &Load,
617 uint32_t LoadCommandIndex,
618 const char **LoadCmd, const char *CmdName,
619 std::list<MachOElement> &Elements) {
620 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
621 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
622 CmdName + " cmdsize too small");
623 if (*LoadCmd != nullptr)
624 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
625 "command");
626 MachO::dyld_info_command DyldInfo =
627 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
628 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
629 return malformedError(Twine(CmdName) + " command " +
630 Twine(LoadCommandIndex) + " has incorrect cmdsize");
631 uint64_t FileSize = Obj.getData().size();
632 if (DyldInfo.rebase_off > FileSize)
633 return malformedError("rebase_off field of " + Twine(CmdName) +
634 " command " + Twine(LoadCommandIndex) + " extends "
635 "past the end of the file");
636 uint64_t BigSize = DyldInfo.rebase_off;
637 BigSize += DyldInfo.rebase_size;
638 if (BigSize > FileSize)
639 return malformedError("rebase_off field plus rebase_size field of " +
640 Twine(CmdName) + " command " +
641 Twine(LoadCommandIndex) + " extends past the end of "
642 "the file");
643 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
644 DyldInfo.rebase_size,
645 "dyld rebase info"))
646 return Err;
647 if (DyldInfo.bind_off > FileSize)
648 return malformedError("bind_off field of " + Twine(CmdName) +
649 " command " + Twine(LoadCommandIndex) + " extends "
650 "past the end of the file");
651 BigSize = DyldInfo.bind_off;
652 BigSize += DyldInfo.bind_size;
653 if (BigSize > FileSize)
654 return malformedError("bind_off field plus bind_size field of " +
655 Twine(CmdName) + " command " +
656 Twine(LoadCommandIndex) + " extends past the end of "
657 "the file");
658 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
659 DyldInfo.bind_size,
660 "dyld bind info"))
661 return Err;
662 if (DyldInfo.weak_bind_off > FileSize)
663 return malformedError("weak_bind_off field of " + Twine(CmdName) +
664 " command " + Twine(LoadCommandIndex) + " extends "
665 "past the end of the file");
666 BigSize = DyldInfo.weak_bind_off;
667 BigSize += DyldInfo.weak_bind_size;
668 if (BigSize > FileSize)
669 return malformedError("weak_bind_off field plus weak_bind_size field of " +
670 Twine(CmdName) + " command " +
671 Twine(LoadCommandIndex) + " extends past the end of "
672 "the file");
673 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
674 DyldInfo.weak_bind_size,
675 "dyld weak bind info"))
676 return Err;
677 if (DyldInfo.lazy_bind_off > FileSize)
678 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
679 " command " + Twine(LoadCommandIndex) + " extends "
680 "past the end of the file");
681 BigSize = DyldInfo.lazy_bind_off;
682 BigSize += DyldInfo.lazy_bind_size;
683 if (BigSize > FileSize)
684 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
685 Twine(CmdName) + " command " +
686 Twine(LoadCommandIndex) + " extends past the end of "
687 "the file");
688 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
689 DyldInfo.lazy_bind_size,
690 "dyld lazy bind info"))
691 return Err;
692 if (DyldInfo.export_off > FileSize)
693 return malformedError("export_off field of " + Twine(CmdName) +
694 " command " + Twine(LoadCommandIndex) + " extends "
695 "past the end of the file");
696 BigSize = DyldInfo.export_off;
697 BigSize += DyldInfo.export_size;
698 if (BigSize > FileSize)
699 return malformedError("export_off field plus export_size field of " +
700 Twine(CmdName) + " command " +
701 Twine(LoadCommandIndex) + " extends past the end of "
702 "the file");
703 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
704 DyldInfo.export_size,
705 "dyld export info"))
706 return Err;
707 *LoadCmd = Load.Ptr;
708 return Error::success();
709}
710
711static Error checkDylibCommand(const MachOObjectFile &Obj,
712 const MachOObjectFile::LoadCommandInfo &Load,
713 uint32_t LoadCommandIndex, const char *CmdName) {
714 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
715 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
716 CmdName + " cmdsize too small");
717 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
718 if (D.dylib.name < sizeof(MachO::dylib_command))
719 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
720 CmdName + " name.offset field too small, not past "
721 "the end of the dylib_command struct");
722 if (D.dylib.name >= D.cmdsize)
723 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
724 CmdName + " name.offset field extends past the end "
725 "of the load command");
726 // Make sure there is a null between the starting offset of the name and
727 // the end of the load command.
728 uint32_t i;
729 const char *P = (const char *)Load.Ptr;
730 for (i = D.dylib.name; i < D.cmdsize; i++)
731 if (P[i] == '\0')
732 break;
733 if (i >= D.cmdsize)
734 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
735 CmdName + " library name extends past the end of the "
736 "load command");
737 return Error::success();
738}
739
740static Error checkDylibIdCommand(const MachOObjectFile &Obj,
741 const MachOObjectFile::LoadCommandInfo &Load,
742 uint32_t LoadCommandIndex,
743 const char **LoadCmd) {
744 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
745 "LC_ID_DYLIB"))
746 return Err;
747 if (*LoadCmd != nullptr)
748 return malformedError("more than one LC_ID_DYLIB command");
749 if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
750 Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
751 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
752 "file type");
753 *LoadCmd = Load.Ptr;
754 return Error::success();
755}
756
757static Error checkDyldCommand(const MachOObjectFile &Obj,
758 const MachOObjectFile::LoadCommandInfo &Load,
759 uint32_t LoadCommandIndex, const char *CmdName) {
760 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
761 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
762 CmdName + " cmdsize too small");
763 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
764 if (D.name < sizeof(MachO::dylinker_command))
765 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
766 CmdName + " name.offset field too small, not past "
767 "the end of the dylinker_command struct");
768 if (D.name >= D.cmdsize)
769 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
770 CmdName + " name.offset field extends past the end "
771 "of the load command");
772 // Make sure there is a null between the starting offset of the name and
773 // the end of the load command.
774 uint32_t i;
775 const char *P = (const char *)Load.Ptr;
776 for (i = D.name; i < D.cmdsize; i++)
777 if (P[i] == '\0')
778 break;
779 if (i >= D.cmdsize)
780 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
781 CmdName + " dyld name extends past the end of the "
782 "load command");
783 return Error::success();
784}
785
786static Error checkVersCommand(const MachOObjectFile &Obj,
787 const MachOObjectFile::LoadCommandInfo &Load,
788 uint32_t LoadCommandIndex,
789 const char **LoadCmd, const char *CmdName) {
790 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
791 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
792 CmdName + " has incorrect cmdsize");
793 if (*LoadCmd != nullptr)
794 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
795 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
796 "LC_VERSION_MIN_WATCHOS command");
797 *LoadCmd = Load.Ptr;
798 return Error::success();
799}
800
801static Error checkNoteCommand(const MachOObjectFile &Obj,
802 const MachOObjectFile::LoadCommandInfo &Load,
803 uint32_t LoadCommandIndex,
804 std::list<MachOElement> &Elements) {
805 if (Load.C.cmdsize != sizeof(MachO::note_command))
806 return malformedError("load command " + Twine(LoadCommandIndex) +
807 " LC_NOTE has incorrect cmdsize");
808 MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
809 uint64_t FileSize = Obj.getData().size();
810 if (Nt.offset > FileSize)
811 return malformedError("offset field of LC_NOTE command " +
812 Twine(LoadCommandIndex) + " extends "
813 "past the end of the file");
814 uint64_t BigSize = Nt.offset;
815 BigSize += Nt.size;
816 if (BigSize > FileSize)
817 return malformedError("size field plus offset field of LC_NOTE command " +
818 Twine(LoadCommandIndex) + " extends past the end of "
819 "the file");
820 if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
821 "LC_NOTE data"))
822 return Err;
823 return Error::success();
824}
825
826static Error
827parseBuildVersionCommand(const MachOObjectFile &Obj,
828 const MachOObjectFile::LoadCommandInfo &Load,
829 SmallVectorImpl<const char*> &BuildTools,
830 uint32_t LoadCommandIndex) {
831 MachO::build_version_command BVC =
832 getStruct<MachO::build_version_command>(Obj, Load.Ptr);
833 if (Load.C.cmdsize !=
834 sizeof(MachO::build_version_command) +
835 BVC.ntools * sizeof(MachO::build_tool_version))
836 return malformedError("load command " + Twine(LoadCommandIndex) +
837 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
838
839 auto Start = Load.Ptr + sizeof(MachO::build_version_command);
840 BuildTools.resize(BVC.ntools);
841 for (unsigned i = 0; i < BVC.ntools; ++i)
842 BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
843
844 return Error::success();
845}
846
847static Error checkRpathCommand(const MachOObjectFile &Obj,
848 const MachOObjectFile::LoadCommandInfo &Load,
849 uint32_t LoadCommandIndex) {
850 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
851 return malformedError("load command " + Twine(LoadCommandIndex) +
852 " LC_RPATH cmdsize too small");
853 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
854 if (R.path < sizeof(MachO::rpath_command))
855 return malformedError("load command " + Twine(LoadCommandIndex) +
856 " LC_RPATH path.offset field too small, not past "
857 "the end of the rpath_command struct");
858 if (R.path >= R.cmdsize)
859 return malformedError("load command " + Twine(LoadCommandIndex) +
860 " LC_RPATH path.offset field extends past the end "
861 "of the load command");
862 // Make sure there is a null between the starting offset of the path and
863 // the end of the load command.
864 uint32_t i;
865 const char *P = (const char *)Load.Ptr;
866 for (i = R.path; i < R.cmdsize; i++)
867 if (P[i] == '\0')
868 break;
869 if (i >= R.cmdsize)
870 return malformedError("load command " + Twine(LoadCommandIndex) +
871 " LC_RPATH library name extends past the end of the "
872 "load command");
873 return Error::success();
874}
875
876static Error checkEncryptCommand(const MachOObjectFile &Obj,
877 const MachOObjectFile::LoadCommandInfo &Load,
878 uint32_t LoadCommandIndex,
879 uint64_t cryptoff, uint64_t cryptsize,
880 const char **LoadCmd, const char *CmdName) {
881 if (*LoadCmd != nullptr)
882 return malformedError("more than one LC_ENCRYPTION_INFO and or "
883 "LC_ENCRYPTION_INFO_64 command");
884 uint64_t FileSize = Obj.getData().size();
885 if (cryptoff > FileSize)
886 return malformedError("cryptoff field of " + Twine(CmdName) +
887 " command " + Twine(LoadCommandIndex) + " extends "
888 "past the end of the file");
889 uint64_t BigSize = cryptoff;
890 BigSize += cryptsize;
891 if (BigSize > FileSize)
892 return malformedError("cryptoff field plus cryptsize field of " +
893 Twine(CmdName) + " command " +
894 Twine(LoadCommandIndex) + " extends past the end of "
895 "the file");
896 *LoadCmd = Load.Ptr;
897 return Error::success();
898}
899
900static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
901 const MachOObjectFile::LoadCommandInfo &Load,
902 uint32_t LoadCommandIndex) {
903 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
904 return malformedError("load command " + Twine(LoadCommandIndex) +
905 " LC_LINKER_OPTION cmdsize too small");
906 MachO::linker_option_command L =
907 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
908 // Make sure the count of strings is correct.
909 const char *string = (const char *)Load.Ptr +
910 sizeof(struct MachO::linker_option_command);
911 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
912 uint32_t i = 0;
913 while (left > 0) {
914 while (*string == '\0' && left > 0) {
915 string++;
916 left--;
917 }
918 if (left > 0) {
919 i++;
920 uint32_t NullPos = StringRef(string, left).find('\0');
921 uint32_t len = std::min(NullPos, left) + 1;
922 string += len;
923 left -= len;
924 }
925 }
926 if (L.count != i)
927 return malformedError("load command " + Twine(LoadCommandIndex) +
928 " LC_LINKER_OPTION string count " + Twine(L.count) +
929 " does not match number of strings");
930 return Error::success();
931}
932
933static Error checkSubCommand(const MachOObjectFile &Obj,
934 const MachOObjectFile::LoadCommandInfo &Load,
935 uint32_t LoadCommandIndex, const char *CmdName,
936 size_t SizeOfCmd, const char *CmdStructName,
937 uint32_t PathOffset, const char *PathFieldName) {
938 if (PathOffset < SizeOfCmd)
939 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
940 CmdName + " " + PathFieldName + ".offset field too "
941 "small, not past the end of the " + CmdStructName);
942 if (PathOffset >= Load.C.cmdsize)
943 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
944 CmdName + " " + PathFieldName + ".offset field "
945 "extends past the end of the load command");
946 // Make sure there is a null between the starting offset of the path and
947 // the end of the load command.
948 uint32_t i;
949 const char *P = (const char *)Load.Ptr;
950 for (i = PathOffset; i < Load.C.cmdsize; i++)
951 if (P[i] == '\0')
952 break;
953 if (i >= Load.C.cmdsize)
954 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
955 CmdName + " " + PathFieldName + " name extends past "
956 "the end of the load command");
957 return Error::success();
958}
959
960static Error checkThreadCommand(const MachOObjectFile &Obj,
961 const MachOObjectFile::LoadCommandInfo &Load,
962 uint32_t LoadCommandIndex,
963 const char *CmdName) {
964 if (Load.C.cmdsize < sizeof(MachO::thread_command))
965 return malformedError("load command " + Twine(LoadCommandIndex) +
966 CmdName + " cmdsize too small");
967 MachO::thread_command T =
968 getStruct<MachO::thread_command>(Obj, Load.Ptr);
969 const char *state = Load.Ptr + sizeof(MachO::thread_command);
970 const char *end = Load.Ptr + T.cmdsize;
971 uint32_t nflavor = 0;
972 uint32_t cputype = getCPUType(Obj);
973 while (state < end) {
974 if(state + sizeof(uint32_t) > end)
975 return malformedError("load command " + Twine(LoadCommandIndex) +
976 "flavor in " + CmdName + " extends past end of "
977 "command");
978 uint32_t flavor;
979 memcpy(&flavor, state, sizeof(uint32_t));
980 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
981 sys::swapByteOrder(flavor);
982 state += sizeof(uint32_t);
983
984 if(state + sizeof(uint32_t) > end)
985 return malformedError("load command " + Twine(LoadCommandIndex) +
986 " count in " + CmdName + " extends past end of "
987 "command");
988 uint32_t count;
989 memcpy(&count, state, sizeof(uint32_t));
990 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
991 sys::swapByteOrder(count);
992 state += sizeof(uint32_t);
993
994 if (cputype == MachO::CPU_TYPE_I386) {
995 if (flavor == MachO::x86_THREAD_STATE32) {
996 if (count != MachO::x86_THREAD_STATE32_COUNT)
997 return malformedError("load command " + Twine(LoadCommandIndex) +
998 " count not x86_THREAD_STATE32_COUNT for "
999 "flavor number " + Twine(nflavor) + " which is "
1000 "a x86_THREAD_STATE32 flavor in " + CmdName +
1001 " command");
1002 if (state + sizeof(MachO::x86_thread_state32_t) > end)
1003 return malformedError("load command " + Twine(LoadCommandIndex) +
1004 " x86_THREAD_STATE32 extends past end of "
1005 "command in " + CmdName + " command");
1006 state += sizeof(MachO::x86_thread_state32_t);
1007 } else {
1008 return malformedError("load command " + Twine(LoadCommandIndex) +
1009 " unknown flavor (" + Twine(flavor) + ") for "
1010 "flavor number " + Twine(nflavor) + " in " +
1011 CmdName + " command");
1012 }
1013 } else if (cputype == MachO::CPU_TYPE_X86_64) {
1014 if (flavor == MachO::x86_THREAD_STATE) {
1015 if (count != MachO::x86_THREAD_STATE_COUNT)
1016 return malformedError("load command " + Twine(LoadCommandIndex) +
1017 " count not x86_THREAD_STATE_COUNT for "
1018 "flavor number " + Twine(nflavor) + " which is "
1019 "a x86_THREAD_STATE flavor in " + CmdName +
1020 " command");
1021 if (state + sizeof(MachO::x86_thread_state_t) > end)
1022 return malformedError("load command " + Twine(LoadCommandIndex) +
1023 " x86_THREAD_STATE extends past end of "
1024 "command in " + CmdName + " command");
1025 state += sizeof(MachO::x86_thread_state_t);
1026 } else if (flavor == MachO::x86_FLOAT_STATE) {
1027 if (count != MachO::x86_FLOAT_STATE_COUNT)
1028 return malformedError("load command " + Twine(LoadCommandIndex) +
1029 " count not x86_FLOAT_STATE_COUNT for "
1030 "flavor number " + Twine(nflavor) + " which is "
1031 "a x86_FLOAT_STATE flavor in " + CmdName +
1032 " command");
1033 if (state + sizeof(MachO::x86_float_state_t) > end)
1034 return malformedError("load command " + Twine(LoadCommandIndex) +
1035 " x86_FLOAT_STATE extends past end of "
1036 "command in " + CmdName + " command");
1037 state += sizeof(MachO::x86_float_state_t);
1038 } else if (flavor == MachO::x86_EXCEPTION_STATE) {
1039 if (count != MachO::x86_EXCEPTION_STATE_COUNT)
1040 return malformedError("load command " + Twine(LoadCommandIndex) +
1041 " count not x86_EXCEPTION_STATE_COUNT for "
1042 "flavor number " + Twine(nflavor) + " which is "
1043 "a x86_EXCEPTION_STATE flavor in " + CmdName +
1044 " command");
1045 if (state + sizeof(MachO::x86_exception_state_t) > end)
1046 return malformedError("load command " + Twine(LoadCommandIndex) +
1047 " x86_EXCEPTION_STATE extends past end of "
1048 "command in " + CmdName + " command");
1049 state += sizeof(MachO::x86_exception_state_t);
1050 } else if (flavor == MachO::x86_THREAD_STATE64) {
1051 if (count != MachO::x86_THREAD_STATE64_COUNT)
1052 return malformedError("load command " + Twine(LoadCommandIndex) +
1053 " count not x86_THREAD_STATE64_COUNT for "
1054 "flavor number " + Twine(nflavor) + " which is "
1055 "a x86_THREAD_STATE64 flavor in " + CmdName +
1056 " command");
1057 if (state + sizeof(MachO::x86_thread_state64_t) > end)
1058 return malformedError("load command " + Twine(LoadCommandIndex) +
1059 " x86_THREAD_STATE64 extends past end of "
1060 "command in " + CmdName + " command");
1061 state += sizeof(MachO::x86_thread_state64_t);
1062 } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
1063 if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
1064 return malformedError("load command " + Twine(LoadCommandIndex) +
1065 " count not x86_EXCEPTION_STATE64_COUNT for "
1066 "flavor number " + Twine(nflavor) + " which is "
1067 "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
1068 " command");
1069 if (state + sizeof(MachO::x86_exception_state64_t) > end)
1070 return malformedError("load command " + Twine(LoadCommandIndex) +
1071 " x86_EXCEPTION_STATE64 extends past end of "
1072 "command in " + CmdName + " command");
1073 state += sizeof(MachO::x86_exception_state64_t);
1074 } else {
1075 return malformedError("load command " + Twine(LoadCommandIndex) +
1076 " unknown flavor (" + Twine(flavor) + ") for "
1077 "flavor number " + Twine(nflavor) + " in " +
1078 CmdName + " command");
1079 }
1080 } else if (cputype == MachO::CPU_TYPE_ARM) {
1081 if (flavor == MachO::ARM_THREAD_STATE) {
1082 if (count != MachO::ARM_THREAD_STATE_COUNT)
1083 return malformedError("load command " + Twine(LoadCommandIndex) +
1084 " count not ARM_THREAD_STATE_COUNT for "
1085 "flavor number " + Twine(nflavor) + " which is "
1086 "a ARM_THREAD_STATE flavor in " + CmdName +
1087 " command");
1088 if (state + sizeof(MachO::arm_thread_state32_t) > end)
1089 return malformedError("load command " + Twine(LoadCommandIndex) +
1090 " ARM_THREAD_STATE extends past end of "
1091 "command in " + CmdName + " command");
1092 state += sizeof(MachO::arm_thread_state32_t);
1093 } else {
1094 return malformedError("load command " + Twine(LoadCommandIndex) +
1095 " unknown flavor (" + Twine(flavor) + ") for "
1096 "flavor number " + Twine(nflavor) + " in " +
1097 CmdName + " command");
1098 }
1099 } else if (cputype == MachO::CPU_TYPE_ARM64) {
1100 if (flavor == MachO::ARM_THREAD_STATE64) {
1101 if (count != MachO::ARM_THREAD_STATE64_COUNT)
1102 return malformedError("load command " + Twine(LoadCommandIndex) +
1103 " count not ARM_THREAD_STATE64_COUNT for "
1104 "flavor number " + Twine(nflavor) + " which is "
1105 "a ARM_THREAD_STATE64 flavor in " + CmdName +
1106 " command");
1107 if (state + sizeof(MachO::arm_thread_state64_t) > end)
1108 return malformedError("load command " + Twine(LoadCommandIndex) +
1109 " ARM_THREAD_STATE64 extends past end of "
1110 "command in " + CmdName + " command");
1111 state += sizeof(MachO::arm_thread_state64_t);
1112 } else {
1113 return malformedError("load command " + Twine(LoadCommandIndex) +
1114 " unknown flavor (" + Twine(flavor) + ") for "
1115 "flavor number " + Twine(nflavor) + " in " +
1116 CmdName + " command");
1117 }
1118 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1119 if (flavor == MachO::PPC_THREAD_STATE) {
1120 if (count != MachO::PPC_THREAD_STATE_COUNT)
1121 return malformedError("load command " + Twine(LoadCommandIndex) +
1122 " count not PPC_THREAD_STATE_COUNT for "
1123 "flavor number " + Twine(nflavor) + " which is "
1124 "a PPC_THREAD_STATE flavor in " + CmdName +
1125 " command");
1126 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1127 return malformedError("load command " + Twine(LoadCommandIndex) +
1128 " PPC_THREAD_STATE extends past end of "
1129 "command in " + CmdName + " command");
1130 state += sizeof(MachO::ppc_thread_state32_t);
1131 } else {
1132 return malformedError("load command " + Twine(LoadCommandIndex) +
1133 " unknown flavor (" + Twine(flavor) + ") for "
1134 "flavor number " + Twine(nflavor) + " in " +
1135 CmdName + " command");
1136 }
1137 } else {
1138 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1139 "command " + Twine(LoadCommandIndex) + " for " +
1140 CmdName + " command can't be checked");
1141 }
1142 nflavor++;
1143 }
1144 return Error::success();
1145}
1146
1147static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
1148 const MachOObjectFile::LoadCommandInfo
1149 &Load,
1150 uint32_t LoadCommandIndex,
1151 const char **LoadCmd,
1152 std::list<MachOElement> &Elements) {
1153 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1154 return malformedError("load command " + Twine(LoadCommandIndex) +
1155 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1156 if (*LoadCmd != nullptr)
1157 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1158 MachO::twolevel_hints_command Hints =
1159 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1160 uint64_t FileSize = Obj.getData().size();
1161 if (Hints.offset > FileSize)
1162 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1163 Twine(LoadCommandIndex) + " extends past the end of "
1164 "the file");
1165 uint64_t BigSize = Hints.nhints;
1166 BigSize *= sizeof(MachO::twolevel_hint);
1167 BigSize += Hints.offset;
1168 if (BigSize > FileSize)
1169 return malformedError("offset field plus nhints times sizeof(struct "
1170 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1171 Twine(LoadCommandIndex) + " extends past the end of "
1172 "the file");
1173 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1174 sizeof(MachO::twolevel_hint),
1175 "two level hints"))
1176 return Err;
1177 *LoadCmd = Load.Ptr;
1178 return Error::success();
1179}
1180
1181// Returns true if the libObject code does not support the load command and its
1182// contents. The cmd value it is treated as an unknown load command but with
1183// an error message that says the cmd value is obsolete.
1184static bool isLoadCommandObsolete(uint32_t cmd) {
1185 if (cmd == MachO::LC_SYMSEG ||
1186 cmd == MachO::LC_LOADFVMLIB ||
1187 cmd == MachO::LC_IDFVMLIB ||
1188 cmd == MachO::LC_IDENT ||
1189 cmd == MachO::LC_FVMFILE ||
1190 cmd == MachO::LC_PREPAGE ||
1191 cmd == MachO::LC_PREBOUND_DYLIB ||
1192 cmd == MachO::LC_TWOLEVEL_HINTS ||
1193 cmd == MachO::LC_PREBIND_CKSUM)
1194 return true;
1195 return false;
1196}
1197
1198Expected<std::unique_ptr<MachOObjectFile>>
1199MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
1200 bool Is64Bits, uint32_t UniversalCputype,
1201 uint32_t UniversalIndex) {
1202 Error Err = Error::success();
1203 std::unique_ptr<MachOObjectFile> Obj(
1204 new MachOObjectFile(std::move(Object), IsLittleEndian,
1205 Is64Bits, Err, UniversalCputype,
1206 UniversalIndex));
1207 if (Err)
1208 return std::move(Err);
1209 return std::move(Obj);
1210}
1211
1212MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
1213 bool Is64bits, Error &Err,
1214 uint32_t UniversalCputype,
1215 uint32_t UniversalIndex)
1216 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
1217 ErrorAsOutParameter ErrAsOutParam(&Err);
1218 uint64_t SizeOfHeaders;
1219 uint32_t cputype;
1220 if (is64Bit()) {
1221 parseHeader(*this, Header64, Err);
1222 SizeOfHeaders = sizeof(MachO::mach_header_64);
1223 cputype = Header64.cputype;
1224 } else {
1225 parseHeader(*this, Header, Err);
1226 SizeOfHeaders = sizeof(MachO::mach_header);
1227 cputype = Header.cputype;
1228 }
1229 if (Err)
1230 return;
1231 SizeOfHeaders += getHeader().sizeofcmds;
1232 if (getData().data() + SizeOfHeaders > getData().end()) {
1233 Err = malformedError("load commands extend past the end of the file");
1234 return;
1235 }
1236 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1237 Err = malformedError("universal header architecture: " +
1238 Twine(UniversalIndex) + "'s cputype does not match "
1239 "object file's mach header");
1240 return;
1241 }
1242 std::list<MachOElement> Elements;
1243 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
1244
1245 uint32_t LoadCommandCount = getHeader().ncmds;
1246 LoadCommandInfo Load;
1247 if (LoadCommandCount != 0) {
1248 if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
1249 Load = *LoadOrErr;
1250 else {
1251 Err = LoadOrErr.takeError();
1252 return;
1253 }
1254 }
1255
1256 const char *DyldIdLoadCmd = nullptr;
1257 const char *FuncStartsLoadCmd = nullptr;
1258 const char *SplitInfoLoadCmd = nullptr;
1259 const char *CodeSignDrsLoadCmd = nullptr;
1260 const char *CodeSignLoadCmd = nullptr;
1261 const char *VersLoadCmd = nullptr;
1262 const char *SourceLoadCmd = nullptr;
1263 const char *EntryPointLoadCmd = nullptr;
1264 const char *EncryptLoadCmd = nullptr;
1265 const char *RoutinesLoadCmd = nullptr;
1266 const char *UnixThreadLoadCmd = nullptr;
1267 const char *TwoLevelHintsLoadCmd = nullptr;
1268 for (unsigned I = 0; I < LoadCommandCount; ++I) {
1269 if (is64Bit()) {
1270 if (Load.C.cmdsize % 8 != 0) {
1271 // We have a hack here to allow 64-bit Mach-O core files to have
1272 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1273 // allowed since the macOS kernel produces them.
1274 if (getHeader().filetype != MachO::MH_CORE ||
1275 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1276 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1277 "multiple of 8");
1278 return;
1279 }
1280 }
1281 } else {
1282 if (Load.C.cmdsize % 4 != 0) {
1283 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1284 "multiple of 4");
1285 return;
1286 }
1287 }
1288 LoadCommands.push_back(Load);
1289 if (Load.C.cmd == MachO::LC_SYMTAB) {
1290 if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
1291 return;
1292 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
1293 if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
1294 Elements)))
1295 return;
1296 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
1297 if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
1298 "LC_DATA_IN_CODE", Elements,
1299 "data in code info")))
1300 return;
1301 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
1302 if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
1303 "LC_LINKER_OPTIMIZATION_HINT",
1304 Elements, "linker optimization "
1305 "hints")))
1306 return;
1307 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1308 if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
1309 "LC_FUNCTION_STARTS", Elements,
1310 "function starts data")))
1311 return;
1312 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1313 if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
1314 "LC_SEGMENT_SPLIT_INFO", Elements,
1315 "split info data")))
1316 return;
1317 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1318 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
1319 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1320 "code signing RDs data")))
1321 return;
1322 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1323 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
1324 "LC_CODE_SIGNATURE", Elements,
1325 "code signature data")))
1326 return;
1327 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1328 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1329 "LC_DYLD_INFO", Elements)))
1330 return;
1331 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1332 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1333 "LC_DYLD_INFO_ONLY", Elements)))
1334 return;
1335 } else if (Load.C.cmd == MachO::LC_UUID) {
1336 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1337 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1338 "cmdsize");
1339 return;
1340 }
1341 if (UuidLoadCmd) {
1342 Err = malformedError("more than one LC_UUID command");
1343 return;
1344 }
1345 UuidLoadCmd = Load.Ptr;
1346 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
1347 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1348 MachO::section_64>(
1349 *this, Load, Sections, HasPageZeroSegment, I,
1350 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
1351 return;
1352 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1353 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1354 MachO::section>(
1355 *this, Load, Sections, HasPageZeroSegment, I,
1356 "LC_SEGMENT", SizeOfHeaders, Elements)))
1357 return;
1358 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1359 if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
1360 return;
1361 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1362 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
1363 return;
1364 Libraries.push_back(Load.Ptr);
1365 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1366 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1367 return;
1368 Libraries.push_back(Load.Ptr);
1369 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1370 if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1371 return;
1372 Libraries.push_back(Load.Ptr);
1373 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1374 if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
1375 return;
1376 Libraries.push_back(Load.Ptr);
1377 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1378 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1379 return;
1380 Libraries.push_back(Load.Ptr);
1381 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1382 if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
1383 return;
1384 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1385 if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
1386 return;
1387 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1388 if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
1389 return;
1390 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1391 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1392 "LC_VERSION_MIN_MACOSX")))
1393 return;
1394 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1395 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1396 "LC_VERSION_MIN_IPHONEOS")))
1397 return;
1398 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1399 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1400 "LC_VERSION_MIN_TVOS")))
1401 return;
1402 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1403 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1404 "LC_VERSION_MIN_WATCHOS")))
1405 return;
1406 } else if (Load.C.cmd == MachO::LC_NOTE) {
1407 if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1408 return;
1409 } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1410 if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1411 return;
1412 } else if (Load.C.cmd == MachO::LC_RPATH) {
1413 if ((Err = checkRpathCommand(*this, Load, I)))
1414 return;
1415 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1416 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1417 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1418 " has incorrect cmdsize");
1419 return;
1420 }
1421 if (SourceLoadCmd) {
1422 Err = malformedError("more than one LC_SOURCE_VERSION command");
1423 return;
1424 }
1425 SourceLoadCmd = Load.Ptr;
1426 } else if (Load.C.cmd == MachO::LC_MAIN) {
1427 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1428 Err = malformedError("LC_MAIN command " + Twine(I) +
1429 " has incorrect cmdsize");
1430 return;
1431 }
1432 if (EntryPointLoadCmd) {
1433 Err = malformedError("more than one LC_MAIN command");
1434 return;
1435 }
1436 EntryPointLoadCmd = Load.Ptr;
1437 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1438 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1439 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1440 " has incorrect cmdsize");
1441 return;
1442 }
1443 MachO::encryption_info_command E =
1444 getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1445 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1446 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1447 return;
1448 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1449 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1450 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1451 " has incorrect cmdsize");
1452 return;
1453 }
1454 MachO::encryption_info_command_64 E =
1455 getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1456 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1457 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1458 return;
1459 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1460 if ((Err = checkLinkerOptCommand(*this, Load, I)))
1461 return;
1462 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1463 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1464 Err = malformedError("load command " + Twine(I) +
1465 " LC_SUB_FRAMEWORK cmdsize too small");
1466 return;
1467 }
1468 MachO::sub_framework_command S =
1469 getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1470 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
1471 sizeof(MachO::sub_framework_command),
1472 "sub_framework_command", S.umbrella,
1473 "umbrella")))
1474 return;
1475 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1476 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1477 Err = malformedError("load command " + Twine(I) +
1478 " LC_SUB_UMBRELLA cmdsize too small");
1479 return;
1480 }
1481 MachO::sub_umbrella_command S =
1482 getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1483 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
1484 sizeof(MachO::sub_umbrella_command),
1485 "sub_umbrella_command", S.sub_umbrella,
1486 "sub_umbrella")))
1487 return;
1488 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1489 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1490 Err = malformedError("load command " + Twine(I) +
1491 " LC_SUB_LIBRARY cmdsize too small");
1492 return;
1493 }
1494 MachO::sub_library_command S =
1495 getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1496 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
1497 sizeof(MachO::sub_library_command),
1498 "sub_library_command", S.sub_library,
1499 "sub_library")))
1500 return;
1501 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1502 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1503 Err = malformedError("load command " + Twine(I) +
1504 " LC_SUB_CLIENT cmdsize too small");
1505 return;
1506 }
1507 MachO::sub_client_command S =
1508 getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1509 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
1510 sizeof(MachO::sub_client_command),
1511 "sub_client_command", S.client, "client")))
1512 return;
1513 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1514 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1515 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1516 " has incorrect cmdsize");
1517 return;
1518 }
1519 if (RoutinesLoadCmd) {
1520 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1521 "command");
1522 return;
1523 }
1524 RoutinesLoadCmd = Load.Ptr;
1525 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1526 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1527 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1528 " has incorrect cmdsize");
1529 return;
1530 }
1531 if (RoutinesLoadCmd) {
1532 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1533 "command");
1534 return;
1535 }
1536 RoutinesLoadCmd = Load.Ptr;
1537 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1538 if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
1539 return;
1540 if (UnixThreadLoadCmd) {
1541 Err = malformedError("more than one LC_UNIXTHREAD command");
1542 return;
1543 }
1544 UnixThreadLoadCmd = Load.Ptr;
1545 } else if (Load.C.cmd == MachO::LC_THREAD) {
1546 if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
1547 return;
1548 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1549 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1550 if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
1551 &TwoLevelHintsLoadCmd, Elements)))
1552 return;
1553 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1554 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1555 Twine(Load.C.cmd) + " is obsolete and not "
1556 "supported");
1557 return;
1558 }
1559 // TODO: generate a error for unknown load commands by default. But still
1560 // need work out an approach to allow or not allow unknown values like this
1561 // as an option for some uses like lldb.
1562 if (I < LoadCommandCount - 1) {
1563 if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
1564 Load = *LoadOrErr;
1565 else {
1566 Err = LoadOrErr.takeError();
1567 return;
1568 }
1569 }
1570 }
1571 if (!SymtabLoadCmd) {
1572 if (DysymtabLoadCmd) {
1573 Err = malformedError("contains LC_DYSYMTAB load command without a "
1574 "LC_SYMTAB load command");
1575 return;
1576 }
1577 } else if (DysymtabLoadCmd) {
1578 MachO::symtab_command Symtab =
1579 getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
1580 MachO::dysymtab_command Dysymtab =
1581 getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
1582 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
1583 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
1584 "extends past the end of the symbol table");
1585 return;
1586 }
1587 uint64_t BigSize = Dysymtab.ilocalsym;
1588 BigSize += Dysymtab.nlocalsym;
1589 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
1590 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1591 "command extends past the end of the symbol table");
1592 return;
1593 }
1594 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
1595 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
1596 "extends past the end of the symbol table");
1597 return;
1598 }
1599 BigSize = Dysymtab.iextdefsym;
1600 BigSize += Dysymtab.nextdefsym;
1601 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
1602 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1603 "load command extends past the end of the symbol "
1604 "table");
1605 return;
1606 }
1607 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
1608 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
1609 "extends past the end of the symbol table");
1610 return;
1611 }
1612 BigSize = Dysymtab.iundefsym;
1613 BigSize += Dysymtab.nundefsym;
1614 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
1615 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1616 " command extends past the end of the symbol table");
1617 return;
1618 }
1619 }
1620 if ((getHeader().filetype == MachO::MH_DYLIB ||
1621 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1622 DyldIdLoadCmd == nullptr) {
1623 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1624 "filetype");
1625 return;
1626 }
1627 assert(LoadCommands.size() == LoadCommandCount)(static_cast <bool> (LoadCommands.size() == LoadCommandCount
) ? void (0) : __assert_fail ("LoadCommands.size() == LoadCommandCount"
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 1627, __extension__ __PRETTY_FUNCTION__))
;
1628
1629 Err = Error::success();
1630}
1631
1632Error MachOObjectFile::checkSymbolTable() const {
1633 uint32_t Flags = 0;
1634 if (is64Bit()) {
1635 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1636 Flags = H_64.flags;
1637 } else {
1638 MachO::mach_header H = MachOObjectFile::getHeader();
1639 Flags = H.flags;
1640 }
1641 uint8_t NType = 0;
1642 uint8_t NSect = 0;
1643 uint16_t NDesc = 0;
1644 uint32_t NStrx = 0;
1645 uint64_t NValue = 0;
1646 uint32_t SymbolIndex = 0;
1647 MachO::symtab_command S = getSymtabLoadCommand();
1648 for (const SymbolRef &Symbol : symbols()) {
1649 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1650 if (is64Bit()) {
1651 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1652 NType = STE_64.n_type;
1653 NSect = STE_64.n_sect;
1654 NDesc = STE_64.n_desc;
1655 NStrx = STE_64.n_strx;
1656 NValue = STE_64.n_value;
1657 } else {
1658 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1659 NType = STE.n_type;
1660 NType = STE.n_type;
1661 NSect = STE.n_sect;
1662 NDesc = STE.n_desc;
1663 NStrx = STE.n_strx;
1664 NValue = STE.n_value;
1665 }
1666 if ((NType & MachO::N_STAB) == 0 &&
1667 (NType & MachO::N_TYPE) == MachO::N_SECT) {
1668 if (NSect == 0 || NSect > Sections.size())
1669 return malformedError("bad section index: " + Twine((int)NSect) +
1670 " for symbol at index " + Twine(SymbolIndex));
1671 }
1672 if ((NType & MachO::N_STAB) == 0 &&
1673 (NType & MachO::N_TYPE) == MachO::N_INDR) {
1674 if (NValue >= S.strsize)
1675 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1676 "the end of string table, for N_INDR symbol at "
1677 "index " + Twine(SymbolIndex));
1678 }
1679 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1680 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1681 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1682 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1683 if (LibraryOrdinal != 0 &&
1684 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1685 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1686 LibraryOrdinal - 1 >= Libraries.size() ) {
1687 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1688 " for symbol at index " + Twine(SymbolIndex));
1689 }
1690 }
1691 if (NStrx >= S.strsize)
1692 return malformedError("bad string table index: " + Twine((int)NStrx) +
1693 " past the end of string table, for symbol at "
1694 "index " + Twine(SymbolIndex));
1695 SymbolIndex++;
1696 }
1697 return Error::success();
1698}
1699
1700void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1701 unsigned SymbolTableEntrySize = is64Bit() ?
1702 sizeof(MachO::nlist_64) :
1703 sizeof(MachO::nlist);
1704 Symb.p += SymbolTableEntrySize;
1705}
1706
1707Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
1708 StringRef StringTable = getStringTableData();
1709 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1710 if (Entry.n_strx == 0)
1711 // A n_strx value of 0 indicates that no name is associated with a
1712 // particular symbol table entry.
1713 return StringRef();
1714 const char *Start = &StringTable.data()[Entry.n_strx];
1715 if (Start < getData().begin() || Start >= getData().end()) {
1716 return malformedError("bad string index: " + Twine(Entry.n_strx) +
1717 " for symbol at index " + Twine(getSymbolIndex(Symb)));
1718 }
1719 return StringRef(Start);
1720}
1721
1722unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1723 DataRefImpl DRI = Sec.getRawDataRefImpl();
1724 uint32_t Flags = getSectionFlags(*this, DRI);
1725 return Flags & MachO::SECTION_TYPE;
1726}
1727
1728uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1729 if (is64Bit()) {
1730 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1731 return Entry.n_value;
1732 }
1733 MachO::nlist Entry = getSymbolTableEntry(Sym);
1734 return Entry.n_value;
1735}
1736
1737// getIndirectName() returns the name of the alias'ed symbol who's string table
1738// index is in the n_value field.
1739std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1740 StringRef &Res) const {
1741 StringRef StringTable = getStringTableData();
1742 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1743 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1744 return object_error::parse_failed;
1745 uint64_t NValue = getNValue(Symb);
1746 if (NValue >= StringTable.size())
1747 return object_error::parse_failed;
1748 const char *Start = &StringTable.data()[NValue];
1749 Res = StringRef(Start);
1750 return std::error_code();
1751}
1752
1753uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
1754 return getNValue(Sym);
1755}
1756
1757Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
1758 return getSymbolValue(Sym);
1759}
1760
1761uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
1762 uint32_t flags = getSymbolFlags(DRI);
1763 if (flags & SymbolRef::SF_Common) {
1764 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1765 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
1766 }
1767 return 0;
1768}
1769
1770uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
1771 return getNValue(DRI);
1772}
1773
1774Expected<SymbolRef::Type>
1775MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
1776 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1777 uint8_t n_type = Entry.n_type;
1778
1779 // If this is a STAB debugging symbol, we can do nothing more.
1780 if (n_type & MachO::N_STAB)
1781 return SymbolRef::ST_Debug;
1782
1783 switch (n_type & MachO::N_TYPE) {
1784 case MachO::N_UNDF :
1785 return SymbolRef::ST_Unknown;
1786 case MachO::N_SECT :
1787 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
1788 if (!SecOrError)
1789 return SecOrError.takeError();
1790 section_iterator Sec = *SecOrError;
1791 if (Sec->isData() || Sec->isBSS())
1792 return SymbolRef::ST_Data;
1793 return SymbolRef::ST_Function;
1794 }
1795 return SymbolRef::ST_Other;
1796}
1797
1798uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
1799 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1800
1801 uint8_t MachOType = Entry.n_type;
1802 uint16_t MachOFlags = Entry.n_desc;
1803
1804 uint32_t Result = SymbolRef::SF_None;
1805
1806 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1807 Result |= SymbolRef::SF_Indirect;
1808
1809 if (MachOType & MachO::N_STAB)
1810 Result |= SymbolRef::SF_FormatSpecific;
1811
1812 if (MachOType & MachO::N_EXT) {
1813 Result |= SymbolRef::SF_Global;
1814 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
1815 if (getNValue(DRI))
1816 Result |= SymbolRef::SF_Common;
1817 else
1818 Result |= SymbolRef::SF_Undefined;
1819 }
1820
1821 if (!(MachOType & MachO::N_PEXT))
1822 Result |= SymbolRef::SF_Exported;
1823 }
1824
1825 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
1826 Result |= SymbolRef::SF_Weak;
1827
1828 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1829 Result |= SymbolRef::SF_Thumb;
1830
1831 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
1832 Result |= SymbolRef::SF_Absolute;
1833
1834 return Result;
1835}
1836
1837Expected<section_iterator>
1838MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
1839 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1840 uint8_t index = Entry.n_sect;
1841
1842 if (index == 0)
1843 return section_end();
1844 DataRefImpl DRI;
1845 DRI.d.a = index - 1;
1846 if (DRI.d.a >= Sections.size()){
1847 return malformedError("bad section index: " + Twine((int)index) +
1848 " for symbol at index " + Twine(getSymbolIndex(Symb)));
1849 }
1850 return section_iterator(SectionRef(DRI, this));
1851}
1852
1853unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1854 MachO::nlist_base Entry =
1855 getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
1856 return Entry.n_sect - 1;
1857}
1858
1859void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
1860 Sec.d.a++;
1861}
1862
1863std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1864 StringRef &Result) const {
1865 ArrayRef<char> Raw = getSectionRawName(Sec);
1866 Result = parseSegmentOrSectionName(Raw.data());
1867 return std::error_code();
1868}
1869
1870uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1871 if (is64Bit())
1872 return getSection64(Sec).addr;
1873 return getSection(Sec).addr;
1874}
1875
1876uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1877 return Sec.d.a;
1878}
1879
1880uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
1881 // In the case if a malformed Mach-O file where the section offset is past
1882 // the end of the file or some part of the section size is past the end of
1883 // the file return a size of zero or a size that covers the rest of the file
1884 // but does not extend past the end of the file.
1885 uint32_t SectOffset, SectType;
1886 uint64_t SectSize;
1887
1888 if (is64Bit()) {
1889 MachO::section_64 Sect = getSection64(Sec);
1890 SectOffset = Sect.offset;
1891 SectSize = Sect.size;
1892 SectType = Sect.flags & MachO::SECTION_TYPE;
1893 } else {
1894 MachO::section Sect = getSection(Sec);
1895 SectOffset = Sect.offset;
1896 SectSize = Sect.size;
1897 SectType = Sect.flags & MachO::SECTION_TYPE;
1898 }
1899 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1900 return SectSize;
1901 uint64_t FileSize = getData().size();
1902 if (SectOffset > FileSize)
1903 return 0;
1904 if (FileSize - SectOffset < SectSize)
1905 return FileSize - SectOffset;
1906 return SectSize;
1907}
1908
1909std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1910 StringRef &Res) const {
1911 uint32_t Offset;
1912 uint64_t Size;
1913
1914 if (is64Bit()) {
1915 MachO::section_64 Sect = getSection64(Sec);
1916 Offset = Sect.offset;
1917 Size = Sect.size;
1918 } else {
1919 MachO::section Sect = getSection(Sec);
1920 Offset = Sect.offset;
1921 Size = Sect.size;
1922 }
1923
1924 Res = this->getData().substr(Offset, Size);
1925 return std::error_code();
1926}
1927
1928uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1929 uint32_t Align;
1930 if (is64Bit()) {
1931 MachO::section_64 Sect = getSection64(Sec);
1932 Align = Sect.align;
1933 } else {
1934 MachO::section Sect = getSection(Sec);
1935 Align = Sect.align;
1936 }
1937
1938 return uint64_t(1) << Align;
1939}
1940
1941bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1942 return false;
1943}
1944
1945bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
1946 uint32_t Flags = getSectionFlags(*this, Sec);
1947 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
1948}
1949
1950bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
1951 uint32_t Flags = getSectionFlags(*this, Sec);
1952 unsigned SectionType = Flags & MachO::SECTION_TYPE;
1953 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1954 !(SectionType == MachO::S_ZEROFILL ||
1955 SectionType == MachO::S_GB_ZEROFILL);
1956}
1957
1958bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
1959 uint32_t Flags = getSectionFlags(*this, Sec);
1960 unsigned SectionType = Flags & MachO::SECTION_TYPE;
1961 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1962 (SectionType == MachO::S_ZEROFILL ||
1963 SectionType == MachO::S_GB_ZEROFILL);
1964}
1965
1966unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1967 return Sec.getRawDataRefImpl().d.a;
1968}
1969
1970bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
1971 // FIXME: Unimplemented.
1972 return false;
1973}
1974
1975bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1976 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1977 StringRef SectName;
1978 if (!getSectionName(Sec, SectName))
1979 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1980 return false;
1981}
1982
1983bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
1984 if (is64Bit())
1985 return getSection64(Sec).offset == 0;
1986 return getSection(Sec).offset == 0;
1987}
1988
1989relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
1990 DataRefImpl Ret;
1991 Ret.d.a = Sec.d.a;
1992 Ret.d.b = 0;
1993 return relocation_iterator(RelocationRef(Ret, this));
1994}
1995
1996relocation_iterator
1997MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
1998 uint32_t Num;
1999 if (is64Bit()) {
2000 MachO::section_64 Sect = getSection64(Sec);
2001 Num = Sect.nreloc;
2002 } else {
2003 MachO::section Sect = getSection(Sec);
2004 Num = Sect.nreloc;
2005 }
2006
2007 DataRefImpl Ret;
2008 Ret.d.a = Sec.d.a;
2009 Ret.d.b = Num;
2010 return relocation_iterator(RelocationRef(Ret, this));
2011}
2012
2013relocation_iterator MachOObjectFile::extrel_begin() const {
2014 DataRefImpl Ret;
2015 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2016 Ret.d.a = 0; // Would normally be a section index.
2017 Ret.d.b = 0; // Index into the external relocations
2018 return relocation_iterator(RelocationRef(Ret, this));
2019}
2020
2021relocation_iterator MachOObjectFile::extrel_end() const {
2022 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2023 DataRefImpl Ret;
2024 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2025 Ret.d.a = 0; // Would normally be a section index.
2026 Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
2027 return relocation_iterator(RelocationRef(Ret, this));
2028}
2029
2030relocation_iterator MachOObjectFile::locrel_begin() const {
2031 DataRefImpl Ret;
2032 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2033 Ret.d.a = 1; // Would normally be a section index.
2034 Ret.d.b = 0; // Index into the local relocations
2035 return relocation_iterator(RelocationRef(Ret, this));
2036}
2037
2038relocation_iterator MachOObjectFile::locrel_end() const {
2039 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2040 DataRefImpl Ret;
2041 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2042 Ret.d.a = 1; // Would normally be a section index.
2043 Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
2044 return relocation_iterator(RelocationRef(Ret, this));
2045}
2046
2047void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
2048 ++Rel.d.b;
2049}
2050
2051uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
2052 assert((getHeader().filetype == MachO::MH_OBJECT ||(static_cast <bool> ((getHeader().filetype == MachO::MH_OBJECT
|| getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
"Only implemented for MH_OBJECT && MH_KEXT_BUNDLE") ?
void (0) : __assert_fail ("(getHeader().filetype == MachO::MH_OBJECT || getHeader().filetype == MachO::MH_KEXT_BUNDLE) && \"Only implemented for MH_OBJECT && MH_KEXT_BUNDLE\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 2054, __extension__ __PRETTY_FUNCTION__))
2053 getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&(static_cast <bool> ((getHeader().filetype == MachO::MH_OBJECT
|| getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
"Only implemented for MH_OBJECT && MH_KEXT_BUNDLE") ?
void (0) : __assert_fail ("(getHeader().filetype == MachO::MH_OBJECT || getHeader().filetype == MachO::MH_KEXT_BUNDLE) && \"Only implemented for MH_OBJECT && MH_KEXT_BUNDLE\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 2054, __extension__ __PRETTY_FUNCTION__))
2054 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE")(static_cast <bool> ((getHeader().filetype == MachO::MH_OBJECT
|| getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
"Only implemented for MH_OBJECT && MH_KEXT_BUNDLE") ?
void (0) : __assert_fail ("(getHeader().filetype == MachO::MH_OBJECT || getHeader().filetype == MachO::MH_KEXT_BUNDLE) && \"Only implemented for MH_OBJECT && MH_KEXT_BUNDLE\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 2054, __extension__ __PRETTY_FUNCTION__))
;
2055 MachO::any_relocation_info RE = getRelocation(Rel);
2056 return getAnyRelocationAddress(RE);
2057}
2058
2059symbol_iterator
2060MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
2061 MachO::any_relocation_info RE = getRelocation(Rel);
2062 if (isRelocationScattered(RE))
2063 return symbol_end();
2064
2065 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
2066 bool isExtern = getPlainRelocationExternal(RE);
2067 if (!isExtern)
2068 return symbol_end();
2069
2070 MachO::symtab_command S = getSymtabLoadCommand();
2071 unsigned SymbolTableEntrySize = is64Bit() ?
2072 sizeof(MachO::nlist_64) :
2073 sizeof(MachO::nlist);
2074 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
2075 DataRefImpl Sym;
2076 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2077 return symbol_iterator(SymbolRef(Sym, this));
2078}
2079
2080section_iterator
2081MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2082 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2083}
2084
2085uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
2086 MachO::any_relocation_info RE = getRelocation(Rel);
2087 return getAnyRelocationType(RE);
2088}
2089
2090void MachOObjectFile::getRelocationTypeName(
2091 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
2092 StringRef res;
2093 uint64_t RType = getRelocationType(Rel);
2094
2095 unsigned Arch = this->getArch();
2096
2097 switch (Arch) {
2098 case Triple::x86: {
2099 static const char *const Table[] = {
2100 "GENERIC_RELOC_VANILLA",
2101 "GENERIC_RELOC_PAIR",
2102 "GENERIC_RELOC_SECTDIFF",
2103 "GENERIC_RELOC_PB_LA_PTR",
2104 "GENERIC_RELOC_LOCAL_SECTDIFF",
2105 "GENERIC_RELOC_TLV" };
2106
2107 if (RType > 5)
2108 res = "Unknown";
2109 else
2110 res = Table[RType];
2111 break;
2112 }
2113 case Triple::x86_64: {
2114 static const char *const Table[] = {
2115 "X86_64_RELOC_UNSIGNED",
2116 "X86_64_RELOC_SIGNED",
2117 "X86_64_RELOC_BRANCH",
2118 "X86_64_RELOC_GOT_LOAD",
2119 "X86_64_RELOC_GOT",
2120 "X86_64_RELOC_SUBTRACTOR",
2121 "X86_64_RELOC_SIGNED_1",
2122 "X86_64_RELOC_SIGNED_2",
2123 "X86_64_RELOC_SIGNED_4",
2124 "X86_64_RELOC_TLV" };
2125
2126 if (RType > 9)
2127 res = "Unknown";
2128 else
2129 res = Table[RType];
2130 break;
2131 }
2132 case Triple::arm: {
2133 static const char *const Table[] = {
2134 "ARM_RELOC_VANILLA",
2135 "ARM_RELOC_PAIR",
2136 "ARM_RELOC_SECTDIFF",
2137 "ARM_RELOC_LOCAL_SECTDIFF",
2138 "ARM_RELOC_PB_LA_PTR",
2139 "ARM_RELOC_BR24",
2140 "ARM_THUMB_RELOC_BR22",
2141 "ARM_THUMB_32BIT_BRANCH",
2142 "ARM_RELOC_HALF",
2143 "ARM_RELOC_HALF_SECTDIFF" };
2144
2145 if (RType > 9)
2146 res = "Unknown";
2147 else
2148 res = Table[RType];
2149 break;
2150 }
2151 case Triple::aarch64: {
2152 static const char *const Table[] = {
2153 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2154 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2155 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2156 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2157 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2158 "ARM64_RELOC_ADDEND"
2159 };
2160
2161 if (RType >= array_lengthof(Table))
2162 res = "Unknown";
2163 else
2164 res = Table[RType];
2165 break;
2166 }
2167 case Triple::ppc: {
2168 static const char *const Table[] = {
2169 "PPC_RELOC_VANILLA",
2170 "PPC_RELOC_PAIR",
2171 "PPC_RELOC_BR14",
2172 "PPC_RELOC_BR24",
2173 "PPC_RELOC_HI16",
2174 "PPC_RELOC_LO16",
2175 "PPC_RELOC_HA16",
2176 "PPC_RELOC_LO14",
2177 "PPC_RELOC_SECTDIFF",
2178 "PPC_RELOC_PB_LA_PTR",
2179 "PPC_RELOC_HI16_SECTDIFF",
2180 "PPC_RELOC_LO16_SECTDIFF",
2181 "PPC_RELOC_HA16_SECTDIFF",
2182 "PPC_RELOC_JBSR",
2183 "PPC_RELOC_LO14_SECTDIFF",
2184 "PPC_RELOC_LOCAL_SECTDIFF" };
2185
2186 if (RType > 15)
2187 res = "Unknown";
2188 else
2189 res = Table[RType];
2190 break;
2191 }
2192 case Triple::UnknownArch:
2193 res = "Unknown";
2194 break;
2195 }
2196 Result.append(res.begin(), res.end());
2197}
2198
2199uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2200 MachO::any_relocation_info RE = getRelocation(Rel);
2201 return getAnyRelocationLength(RE);
2202}
2203
2204//
2205// guessLibraryShortName() is passed a name of a dynamic library and returns a
2206// guess on what the short name is. Then name is returned as a substring of the
2207// StringRef Name passed in. The name of the dynamic library is recognized as
2208// a framework if it has one of the two following forms:
2209// Foo.framework/Versions/A/Foo
2210// Foo.framework/Foo
2211// Where A and Foo can be any string. And may contain a trailing suffix
2212// starting with an underbar. If the Name is recognized as a framework then
2213// isFramework is set to true else it is set to false. If the Name has a
2214// suffix then Suffix is set to the substring in Name that contains the suffix
2215// else it is set to a NULL StringRef.
2216//
2217// The Name of the dynamic library is recognized as a library name if it has
2218// one of the two following forms:
2219// libFoo.A.dylib
2220// libFoo.dylib
2221// The library may have a suffix trailing the name Foo of the form:
2222// libFoo_profile.A.dylib
2223// libFoo_profile.dylib
2224//
2225// The Name of the dynamic library is also recognized as a library name if it
2226// has the following form:
2227// Foo.qtx
2228//
2229// If the Name of the dynamic library is none of the forms above then a NULL
2230// StringRef is returned.
2231//
2232StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2233 bool &isFramework,
2234 StringRef &Suffix) {
2235 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2236 size_t a, b, c, d, Idx;
2237
2238 isFramework = false;
2239 Suffix = StringRef();
2240
2241 // Pull off the last component and make Foo point to it
2242 a = Name.rfind('/');
2243 if (a == Name.npos || a == 0)
2244 goto guess_library;
2245 Foo = Name.slice(a+1, Name.npos);
2246
2247 // Look for a suffix starting with a '_'
2248 Idx = Foo.rfind('_');
2249 if (Idx != Foo.npos && Foo.size() >= 2) {
2250 Suffix = Foo.slice(Idx, Foo.npos);
2251 Foo = Foo.slice(0, Idx);
2252 }
2253
2254 // First look for the form Foo.framework/Foo
2255 b = Name.rfind('/', a);
2256 if (b == Name.npos)
2257 Idx = 0;
2258 else
2259 Idx = b+1;
2260 F = Name.slice(Idx, Idx + Foo.size());
2261 DotFramework = Name.slice(Idx + Foo.size(),
2262 Idx + Foo.size() + sizeof(".framework/")-1);
2263 if (F == Foo && DotFramework == ".framework/") {
2264 isFramework = true;
2265 return Foo;
2266 }
2267
2268 // Next look for the form Foo.framework/Versions/A/Foo
2269 if (b == Name.npos)
2270 goto guess_library;
2271 c = Name.rfind('/', b);
2272 if (c == Name.npos || c == 0)
2273 goto guess_library;
2274 V = Name.slice(c+1, Name.npos);
2275 if (!V.startswith("Versions/"))
2276 goto guess_library;
2277 d = Name.rfind('/', c);
2278 if (d == Name.npos)
2279 Idx = 0;
2280 else
2281 Idx = d+1;
2282 F = Name.slice(Idx, Idx + Foo.size());
2283 DotFramework = Name.slice(Idx + Foo.size(),
2284 Idx + Foo.size() + sizeof(".framework/")-1);
2285 if (F == Foo && DotFramework == ".framework/") {
2286 isFramework = true;
2287 return Foo;
2288 }
2289
2290guess_library:
2291 // pull off the suffix after the "." and make a point to it
2292 a = Name.rfind('.');
2293 if (a == Name.npos || a == 0)
2294 return StringRef();
2295 Dylib = Name.slice(a, Name.npos);
2296 if (Dylib != ".dylib")
2297 goto guess_qtx;
2298
2299 // First pull off the version letter for the form Foo.A.dylib if any.
2300 if (a >= 3) {
2301 Dot = Name.slice(a-2, a-1);
2302 if (Dot == ".")
2303 a = a - 2;
2304 }
2305
2306 b = Name.rfind('/', a);
2307 if (b == Name.npos)
2308 b = 0;
2309 else
2310 b = b+1;
2311 // ignore any suffix after an underbar like Foo_profile.A.dylib
2312 Idx = Name.find('_', b);
2313 if (Idx != Name.npos && Idx != b) {
2314 Lib = Name.slice(b, Idx);
2315 Suffix = Name.slice(Idx, a);
2316 }
2317 else
2318 Lib = Name.slice(b, a);
2319 // There are incorrect library names of the form:
2320 // libATS.A_profile.dylib so check for these.
2321 if (Lib.size() >= 3) {
2322 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2323 if (Dot == ".")
2324 Lib = Lib.slice(0, Lib.size()-2);
2325 }
2326 return Lib;
2327
2328guess_qtx:
2329 Qtx = Name.slice(a, Name.npos);
2330 if (Qtx != ".qtx")
2331 return StringRef();
2332 b = Name.rfind('/', a);
2333 if (b == Name.npos)
2334 Lib = Name.slice(0, a);
2335 else
2336 Lib = Name.slice(b+1, a);
2337 // There are library names of the form: QT.A.qtx so check for these.
2338 if (Lib.size() >= 3) {
2339 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2340 if (Dot == ".")
2341 Lib = Lib.slice(0, Lib.size()-2);
2342 }
2343 return Lib;
2344}
2345
2346// getLibraryShortNameByIndex() is used to get the short name of the library
2347// for an undefined symbol in a linked Mach-O binary that was linked with the
2348// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2349// It is passed the index (0 - based) of the library as translated from
2350// GET_LIBRARY_ORDINAL (1 - based).
2351std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
2352 StringRef &Res) const {
2353 if (Index >= Libraries.size())
2354 return object_error::parse_failed;
2355
2356 // If the cache of LibrariesShortNames is not built up do that first for
2357 // all the Libraries.
2358 if (LibrariesShortNames.size() == 0) {
2359 for (unsigned i = 0; i < Libraries.size(); i++) {
2360 MachO::dylib_command D =
2361 getStruct<MachO::dylib_command>(*this, Libraries[i]);
2362 if (D.dylib.name >= D.cmdsize)
2363 return object_error::parse_failed;
2364 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
2365 StringRef Name = StringRef(P);
2366 if (D.dylib.name+Name.size() >= D.cmdsize)
2367 return object_error::parse_failed;
2368 StringRef Suffix;
2369 bool isFramework;
2370 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
2371 if (shortName.empty())
2372 LibrariesShortNames.push_back(Name);
2373 else
2374 LibrariesShortNames.push_back(shortName);
2375 }
2376 }
2377
2378 Res = LibrariesShortNames[Index];
2379 return std::error_code();
2380}
2381
2382uint32_t MachOObjectFile::getLibraryCount() const {
2383 return Libraries.size();
2384}
2385
2386section_iterator
2387MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2388 DataRefImpl Sec;
2389 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2390 return section_iterator(SectionRef(Sec, this));
2391}
2392
2393basic_symbol_iterator MachOObjectFile::symbol_begin() const {
2394 DataRefImpl DRI;
2395 MachO::symtab_command Symtab = getSymtabLoadCommand();
2396 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2397 return basic_symbol_iterator(SymbolRef(DRI, this));
2398
2399 return getSymbolByIndex(0);
2400}
2401
2402basic_symbol_iterator MachOObjectFile::symbol_end() const {
2403 DataRefImpl DRI;
2404 MachO::symtab_command Symtab = getSymtabLoadCommand();
2405 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2406 return basic_symbol_iterator(SymbolRef(DRI, this));
2407
2408 unsigned SymbolTableEntrySize = is64Bit() ?
2409 sizeof(MachO::nlist_64) :
2410 sizeof(MachO::nlist);
2411 unsigned Offset = Symtab.symoff +
2412 Symtab.nsyms * SymbolTableEntrySize;
2413 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2414 return basic_symbol_iterator(SymbolRef(DRI, this));
2415}
2416
2417basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
2418 MachO::symtab_command Symtab = getSymtabLoadCommand();
2419 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
2420 report_fatal_error("Requested symbol index is out of range.");
2421 unsigned SymbolTableEntrySize =
2422 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2423 DataRefImpl DRI;
2424 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2425 DRI.p += Index * SymbolTableEntrySize;
2426 return basic_symbol_iterator(SymbolRef(DRI, this));
2427}
2428
2429uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2430 MachO::symtab_command Symtab = getSymtabLoadCommand();
2431 if (!SymtabLoadCmd)
2432 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2433 unsigned SymbolTableEntrySize =
2434 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2435 DataRefImpl DRIstart;
2436 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2437 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2438 return Index;
2439}
2440
2441section_iterator MachOObjectFile::section_begin() const {
2442 DataRefImpl DRI;
2443 return section_iterator(SectionRef(DRI, this));
2444}
2445
2446section_iterator MachOObjectFile::section_end() const {
2447 DataRefImpl DRI;
2448 DRI.d.a = Sections.size();
2449 return section_iterator(SectionRef(DRI, this));
2450}
2451
2452uint8_t MachOObjectFile::getBytesInAddress() const {
2453 return is64Bit() ? 8 : 4;
2454}
2455
2456StringRef MachOObjectFile::getFileFormatName() const {
2457 unsigned CPUType = getCPUType(*this);
2458 if (!is64Bit()) {
2459 switch (CPUType) {
2460 case MachO::CPU_TYPE_I386:
2461 return "Mach-O 32-bit i386";
2462 case MachO::CPU_TYPE_ARM:
2463 return "Mach-O arm";
2464 case MachO::CPU_TYPE_POWERPC:
2465 return "Mach-O 32-bit ppc";
2466 default:
2467 return "Mach-O 32-bit unknown";
2468 }
2469 }
2470
2471 switch (CPUType) {
2472 case MachO::CPU_TYPE_X86_64:
2473 return "Mach-O 64-bit x86-64";
2474 case MachO::CPU_TYPE_ARM64:
2475 return "Mach-O arm64";
2476 case MachO::CPU_TYPE_POWERPC64:
2477 return "Mach-O 64-bit ppc64";
2478 default:
2479 return "Mach-O 64-bit unknown";
2480 }
2481}
2482
2483Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2484 switch (CPUType) {
2485 case MachO::CPU_TYPE_I386:
2486 return Triple::x86;
2487 case MachO::CPU_TYPE_X86_64:
2488 return Triple::x86_64;
2489 case MachO::CPU_TYPE_ARM:
2490 return Triple::arm;
2491 case MachO::CPU_TYPE_ARM64:
2492 return Triple::aarch64;
2493 case MachO::CPU_TYPE_POWERPC:
2494 return Triple::ppc;
2495 case MachO::CPU_TYPE_POWERPC64:
2496 return Triple::ppc64;
2497 default:
2498 return Triple::UnknownArch;
2499 }
2500}
2501
2502Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2503 const char **McpuDefault,
2504 const char **ArchFlag) {
2505 if (McpuDefault)
2506 *McpuDefault = nullptr;
2507 if (ArchFlag)
2508 *ArchFlag = nullptr;
2509
2510 switch (CPUType) {
2511 case MachO::CPU_TYPE_I386:
2512 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2513 case MachO::CPU_SUBTYPE_I386_ALL:
2514 if (ArchFlag)
2515 *ArchFlag = "i386";
2516 return Triple("i386-apple-darwin");
2517 default:
2518 return Triple();
2519 }
2520 case MachO::CPU_TYPE_X86_64:
2521 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2522 case MachO::CPU_SUBTYPE_X86_64_ALL:
2523 if (ArchFlag)
2524 *ArchFlag = "x86_64";
2525 return Triple("x86_64-apple-darwin");
2526 case MachO::CPU_SUBTYPE_X86_64_H:
2527 if (ArchFlag)
2528 *ArchFlag = "x86_64h";
2529 return Triple("x86_64h-apple-darwin");
2530 default:
2531 return Triple();
2532 }
2533 case MachO::CPU_TYPE_ARM:
2534 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2535 case MachO::CPU_SUBTYPE_ARM_V4T:
2536 if (ArchFlag)
2537 *ArchFlag = "armv4t";
2538 return Triple("armv4t-apple-darwin");
2539 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2540 if (ArchFlag)
2541 *ArchFlag = "armv5e";
2542 return Triple("armv5e-apple-darwin");
2543 case MachO::CPU_SUBTYPE_ARM_XSCALE:
2544 if (ArchFlag)
2545 *ArchFlag = "xscale";
2546 return Triple("xscale-apple-darwin");
2547 case MachO::CPU_SUBTYPE_ARM_V6:
2548 if (ArchFlag)
2549 *ArchFlag = "armv6";
2550 return Triple("armv6-apple-darwin");
2551 case MachO::CPU_SUBTYPE_ARM_V6M:
2552 if (McpuDefault)
2553 *McpuDefault = "cortex-m0";
2554 if (ArchFlag)
2555 *ArchFlag = "armv6m";
2556 return Triple("armv6m-apple-darwin");
2557 case MachO::CPU_SUBTYPE_ARM_V7:
2558 if (ArchFlag)
2559 *ArchFlag = "armv7";
2560 return Triple("armv7-apple-darwin");
2561 case MachO::CPU_SUBTYPE_ARM_V7EM:
2562 if (McpuDefault)
2563 *McpuDefault = "cortex-m4";
2564 if (ArchFlag)
2565 *ArchFlag = "armv7em";
2566 return Triple("thumbv7em-apple-darwin");
2567 case MachO::CPU_SUBTYPE_ARM_V7K:
2568 if (McpuDefault)
2569 *McpuDefault = "cortex-a7";
2570 if (ArchFlag)
2571 *ArchFlag = "armv7k";
2572 return Triple("armv7k-apple-darwin");
2573 case MachO::CPU_SUBTYPE_ARM_V7M:
2574 if (McpuDefault)
2575 *McpuDefault = "cortex-m3";
2576 if (ArchFlag)
2577 *ArchFlag = "armv7m";
2578 return Triple("thumbv7m-apple-darwin");
2579 case MachO::CPU_SUBTYPE_ARM_V7S:
2580 if (McpuDefault)
2581 *McpuDefault = "cortex-a7";
2582 if (ArchFlag)
2583 *ArchFlag = "armv7s";
2584 return Triple("armv7s-apple-darwin");
2585 default:
2586 return Triple();
2587 }
2588 case MachO::CPU_TYPE_ARM64:
2589 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2590 case MachO::CPU_SUBTYPE_ARM64_ALL:
2591 if (McpuDefault)
2592 *McpuDefault = "cyclone";
2593 if (ArchFlag)
2594 *ArchFlag = "arm64";
2595 return Triple("arm64-apple-darwin");
2596 default:
2597 return Triple();
2598 }
2599 case MachO::CPU_TYPE_POWERPC:
2600 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2601 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2602 if (ArchFlag)
2603 *ArchFlag = "ppc";
2604 return Triple("ppc-apple-darwin");
2605 default:
2606 return Triple();
2607 }
2608 case MachO::CPU_TYPE_POWERPC64:
2609 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2610 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2611 if (ArchFlag)
2612 *ArchFlag = "ppc64";
2613 return Triple("ppc64-apple-darwin");
2614 default:
2615 return Triple();
2616 }
2617 default:
2618 return Triple();
2619 }
2620}
2621
2622Triple MachOObjectFile::getHostArch() {
2623 return Triple(sys::getDefaultTargetTriple());
2624}
2625
2626bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2627 return StringSwitch<bool>(ArchFlag)
2628 .Case("i386", true)
2629 .Case("x86_64", true)
2630 .Case("x86_64h", true)
2631 .Case("armv4t", true)
2632 .Case("arm", true)
2633 .Case("armv5e", true)
2634 .Case("armv6", true)
2635 .Case("armv6m", true)
2636 .Case("armv7", true)
2637 .Case("armv7em", true)
2638 .Case("armv7k", true)
2639 .Case("armv7m", true)
2640 .Case("armv7s", true)
2641 .Case("arm64", true)
2642 .Case("ppc", true)
2643 .Case("ppc64", true)
2644 .Default(false);
2645}
2646
2647Triple::ArchType MachOObjectFile::getArch() const {
2648 return getArch(getCPUType(*this));
2649}
2650
2651Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2652 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
2653}
2654
2655relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
2656 DataRefImpl DRI;
2657 DRI.d.a = Index;
2658 return section_rel_begin(DRI);
2659}
2660
2661relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
2662 DataRefImpl DRI;
2663 DRI.d.a = Index;
2664 return section_rel_end(DRI);
2665}
2666
2667dice_iterator MachOObjectFile::begin_dices() const {
2668 DataRefImpl DRI;
2669 if (!DataInCodeLoadCmd)
2670 return dice_iterator(DiceRef(DRI, this));
2671
2672 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2673 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
2674 return dice_iterator(DiceRef(DRI, this));
2675}
2676
2677dice_iterator MachOObjectFile::end_dices() const {
2678 DataRefImpl DRI;
2679 if (!DataInCodeLoadCmd)
2680 return dice_iterator(DiceRef(DRI, this));
2681
2682 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2683 unsigned Offset = DicLC.dataoff + DicLC.datasize;
2684 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2685 return dice_iterator(DiceRef(DRI, this));
2686}
2687
2688ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
2689 ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
2690
2691void ExportEntry::moveToFirst() {
2692 ErrorAsOutParameter ErrAsOutParam(E);
2693 pushNode(0);
2694 if (*E)
2695 return;
2696 pushDownUntilBottom();
2697}
2698
2699void ExportEntry::moveToEnd() {
2700 Stack.clear();
2701 Done = true;
2702}
2703
2704bool ExportEntry::operator==(const ExportEntry &Other) const {
2705 // Common case, one at end, other iterating from begin.
2706 if (Done || Other.Done)
2707 return (Done == Other.Done);
2708 // Not equal if different stack sizes.
2709 if (Stack.size() != Other.Stack.size())
2710 return false;
2711 // Not equal if different cumulative strings.
2712 if (!CumulativeString.equals(Other.CumulativeString))
2713 return false;
2714 // Equal if all nodes in both stacks match.
2715 for (unsigned i=0; i < Stack.size(); ++i) {
2716 if (Stack[i].Start != Other.Stack[i].Start)
2717 return false;
2718 }
2719 return true;
2720}
2721
2722uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
2723 unsigned Count;
2724 uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
2725 Ptr += Count;
2726 if (Ptr > Trie.end())
2727 Ptr = Trie.end();
2728 return Result;
2729}
2730
2731StringRef ExportEntry::name() const {
2732 return CumulativeString;
2733}
2734
2735uint64_t ExportEntry::flags() const {
2736 return Stack.back().Flags;
2737}
2738
2739uint64_t ExportEntry::address() const {
2740 return Stack.back().Address;
2741}
2742
2743uint64_t ExportEntry::other() const {
2744 return Stack.back().Other;
2745}
2746
2747StringRef ExportEntry::otherName() const {
2748 const char* ImportName = Stack.back().ImportName;
2749 if (ImportName)
2750 return StringRef(ImportName);
2751 return StringRef();
2752}
2753
2754uint32_t ExportEntry::nodeOffset() const {
2755 return Stack.back().Start - Trie.begin();
2756}
2757
2758ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2759 : Start(Ptr), Current(Ptr) {}
2760
2761void ExportEntry::pushNode(uint64_t offset) {
2762 ErrorAsOutParameter ErrAsOutParam(E);
2763 const uint8_t *Ptr = Trie.begin() + offset;
2764 NodeState State(Ptr);
2765 const char *error;
2766 uint64_t ExportInfoSize = readULEB128(State.Current, &error);
2767 if (error) {
2768 *E = malformedError("export info size " + Twine(error) +
2769 " in export trie data at node: 0x" +
2770 Twine::utohexstr(offset));
2771 moveToEnd();
2772 return;
2773 }
2774 State.IsExportNode = (ExportInfoSize != 0);
2775 const uint8_t* Children = State.Current + ExportInfoSize;
2776 if (Children > Trie.end()) {
2777 *E = malformedError(
2778 "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
2779 " in export trie data at node: 0x" + Twine::utohexstr(offset) +
2780 " too big and extends past end of trie data");
2781 moveToEnd();
2782 return;
2783 }
2784 if (State.IsExportNode) {
2785 const uint8_t *ExportStart = State.Current;
2786 State.Flags = readULEB128(State.Current, &error);
2787 if (error) {
2788 *E = malformedError("flags " + Twine(error) +
2789 " in export trie data at node: 0x" +
2790 Twine::utohexstr(offset));
2791 moveToEnd();
2792 return;
2793 }
2794 uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
2795 if (State.Flags != 0 &&
2796 (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
2797 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
2798 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
2799 *E = malformedError(
2800 "unsupported exported symbol kind: " + Twine((int)Kind) +
2801 " in flags: 0x" + Twine::utohexstr(State.Flags) +
2802 " in export trie data at node: 0x" + Twine::utohexstr(offset));
2803 moveToEnd();
2804 return;
2805 }
2806 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2807 State.Address = 0;
2808 State.Other = readULEB128(State.Current, &error); // dylib ordinal
2809 if (error) {
2810 *E = malformedError("dylib ordinal of re-export " + Twine(error) +
2811 " in export trie data at node: 0x" +
2812 Twine::utohexstr(offset));
2813 moveToEnd();
2814 return;
2815 }
2816 if (O != nullptr) {
2817 if (State.Other > O->getLibraryCount()) {
2818 *E = malformedError(
2819 "bad library ordinal: " + Twine((int)State.Other) + " (max " +
2820 Twine((int)O->getLibraryCount()) +
2821 ") in export trie data at node: 0x" + Twine::utohexstr(offset));
2822 moveToEnd();
2823 return;
2824 }
2825 }
2826 State.ImportName = reinterpret_cast<const char*>(State.Current);
2827 if (*State.ImportName == '\0') {
2828 State.Current++;
2829 } else {
2830 const uint8_t *End = State.Current + 1;
2831 if (End >= Trie.end()) {
2832 *E = malformedError("import name of re-export in export trie data at "
2833 "node: 0x" +
2834 Twine::utohexstr(offset) +
2835 " starts past end of trie data");
2836 moveToEnd();
2837 return;
2838 }
2839 while(*End != '\0' && End < Trie.end())
2840 End++;
2841 if (*End != '\0') {
2842 *E = malformedError("import name of re-export in export trie data at "
2843 "node: 0x" +
2844 Twine::utohexstr(offset) +
2845 " extends past end of trie data");
2846 moveToEnd();
2847 return;
2848 }
2849 State.Current = End + 1;
2850 }
2851 } else {
2852 State.Address = readULEB128(State.Current, &error);
2853 if (error) {
2854 *E = malformedError("address " + Twine(error) +
2855 " in export trie data at node: 0x" +
2856 Twine::utohexstr(offset));
2857 moveToEnd();
2858 return;
2859 }
2860 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
2861 State.Other = readULEB128(State.Current, &error);
2862 if (error) {
2863 *E = malformedError("resolver of stub and resolver " + Twine(error) +
2864 " in export trie data at node: 0x" +
2865 Twine::utohexstr(offset));
2866 moveToEnd();
2867 return;
2868 }
2869 }
2870 }
2871 if(ExportStart + ExportInfoSize != State.Current) {
2872 *E = malformedError(
2873 "inconsistant export info size: 0x" +
2874 Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
2875 Twine::utohexstr(State.Current - ExportStart) +
2876 " in export trie data at node: 0x" + Twine::utohexstr(offset));
2877 moveToEnd();
2878 return;
2879 }
2880 }
2881 State.ChildCount = *Children;
2882 if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
2883 *E = malformedError("byte for count of childern in export trie data at "
2884 "node: 0x" +
2885 Twine::utohexstr(offset) +
2886 " extends past end of trie data");
2887 moveToEnd();
2888 return;
2889 }
2890 State.Current = Children + 1;
2891 State.NextChildIndex = 0;
2892 State.ParentStringLength = CumulativeString.size();
2893 Stack.push_back(State);
2894}
2895
2896void ExportEntry::pushDownUntilBottom() {
2897 ErrorAsOutParameter ErrAsOutParam(E);
2898 const char *error;
2899 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2900 NodeState &Top = Stack.back();
2901 CumulativeString.resize(Top.ParentStringLength);
2902 for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
2903 char C = *Top.Current;
2904 CumulativeString.push_back(C);
2905 }
2906 if (Top.Current >= Trie.end()) {
2907 *E = malformedError("edge sub-string in export trie data at node: 0x" +
2908 Twine::utohexstr(Top.Start - Trie.begin()) +
2909 " for child #" + Twine((int)Top.NextChildIndex) +
2910 " extends past end of trie data");
2911 moveToEnd();
2912 return;
2913 }
2914 Top.Current += 1;
2915 uint64_t childNodeIndex = readULEB128(Top.Current, &error);
2916 if (error) {
2917 *E = malformedError("child node offset " + Twine(error) +
2918 " in export trie data at node: 0x" +
2919 Twine::utohexstr(Top.Start - Trie.begin()));
2920 moveToEnd();
2921 return;
2922 }
2923 for (const NodeState &node : nodes()) {
2924 if (node.Start == Trie.begin() + childNodeIndex){
2925 *E = malformedError("loop in childern in export trie data at node: 0x" +
2926 Twine::utohexstr(Top.Start - Trie.begin()) +
2927 " back to node: 0x" +
2928 Twine::utohexstr(childNodeIndex));
2929 moveToEnd();
2930 return;
2931 }
2932 }
2933 Top.NextChildIndex += 1;
2934 pushNode(childNodeIndex);
2935 if (*E)
2936 return;
2937 }
2938 if (!Stack.back().IsExportNode) {
2939 *E = malformedError("node is not an export node in export trie data at "
2940 "node: 0x" +
2941 Twine::utohexstr(Stack.back().Start - Trie.begin()));
2942 moveToEnd();
2943 return;
2944 }
2945}
2946
2947// We have a trie data structure and need a way to walk it that is compatible
2948// with the C++ iterator model. The solution is a non-recursive depth first
2949// traversal where the iterator contains a stack of parent nodes along with a
2950// string that is the accumulation of all edge strings along the parent chain
2951// to this point.
2952//
2953// There is one "export" node for each exported symbol. But because some
2954// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
2955// node may have child nodes too.
2956//
2957// The algorithm for moveNext() is to keep moving down the leftmost unvisited
2958// child until hitting a node with no children (which is an export node or
2959// else the trie is malformed). On the way down, each node is pushed on the
2960// stack ivar. If there is no more ways down, it pops up one and tries to go
2961// down a sibling path until a childless node is reached.
2962void ExportEntry::moveNext() {
2963 assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack")(static_cast <bool> (!Stack.empty() && "ExportEntry::moveNext() with empty node stack"
) ? void (0) : __assert_fail ("!Stack.empty() && \"ExportEntry::moveNext() with empty node stack\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 2963, __extension__ __PRETTY_FUNCTION__))
;
2964 if (!Stack.back().IsExportNode) {
2965 *E = malformedError("node is not an export node in export trie data at "
2966 "node: 0x" +
2967 Twine::utohexstr(Stack.back().Start - Trie.begin()));
2968 moveToEnd();
2969 return;
2970 }
2971
2972 Stack.pop_back();
2973 while (!Stack.empty()) {
2974 NodeState &Top = Stack.back();
2975 if (Top.NextChildIndex < Top.ChildCount) {
2976 pushDownUntilBottom();
2977 // Now at the next export node.
2978 return;
2979 } else {
2980 if (Top.IsExportNode) {
2981 // This node has no children but is itself an export node.
2982 CumulativeString.resize(Top.ParentStringLength);
2983 return;
2984 }
2985 Stack.pop_back();
2986 }
2987 }
2988 Done = true;
2989}
2990
2991iterator_range<export_iterator>
2992MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
2993 const MachOObjectFile *O) {
2994 ExportEntry Start(&E, O, Trie);
2995 if (Trie.empty())
2996 Start.moveToEnd();
2997 else
2998 Start.moveToFirst();
2999
3000 ExportEntry Finish(&E, O, Trie);
3001 Finish.moveToEnd();
3002
3003 return make_range(export_iterator(Start), export_iterator(Finish));
3004}
3005
3006iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
3007 return exports(Err, getDyldInfoExportsTrie(), this);
3008}
3009
3010MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
3011 ArrayRef<uint8_t> Bytes, bool is64Bit)
3012 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3013 PointerSize(is64Bit ? 8 : 4) {}
3014
3015void MachORebaseEntry::moveToFirst() {
3016 Ptr = Opcodes.begin();
3017 moveNext();
3018}
3019
3020void MachORebaseEntry::moveToEnd() {
3021 Ptr = Opcodes.end();
3022 RemainingLoopCount = 0;
3023 Done = true;
3024}
3025
3026void MachORebaseEntry::moveNext() {
3027 ErrorAsOutParameter ErrAsOutParam(E);
3028 // If in the middle of some loop, move to next rebasing in loop.
3029 SegmentOffset += AdvanceAmount;
3030 if (RemainingLoopCount) {
3031 --RemainingLoopCount;
3032 return;
3033 }
3034 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3035 // pointer size. Therefore it is possible to reach the end without ever having
3036 // seen REBASE_OPCODE_DONE.
3037 if (Ptr == Opcodes.end()) {
3038 Done = true;
3039 return;
3040 }
3041 bool More = true;
3042 while (More) {
3043 // Parse next opcode and set up next loop.
3044 const uint8_t *OpcodeStart = Ptr;
3045 uint8_t Byte = *Ptr++;
3046 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
3047 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
3048 uint32_t Count, Skip;
3049 const char *error = nullptr;
3050 switch (Opcode) {
3051 case MachO::REBASE_OPCODE_DONE:
3052 More = false;
3053 Done = true;
3054 moveToEnd();
3055 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DONE\n"; }
} while (false)
;
3056 break;
3057 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
3058 RebaseType = ImmValue;
3059 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
3060 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3061 Twine((int)RebaseType) + " for opcode at: 0x" +
3062 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3063 moveToEnd();
3064 return;
3065 }
3066 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
<< "RebaseType=" << (int) RebaseType << "\n"
; } } while (false)
3067 "mach-o-rebase",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
<< "RebaseType=" << (int) RebaseType << "\n"
; } } while (false)
3068 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
<< "RebaseType=" << (int) RebaseType << "\n"
; } } while (false)
3069 << "RebaseType=" << (int) RebaseType << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
<< "RebaseType=" << (int) RebaseType << "\n"
; } } while (false)
;
3070 break;
3071 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3072 SegmentIndex = ImmValue;
3073 SegmentOffset = readULEB128(&error);
3074 if (error) {
3075 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3076 Twine(error) + " for opcode at: 0x" +
3077 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3078 moveToEnd();
3079 return;
3080 }
3081 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3082 true);
3083 if (error) {
3084 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3085 Twine(error) + " for opcode at: 0x" +
3086 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3087 moveToEnd();
3088 return;
3089 }
3090 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3091 "mach-o-rebase",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3092 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3093 << "SegmentIndex=" << SegmentIndex << ", "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3094 << format("SegmentOffset=0x%06X", SegmentOffset)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3095 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
;
3096 break;
3097 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
3098 SegmentOffset += readULEB128(&error);
3099 if (error) {
3100 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3101 " for opcode at: 0x" +
3102 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3103 moveToEnd();
3104 return;
3105 }
3106 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3107 true);
3108 if (error) {
3109 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3110 " for opcode at: 0x" +
3111 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3112 moveToEnd();
3113 return;
3114 }
3115 DEBUG_WITH_TYPE("mach-o-rebase",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3116 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3117 << format("SegmentOffset=0x%06X",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3118 SegmentOffset) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
;
3119 break;
3120 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
3121 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3122 true);
3123 if (error) {
3124 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3125 Twine(error) + " for opcode at: 0x" +
3126 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3127 moveToEnd();
3128 return;
3129 }
3130 SegmentOffset += ImmValue * PointerSize;
3131 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3132 false);
3133 if (error) {
3134 *E =
3135 malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3136 " (after adding immediate times the pointer size) " +
3137 Twine(error) + " for opcode at: 0x" +
3138 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3139 moveToEnd();
3140 return;
3141 }
3142 DEBUG_WITH_TYPE("mach-o-rebase",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3143 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3144 << format("SegmentOffset=0x%06X",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3145 SegmentOffset) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
;
3146 break;
3147 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
3148 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3149 true);
3150 if (error) {
3151 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3152 Twine(error) + " for opcode at: 0x" +
3153 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3154 moveToEnd();
3155 return;
3156 }
3157 AdvanceAmount = PointerSize;
3158 Skip = 0;
3159 Count = ImmValue;
3160 if (ImmValue != 0)
3161 RemainingLoopCount = ImmValue - 1;
3162 else
3163 RemainingLoopCount = 0;
3164 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3165 SegmentIndex, SegmentOffset);
3166 if (error) {
3167 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3168 Twine(error) + " for opcode at: 0x" +
3169 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3170 moveToEnd();
3171 return;
3172 }
3173 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3174 "mach-o-rebase",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3175 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3176 << format("SegmentOffset=0x%06X", SegmentOffset)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3177 << ", AdvanceAmount=" << AdvanceAmountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3178 << ", RemainingLoopCount=" << RemainingLoopCountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3179 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
;
3180 return;
3181 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
3182 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3183 true);
3184 if (error) {
3185 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3186 Twine(error) + " for opcode at: 0x" +
3187 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3188 moveToEnd();
3189 return;
3190 }
3191 AdvanceAmount = PointerSize;
3192 Skip = 0;
3193 Count = readULEB128(&error);
3194 if (error) {
3195 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3196 Twine(error) + " for opcode at: 0x" +
3197 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3198 moveToEnd();
3199 return;
3200 }
3201 if (Count != 0)
3202 RemainingLoopCount = Count - 1;
3203 else
3204 RemainingLoopCount = 0;
3205 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3206 SegmentIndex, SegmentOffset);
3207 if (error) {
3208 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3209 Twine(error) + " for opcode at: 0x" +
3210 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3211 moveToEnd();
3212 return;
3213 }
3214 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3215 "mach-o-rebase",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3216 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3217 << format("SegmentOffset=0x%06X", SegmentOffset)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3218 << ", AdvanceAmount=" << AdvanceAmountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3219 << ", RemainingLoopCount=" << RemainingLoopCountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3220 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
;
3221 return;
3222 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
3223 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3224 true);
3225 if (error) {
3226 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3227 Twine(error) + " for opcode at: 0x" +
3228 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3229 moveToEnd();
3230 return;
3231 }
3232 Skip = readULEB128(&error);
3233 if (error) {
3234 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3235 Twine(error) + " for opcode at: 0x" +
3236 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3237 moveToEnd();
3238 return;
3239 }
3240 AdvanceAmount = Skip + PointerSize;
3241 Count = 1;
3242 RemainingLoopCount = 0;
3243 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3244 SegmentIndex, SegmentOffset);
3245 if (error) {
3246 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3247 Twine(error) + " for opcode at: 0x" +
3248 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3249 moveToEnd();
3250 return;
3251 }
3252 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3253 "mach-o-rebase",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3254 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3255 << format("SegmentOffset=0x%06X", SegmentOffset)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3256 << ", AdvanceAmount=" << AdvanceAmountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3257 << ", RemainingLoopCount=" << RemainingLoopCountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3258 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
;
3259 return;
3260 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
3261 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3262 true);
3263 if (error) {
3264 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3265 "ULEB " +
3266 Twine(error) + " for opcode at: 0x" +
3267 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3268 moveToEnd();
3269 return;
3270 }
3271 Count = readULEB128(&error);
3272 if (error) {
3273 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3274 "ULEB " +
3275 Twine(error) + " for opcode at: 0x" +
3276 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3277 moveToEnd();
3278 return;
3279 }
3280 if (Count != 0)
3281 RemainingLoopCount = Count - 1;
3282 else
3283 RemainingLoopCount = 0;
3284 Skip = readULEB128(&error);
3285 if (error) {
3286 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3287 "ULEB " +
3288 Twine(error) + " for opcode at: 0x" +
3289 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3290 moveToEnd();
3291 return;
3292 }
3293 AdvanceAmount = Skip + PointerSize;
3294
3295 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3296 SegmentIndex, SegmentOffset);
3297 if (error) {
3298 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3299 "ULEB " +
3300 Twine(error) + " for opcode at: 0x" +
3301 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3302 moveToEnd();
3303 return;
3304 }
3305 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3306 "mach-o-rebase",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3307 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3308 << format("SegmentOffset=0x%06X", SegmentOffset)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3309 << ", AdvanceAmount=" << AdvanceAmountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3310 << ", RemainingLoopCount=" << RemainingLoopCountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3311 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-rebase")) { dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
;
3312 return;
3313 default:
3314 *E = malformedError("bad rebase info (bad opcode value 0x" +
3315 Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3316 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3317 moveToEnd();
3318 return;
3319 }
3320 }
3321}
3322
3323uint64_t MachORebaseEntry::readULEB128(const char **error) {
3324 unsigned Count;
3325 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3326 Ptr += Count;
3327 if (Ptr > Opcodes.end())
3328 Ptr = Opcodes.end();
3329 return Result;
3330}
3331
3332int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
3333
3334uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3335
3336StringRef MachORebaseEntry::typeName() const {
3337 switch (RebaseType) {
3338 case MachO::REBASE_TYPE_POINTER:
3339 return "pointer";
3340 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3341 return "text abs32";
3342 case MachO::REBASE_TYPE_TEXT_PCREL32:
3343 return "text rel32";
3344 }
3345 return "unknown";
3346}
3347
3348// For use with the SegIndex of a checked Mach-O Rebase entry
3349// to get the segment name.
3350StringRef MachORebaseEntry::segmentName() const {
3351 return O->BindRebaseSegmentName(SegmentIndex);
3352}
3353
3354// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3355// to get the section name.
3356StringRef MachORebaseEntry::sectionName() const {
3357 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3358}
3359
3360// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3361// to get the address.
3362uint64_t MachORebaseEntry::address() const {
3363 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3364}
3365
3366bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
3367#ifdef EXPENSIVE_CHECKS
3368 assert(Opcodes == Other.Opcodes && "compare iterators of different files")(static_cast <bool> (Opcodes == Other.Opcodes &&
"compare iterators of different files") ? void (0) : __assert_fail
("Opcodes == Other.Opcodes && \"compare iterators of different files\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 3368, __extension__ __PRETTY_FUNCTION__))
;
3369#else
3370 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files")(static_cast <bool> (Opcodes.data() == Other.Opcodes.data
() && "compare iterators of different files") ? void (
0) : __assert_fail ("Opcodes.data() == Other.Opcodes.data() && \"compare iterators of different files\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 3370, __extension__ __PRETTY_FUNCTION__))
;
3371#endif
3372 return (Ptr == Other.Ptr) &&
3373 (RemainingLoopCount == Other.RemainingLoopCount) &&
3374 (Done == Other.Done);
3375}
3376
3377iterator_range<rebase_iterator>
3378MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3379 ArrayRef<uint8_t> Opcodes, bool is64) {
3380 if (O->BindRebaseSectionTable == nullptr)
3381 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3382 MachORebaseEntry Start(&Err, O, Opcodes, is64);
3383 Start.moveToFirst();
3384
3385 MachORebaseEntry Finish(&Err, O, Opcodes, is64);
3386 Finish.moveToEnd();
3387
3388 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
3389}
3390
3391iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3392 return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
3393}
3394
3395MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3396 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
3397 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3398 PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
3399
3400void MachOBindEntry::moveToFirst() {
3401 Ptr = Opcodes.begin();
3402 moveNext();
3403}
3404
3405void MachOBindEntry::moveToEnd() {
3406 Ptr = Opcodes.end();
3407 RemainingLoopCount = 0;
3408 Done = true;
3409}
3410
3411void MachOBindEntry::moveNext() {
3412 ErrorAsOutParameter ErrAsOutParam(E);
3413 // If in the middle of some loop, move to next binding in loop.
3414 SegmentOffset += AdvanceAmount;
3415 if (RemainingLoopCount) {
3416 --RemainingLoopCount;
3417 return;
3418 }
3419 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3420 // pointer size. Therefore it is possible to reach the end without ever having
3421 // seen BIND_OPCODE_DONE.
3422 if (Ptr == Opcodes.end()) {
3423 Done = true;
3424 return;
3425 }
3426 bool More = true;
3427 while (More) {
3428 // Parse next opcode and set up next loop.
3429 const uint8_t *OpcodeStart = Ptr;
3430 uint8_t Byte = *Ptr++;
3431 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3432 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3433 int8_t SignExtended;
3434 const uint8_t *SymStart;
3435 uint32_t Count, Skip;
3436 const char *error = nullptr;
3437 switch (Opcode) {
3438 case MachO::BIND_OPCODE_DONE:
3439 if (TableKind == Kind::Lazy) {
3440 // Lazying bindings have a DONE opcode between entries. Need to ignore
3441 // it to advance to next entry. But need not if this is last entry.
3442 bool NotLastEntry = false;
3443 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3444 if (*P) {
3445 NotLastEntry = true;
3446 }
3447 }
3448 if (NotLastEntry)
3449 break;
3450 }
3451 More = false;
3452 moveToEnd();
3453 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DONE\n"; } } while
(false)
;
3454 break;
3455 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
3456 if (TableKind == Kind::Weak) {
3457 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3458 "weak bind table for opcode at: 0x" +
3459 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3460 moveToEnd();
3461 return;
3462 }
3463 Ordinal = ImmValue;
3464 LibraryOrdinalSet = true;
3465 if (ImmValue > O->getLibraryCount()) {
3466 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3467 "library ordinal: " +
3468 Twine((int)ImmValue) + " (max " +
3469 Twine((int)O->getLibraryCount()) +
3470 ") for opcode at: 0x" +
3471 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3472 moveToEnd();
3473 return;
3474 }
3475 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
3476 "mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
3477 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
3478 << "Ordinal=" << Ordinal << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
;
3479 break;
3480 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
3481 if (TableKind == Kind::Weak) {
3482 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3483 "weak bind table for opcode at: 0x" +
3484 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3485 moveToEnd();
3486 return;
3487 }
3488 Ordinal = readULEB128(&error);
3489 LibraryOrdinalSet = true;
3490 if (error) {
3491 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3492 Twine(error) + " for opcode at: 0x" +
3493 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3494 moveToEnd();
3495 return;
3496 }
3497 if (Ordinal > (int)O->getLibraryCount()) {
3498 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3499 "library ordinal: " +
3500 Twine((int)Ordinal) + " (max " +
3501 Twine((int)O->getLibraryCount()) +
3502 ") for opcode at: 0x" +
3503 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3504 moveToEnd();
3505 return;
3506 }
3507 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
3508 "mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
3509 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
3510 << "Ordinal=" << Ordinal << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
;
3511 break;
3512 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
3513 if (TableKind == Kind::Weak) {
3514 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3515 "weak bind table for opcode at: 0x" +
3516 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3517 moveToEnd();
3518 return;
3519 }
3520 if (ImmValue) {
3521 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3522 Ordinal = SignExtended;
3523 if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3524 *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3525 "special ordinal: " +
3526 Twine((int)Ordinal) + " for opcode at: 0x" +
3527 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3528 moveToEnd();
3529 return;
3530 }
3531 } else
3532 Ordinal = 0;
3533 LibraryOrdinalSet = true;
3534 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
3535 "mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
3536 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
3537 << "Ordinal=" << Ordinal << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
<< "Ordinal=" << Ordinal << "\n"; } } while
(false)
;
3538 break;
3539 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3540 Flags = ImmValue;
3541 SymStart = Ptr;
3542 while (*Ptr && (Ptr < Opcodes.end())) {
3543 ++Ptr;
3544 }
3545 if (Ptr == Opcodes.end()) {
3546 *E = malformedError(
3547 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3548 "symbol name extends past opcodes for opcode at: 0x" +
3549 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3550 moveToEnd();
3551 return;
3552 }
3553 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3554 Ptr-SymStart);
3555 ++Ptr;
3556 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
<< "SymbolName=" << SymbolName << "\n"; } }
while (false)
3557 "mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
<< "SymbolName=" << SymbolName << "\n"; } }
while (false)
3558 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
<< "SymbolName=" << SymbolName << "\n"; } }
while (false)
3559 << "SymbolName=" << SymbolName << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
<< "SymbolName=" << SymbolName << "\n"; } }
while (false)
;
3560 if (TableKind == Kind::Weak) {
3561 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3562 return;
3563 }
3564 break;
3565 case MachO::BIND_OPCODE_SET_TYPE_IMM:
3566 BindType = ImmValue;
3567 if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
3568 *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3569 Twine((int)ImmValue) + " for opcode at: 0x" +
3570 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3571 moveToEnd();
3572 return;
3573 }
3574 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
<< "BindType=" << (int)BindType << "\n"; }
} while (false)
3575 "mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
<< "BindType=" << (int)BindType << "\n"; }
} while (false)
3576 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
<< "BindType=" << (int)BindType << "\n"; }
} while (false)
3577 << "BindType=" << (int)BindType << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
<< "BindType=" << (int)BindType << "\n"; }
} while (false)
;
3578 break;
3579 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
3580 Addend = readSLEB128(&error);
3581 if (error) {
3582 *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
3583 " for opcode at: 0x" +
3584 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3585 moveToEnd();
3586 return;
3587 }
3588 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
<< "Addend=" << Addend << "\n"; } } while (
false)
3589 "mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
<< "Addend=" << Addend << "\n"; } } while (
false)
3590 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
<< "Addend=" << Addend << "\n"; } } while (
false)
3591 << "Addend=" << Addend << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
<< "Addend=" << Addend << "\n"; } } while (
false)
;
3592 break;
3593 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3594 SegmentIndex = ImmValue;
3595 SegmentOffset = readULEB128(&error);
3596 if (error) {
3597 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3598 Twine(error) + " for opcode at: 0x" +
3599 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3600 moveToEnd();
3601 return;
3602 }
3603 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3604 if (error) {
3605 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3606 Twine(error) + " for opcode at: 0x" +
3607 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3608 moveToEnd();
3609 return;
3610 }
3611 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3612 "mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3613 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3614 << "SegmentIndex=" << SegmentIndex << ", "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3615 << format("SegmentOffset=0x%06X", SegmentOffset)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3616 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
<< "SegmentIndex=" << SegmentIndex << ", "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
;
3617 break;
3618 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
3619 SegmentOffset += readULEB128(&error);
3620 if (error) {
3621 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3622 " for opcode at: 0x" +
3623 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3624 moveToEnd();
3625 return;
3626 }
3627 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3628 if (error) {
3629 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3630 " for opcode at: 0x" +
3631 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3632 moveToEnd();
3633 return;
3634 }
3635 DEBUG_WITH_TYPE("mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3636 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3637 << format("SegmentOffset=0x%06X",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3638 SegmentOffset) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
;
3639 break;
3640 case MachO::BIND_OPCODE_DO_BIND:
3641 AdvanceAmount = PointerSize;
3642 RemainingLoopCount = 0;
3643 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3644 if (error) {
3645 *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
3646 " for opcode at: 0x" +
3647 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3648 moveToEnd();
3649 return;
3650 }
3651 if (SymbolName == StringRef()) {
3652 *E = malformedError(
3653 "for BIND_OPCODE_DO_BIND missing preceding "
3654 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3655 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3656 moveToEnd();
3657 return;
3658 }
3659 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3660 *E =
3661 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3662 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3663 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3664 moveToEnd();
3665 return;
3666 }
3667 DEBUG_WITH_TYPE("mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND: " <<
format("SegmentOffset=0x%06X", SegmentOffset) << "\n";
} } while (false)
3668 dbgs() << "BIND_OPCODE_DO_BIND: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND: " <<
format("SegmentOffset=0x%06X", SegmentOffset) << "\n";
} } while (false)
3669 << format("SegmentOffset=0x%06X",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND: " <<
format("SegmentOffset=0x%06X", SegmentOffset) << "\n";
} } while (false)
3670 SegmentOffset) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND: " <<
format("SegmentOffset=0x%06X", SegmentOffset) << "\n";
} } while (false)
;
3671 return;
3672 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
3673 if (TableKind == Kind::Lazy) {
3674 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3675 "lazy bind table for opcode at: 0x" +
3676 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3677 moveToEnd();
3678 return;
3679 }
3680 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3681 if (error) {
3682 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3683 Twine(error) + " for opcode at: 0x" +
3684 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3685 moveToEnd();
3686 return;
3687 }
3688 if (SymbolName == StringRef()) {
3689 *E = malformedError(
3690 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3691 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3692 "at: 0x" +
3693 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3694 moveToEnd();
3695 return;
3696 }
3697 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3698 *E = malformedError(
3699 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3700 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3701 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3702 moveToEnd();
3703 return;
3704 }
3705 AdvanceAmount = readULEB128(&error) + PointerSize;
3706 if (error) {
3707 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3708 Twine(error) + " for opcode at: 0x" +
3709 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3710 moveToEnd();
3711 return;
3712 }
3713 // Note, this is not really an error until the next bind but make no sense
3714 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3715 // bind operation.
3716 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3717 AdvanceAmount, false);
3718 if (error) {
3719 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3720 "ULEB) " +
3721 Twine(error) + " for opcode at: 0x" +
3722 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3723 moveToEnd();
3724 return;
3725 }
3726 RemainingLoopCount = 0;
3727 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3728 "mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3729 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3730 << format("SegmentOffset=0x%06X", SegmentOffset)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3731 << ", AdvanceAmount=" << AdvanceAmountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3732 << ", RemainingLoopCount=" << RemainingLoopCountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3733 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
;
3734 return;
3735 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
3736 if (TableKind == Kind::Lazy) {
3737 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3738 "allowed in lazy bind table for opcode at: 0x" +
3739 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3740 moveToEnd();
3741 return;
3742 }
3743 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3744 if (error) {
3745 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3746 Twine(error) + " for opcode at: 0x" +
3747 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3748 moveToEnd();
3749 return;
3750 }
3751 if (SymbolName == StringRef()) {
3752 *E = malformedError(
3753 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3754 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3755 "opcode at: 0x" +
3756 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3757 moveToEnd();
3758 return;
3759 }
3760 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3761 *E = malformedError(
3762 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3763 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3764 "at: 0x" +
3765 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3766 moveToEnd();
3767 return;
3768 }
3769 AdvanceAmount = ImmValue * PointerSize + PointerSize;
3770 RemainingLoopCount = 0;
3771 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3772 AdvanceAmount, false);
3773 if (error) {
3774 *E =
3775 malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3776 " (after adding immediate times the pointer size) " +
3777 Twine(error) + " for opcode at: 0x" +
3778 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3779 moveToEnd();
3780 return;
3781 }
3782 DEBUG_WITH_TYPE("mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3783 dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3784 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
3785 << format("SegmentOffset=0x%06X", SegmentOffset) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
"\n"; } } while (false)
;
3786 return;
3787 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
3788 if (TableKind == Kind::Lazy) {
3789 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3790 "allowed in lazy bind table for opcode at: 0x" +
3791 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3792 moveToEnd();
3793 return;
3794 }
3795 Count = readULEB128(&error);
3796 if (Count != 0)
3797 RemainingLoopCount = Count - 1;
3798 else
3799 RemainingLoopCount = 0;
3800 if (error) {
3801 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3802 " (count value) " +
3803 Twine(error) + " for opcode at: 0x" +
3804 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3805 moveToEnd();
3806 return;
3807 }
3808 Skip = readULEB128(&error);
3809 AdvanceAmount = Skip + PointerSize;
3810 if (error) {
3811 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3812 " (skip value) " +
3813 Twine(error) + " for opcode at: 0x" +
3814 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3815 moveToEnd();
3816 return;
3817 }
3818 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3819 if (error) {
3820 *E =
3821 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3822 Twine(error) + " for opcode at: 0x" +
3823 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3824 moveToEnd();
3825 return;
3826 }
3827 if (SymbolName == StringRef()) {
3828 *E = malformedError(
3829 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3830 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3831 "opcode at: 0x" +
3832 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3833 moveToEnd();
3834 return;
3835 }
3836 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3837 *E = malformedError(
3838 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3839 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3840 "at: 0x" +
3841 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3842 moveToEnd();
3843 return;
3844 }
3845 error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
3846 SegmentIndex, SegmentOffset);
3847 if (error) {
3848 *E =
3849 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3850 Twine(error) + " for opcode at: 0x" +
3851 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3852 moveToEnd();
3853 return;
3854 }
3855 DEBUG_WITH_TYPE(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3856 "mach-o-bind",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3857 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3858 << format("SegmentOffset=0x%06X", SegmentOffset)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3859 << ", AdvanceAmount=" << AdvanceAmountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3860 << ", RemainingLoopCount=" << RemainingLoopCountdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
3861 << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mach-o-bind")) { dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
<< format("SegmentOffset=0x%06X", SegmentOffset) <<
", AdvanceAmount=" << AdvanceAmount << ", RemainingLoopCount="
<< RemainingLoopCount << "\n"; } } while (false)
;
3862 return;
3863 default:
3864 *E = malformedError("bad bind info (bad opcode value 0x" +
3865 Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3866 Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3867 moveToEnd();
3868 return;
3869 }
3870 }
3871}
3872
3873uint64_t MachOBindEntry::readULEB128(const char **error) {
3874 unsigned Count;
3875 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3876 Ptr += Count;
3877 if (Ptr > Opcodes.end())
3878 Ptr = Opcodes.end();
3879 return Result;
3880}
3881
3882int64_t MachOBindEntry::readSLEB128(const char **error) {
3883 unsigned Count;
3884 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
3885 Ptr += Count;
3886 if (Ptr > Opcodes.end())
3887 Ptr = Opcodes.end();
3888 return Result;
3889}
3890
3891int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
3892
3893uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3894
3895StringRef MachOBindEntry::typeName() const {
3896 switch (BindType) {
3897 case MachO::BIND_TYPE_POINTER:
3898 return "pointer";
3899 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3900 return "text abs32";
3901 case MachO::BIND_TYPE_TEXT_PCREL32:
3902 return "text rel32";
3903 }
3904 return "unknown";
3905}
3906
3907StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3908
3909int64_t MachOBindEntry::addend() const { return Addend; }
3910
3911uint32_t MachOBindEntry::flags() const { return Flags; }
3912
3913int MachOBindEntry::ordinal() const { return Ordinal; }
3914
3915// For use with the SegIndex of a checked Mach-O Bind entry
3916// to get the segment name.
3917StringRef MachOBindEntry::segmentName() const {
3918 return O->BindRebaseSegmentName(SegmentIndex);
3919}
3920
3921// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3922// to get the section name.
3923StringRef MachOBindEntry::sectionName() const {
3924 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3925}
3926
3927// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3928// to get the address.
3929uint64_t MachOBindEntry::address() const {
3930 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3931}
3932
3933bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
3934#ifdef EXPENSIVE_CHECKS
3935 assert(Opcodes == Other.Opcodes && "compare iterators of different files")(static_cast <bool> (Opcodes == Other.Opcodes &&
"compare iterators of different files") ? void (0) : __assert_fail
("Opcodes == Other.Opcodes && \"compare iterators of different files\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 3935, __extension__ __PRETTY_FUNCTION__))
;
3936#else
3937 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files")(static_cast <bool> (Opcodes.data() == Other.Opcodes.data
() && "compare iterators of different files") ? void (
0) : __assert_fail ("Opcodes.data() == Other.Opcodes.data() && \"compare iterators of different files\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 3937, __extension__ __PRETTY_FUNCTION__))
;
3938#endif
3939 return (Ptr == Other.Ptr) &&
3940 (RemainingLoopCount == Other.RemainingLoopCount) &&
3941 (Done == Other.Done);
3942}
3943
3944// Build table of sections so SegIndex/SegOffset pairs can be translated.
3945BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
3946 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
5
Assuming the condition is false
6
'?' condition is false
3947 StringRef CurSegName;
3948 uint64_t CurSegAddress;
7
'CurSegAddress' declared without an initial value
3949 for (const SectionRef &Section : Obj->sections()) {
3950 SectionInfo Info;
3951 Section.getName(Info.SectionName);
3952 Info.Address = Section.getAddress();
3953 Info.Size = Section.getSize();
3954 Info.SegmentName =
3955 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
3956 if (!Info.SegmentName.equals(CurSegName)) {
8
Assuming the condition is false
9
Taking false branch
3957 ++CurSegIndex;
3958 CurSegName = Info.SegmentName;
3959 CurSegAddress = Info.Address;
3960 }
3961 Info.SegmentIndex = CurSegIndex - 1;
3962 Info.OffsetInSegment = Info.Address - CurSegAddress;
10
The right operand of '-' is a garbage value
3963 Info.SegmentStartAddress = CurSegAddress;
3964 Sections.push_back(Info);
3965 }
3966 MaxSegIndex = CurSegIndex;
3967}
3968
3969// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
3970// validate a MachOBindEntry or MachORebaseEntry.
3971const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
3972 uint64_t SegOffset,
3973 bool endInvalid) {
3974 if (SegIndex == -1)
3975 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
3976 if (SegIndex >= MaxSegIndex)
3977 return "bad segIndex (too large)";
3978 for (const SectionInfo &SI : Sections) {
3979 if (SI.SegmentIndex != SegIndex)
3980 continue;
3981 if (SI.OffsetInSegment > SegOffset)
3982 continue;
3983 if (SegOffset > (SI.OffsetInSegment + SI.Size))
3984 continue;
3985 if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
3986 continue;
3987 return nullptr;
3988 }
3989 return "bad segOffset, too large";
3990}
3991
3992// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
3993// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
3994// MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
3995// REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
3996// been already checked.
3997const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
3998 uint8_t PointerSize,
3999 int32_t SegIndex,
4000 uint64_t SegOffset) {
4001 const SectionInfo &SI = findSection(SegIndex, SegOffset);
4002 uint64_t addr = SI.SegmentStartAddress + SegOffset;
4003 if (addr >= SI.Address + SI.Size)
4004 return "bad segOffset, too large";
4005 uint64_t i = 0;
4006 if (Count > 1)
4007 i = (Skip + PointerSize) * (Count - 1);
4008 else if (Count == 1)
4009 i = Skip + PointerSize;
4010 if (addr + i >= SI.Address + SI.Size) {
4011 // For rebase opcodes they can step from one section to another.
4012 uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
4013 const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
4014 if (error)
4015 return "bad count and skip, too large";
4016 }
4017 return nullptr;
4018}
4019
4020// For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4021// to get the segment name.
4022StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
4023 for (const SectionInfo &SI : Sections) {
4024 if (SI.SegmentIndex == SegIndex)
4025 return SI.SegmentName;
4026 }
4027 llvm_unreachable("invalid SegIndex")::llvm::llvm_unreachable_internal("invalid SegIndex", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 4027)
;
4028}
4029
4030// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4031// to get the SectionInfo.
4032const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
4033 int32_t SegIndex, uint64_t SegOffset) {
4034 for (const SectionInfo &SI : Sections) {
4035 if (SI.SegmentIndex != SegIndex)
4036 continue;
4037 if (SI.OffsetInSegment > SegOffset)
4038 continue;
4039 if (SegOffset >= (SI.OffsetInSegment + SI.Size))
4040 continue;
4041 return SI;
4042 }
4043 llvm_unreachable("SegIndex and SegOffset not in any section")::llvm::llvm_unreachable_internal("SegIndex and SegOffset not in any section"
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 4043)
;
4044}
4045
4046// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4047// entry to get the section name.
4048StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
4049 uint64_t SegOffset) {
4050 return findSection(SegIndex, SegOffset).SectionName;
4051}
4052
4053// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4054// entry to get the address.
4055uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
4056 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
4057 return SI.SegmentStartAddress + OffsetInSeg;
4058}
4059
4060iterator_range<bind_iterator>
4061MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
4062 ArrayRef<uint8_t> Opcodes, bool is64,
4063 MachOBindEntry::Kind BKind) {
4064 if (O->BindRebaseSectionTable == nullptr)
2
Taking true branch
4065 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3
Calling 'make_unique'
4066 MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
4067 Start.moveToFirst();
4068
4069 MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
4070 Finish.moveToEnd();
4071
4072 return make_range(bind_iterator(Start), bind_iterator(Finish));
4073}
4074
4075iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
4076 return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
4077 MachOBindEntry::Kind::Regular);
4078}
4079
4080iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
4081 return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4082 MachOBindEntry::Kind::Lazy);
4083}
4084
4085iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
4086 return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
1
Calling 'MachOObjectFile::bindTable'
4087 MachOBindEntry::Kind::Weak);
4088}
4089
4090MachOObjectFile::load_command_iterator
4091MachOObjectFile::begin_load_commands() const {
4092 return LoadCommands.begin();
4093}
4094
4095MachOObjectFile::load_command_iterator
4096MachOObjectFile::end_load_commands() const {
4097 return LoadCommands.end();
4098}
4099
4100iterator_range<MachOObjectFile::load_command_iterator>
4101MachOObjectFile::load_commands() const {
4102 return make_range(begin_load_commands(), end_load_commands());
4103}
4104
4105StringRef
4106MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
4107 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
4108 return parseSegmentOrSectionName(Raw.data());
4109}
4110
4111ArrayRef<char>
4112MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
4113 assert(Sec.d.a < Sections.size() && "Should have detected this earlier")(static_cast <bool> (Sec.d.a < Sections.size() &&
"Should have detected this earlier") ? void (0) : __assert_fail
("Sec.d.a < Sections.size() && \"Should have detected this earlier\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 4113, __extension__ __PRETTY_FUNCTION__))
;
4114 const section_base *Base =
4115 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4116 return makeArrayRef(Base->sectname);
4117}
4118
4119ArrayRef<char>
4120MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
4121 assert(Sec.d.a < Sections.size() && "Should have detected this earlier")(static_cast <bool> (Sec.d.a < Sections.size() &&
"Should have detected this earlier") ? void (0) : __assert_fail
("Sec.d.a < Sections.size() && \"Should have detected this earlier\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 4121, __extension__ __PRETTY_FUNCTION__))
;
4122 const section_base *Base =
4123 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4124 return makeArrayRef(Base->segname);
4125}
4126
4127bool
4128MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
4129 const {
4130 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
4131 return false;
4132 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
4133}
4134
4135unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4136 const MachO::any_relocation_info &RE) const {
4137 if (isLittleEndian())
4138 return RE.r_word1 & 0xffffff;
4139 return RE.r_word1 >> 8;
4140}
4141
4142bool MachOObjectFile::getPlainRelocationExternal(
4143 const MachO::any_relocation_info &RE) const {
4144 if (isLittleEndian())
4145 return (RE.r_word1 >> 27) & 1;
4146 return (RE.r_word1 >> 4) & 1;
4147}
4148
4149bool MachOObjectFile::getScatteredRelocationScattered(
4150 const MachO::any_relocation_info &RE) const {
4151 return RE.r_word0 >> 31;
4152}
4153
4154uint32_t MachOObjectFile::getScatteredRelocationValue(
4155 const MachO::any_relocation_info &RE) const {
4156 return RE.r_word1;
4157}
4158
4159uint32_t MachOObjectFile::getScatteredRelocationType(
4160 const MachO::any_relocation_info &RE) const {
4161 return (RE.r_word0 >> 24) & 0xf;
4162}
4163
4164unsigned MachOObjectFile::getAnyRelocationAddress(
4165 const MachO::any_relocation_info &RE) const {
4166 if (isRelocationScattered(RE))
4167 return getScatteredRelocationAddress(RE);
4168 return getPlainRelocationAddress(RE);
4169}
4170
4171unsigned MachOObjectFile::getAnyRelocationPCRel(
4172 const MachO::any_relocation_info &RE) const {
4173 if (isRelocationScattered(RE))
4174 return getScatteredRelocationPCRel(RE);
4175 return getPlainRelocationPCRel(*this, RE);
4176}
4177
4178unsigned MachOObjectFile::getAnyRelocationLength(
4179 const MachO::any_relocation_info &RE) const {
4180 if (isRelocationScattered(RE))
4181 return getScatteredRelocationLength(RE);
4182 return getPlainRelocationLength(*this, RE);
4183}
4184
4185unsigned
4186MachOObjectFile::getAnyRelocationType(
4187 const MachO::any_relocation_info &RE) const {
4188 if (isRelocationScattered(RE))
4189 return getScatteredRelocationType(RE);
4190 return getPlainRelocationType(*this, RE);
4191}
4192
4193SectionRef
4194MachOObjectFile::getAnyRelocationSection(
4195 const MachO::any_relocation_info &RE) const {
4196 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
4197 return *section_end();
4198 unsigned SecNum = getPlainRelocationSymbolNum(RE);
4199 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
4200 return *section_end();
4201 DataRefImpl DRI;
4202 DRI.d.a = SecNum - 1;
4203 return SectionRef(DRI, this);
4204}
4205
4206MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
4207 assert(DRI.d.a < Sections.size() && "Should have detected this earlier")(static_cast <bool> (DRI.d.a < Sections.size() &&
"Should have detected this earlier") ? void (0) : __assert_fail
("DRI.d.a < Sections.size() && \"Should have detected this earlier\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 4207, __extension__ __PRETTY_FUNCTION__))
;
4208 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
4209}
4210
4211MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
4212 assert(DRI.d.a < Sections.size() && "Should have detected this earlier")(static_cast <bool> (DRI.d.a < Sections.size() &&
"Should have detected this earlier") ? void (0) : __assert_fail
("DRI.d.a < Sections.size() && \"Should have detected this earlier\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 4212, __extension__ __PRETTY_FUNCTION__))
;
4213 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
4214}
4215
4216MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
4217 unsigned Index) const {
4218 const char *Sec = getSectionPtr(*this, L, Index);
4219 return getStruct<MachO::section>(*this, Sec);
4220}
4221
4222MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4223 unsigned Index) const {
4224 const char *Sec = getSectionPtr(*this, L, Index);
4225 return getStruct<MachO::section_64>(*this, Sec);
4226}
4227
4228MachO::nlist
4229MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
4230 const char *P = reinterpret_cast<const char *>(DRI.p);
4231 return getStruct<MachO::nlist>(*this, P);
4232}
4233
4234MachO::nlist_64
4235MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
4236 const char *P = reinterpret_cast<const char *>(DRI.p);
4237 return getStruct<MachO::nlist_64>(*this, P);
4238}
4239
4240MachO::linkedit_data_command
4241MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
4242 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
4243}
4244
4245MachO::segment_command
4246MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
4247 return getStruct<MachO::segment_command>(*this, L.Ptr);
4248}
4249
4250MachO::segment_command_64
4251MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
4252 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
4253}
4254
4255MachO::linker_option_command
4256MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
4257 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
4258}
4259
4260MachO::version_min_command
4261MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
4262 return getStruct<MachO::version_min_command>(*this, L.Ptr);
4263}
4264
4265MachO::note_command
4266MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
4267 return getStruct<MachO::note_command>(*this, L.Ptr);
4268}
4269
4270MachO::build_version_command
4271MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
4272 return getStruct<MachO::build_version_command>(*this, L.Ptr);
4273}
4274
4275MachO::build_tool_version
4276MachOObjectFile::getBuildToolVersion(unsigned index) const {
4277 return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
4278}
4279
4280MachO::dylib_command
4281MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
4282 return getStruct<MachO::dylib_command>(*this, L.Ptr);
4283}
4284
4285MachO::dyld_info_command
4286MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
4287 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
4288}
4289
4290MachO::dylinker_command
4291MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
4292 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
4293}
4294
4295MachO::uuid_command
4296MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
4297 return getStruct<MachO::uuid_command>(*this, L.Ptr);
4298}
4299
4300MachO::rpath_command
4301MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
4302 return getStruct<MachO::rpath_command>(*this, L.Ptr);
4303}
4304
4305MachO::source_version_command
4306MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
4307 return getStruct<MachO::source_version_command>(*this, L.Ptr);
4308}
4309
4310MachO::entry_point_command
4311MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
4312 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
4313}
4314
4315MachO::encryption_info_command
4316MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
4317 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
4318}
4319
4320MachO::encryption_info_command_64
4321MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
4322 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
4323}
4324
4325MachO::sub_framework_command
4326MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
4327 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
4328}
4329
4330MachO::sub_umbrella_command
4331MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
4332 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
4333}
4334
4335MachO::sub_library_command
4336MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
4337 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
4338}
4339
4340MachO::sub_client_command
4341MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
4342 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
4343}
4344
4345MachO::routines_command
4346MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
4347 return getStruct<MachO::routines_command>(*this, L.Ptr);
4348}
4349
4350MachO::routines_command_64
4351MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
4352 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
4353}
4354
4355MachO::thread_command
4356MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
4357 return getStruct<MachO::thread_command>(*this, L.Ptr);
4358}
4359
4360MachO::any_relocation_info
4361MachOObjectFile::getRelocation(DataRefImpl Rel) const {
4362 uint32_t Offset;
4363 if (getHeader().filetype == MachO::MH_OBJECT) {
4364 DataRefImpl Sec;
4365 Sec.d.a = Rel.d.a;
4366 if (is64Bit()) {
4367 MachO::section_64 Sect = getSection64(Sec);
4368 Offset = Sect.reloff;
4369 } else {
4370 MachO::section Sect = getSection(Sec);
4371 Offset = Sect.reloff;
4372 }
4373 } else {
4374 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
4375 if (Rel.d.a == 0)
4376 Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
4377 else
4378 Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
4379 }
4380
4381 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
4382 getPtr(*this, Offset)) + Rel.d.b;
4383 return getStruct<MachO::any_relocation_info>(
4384 *this, reinterpret_cast<const char *>(P));
4385}
4386
4387MachO::data_in_code_entry
4388MachOObjectFile::getDice(DataRefImpl Rel) const {
4389 const char *P = reinterpret_cast<const char *>(Rel.p);
4390 return getStruct<MachO::data_in_code_entry>(*this, P);
4391}
4392
4393const MachO::mach_header &MachOObjectFile::getHeader() const {
4394 return Header;
4395}
4396
4397const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4398 assert(is64Bit())(static_cast <bool> (is64Bit()) ? void (0) : __assert_fail
("is64Bit()", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Object/MachOObjectFile.cpp"
, 4398, __extension__ __PRETTY_FUNCTION__))
;
4399 return Header64;
4400}
4401
4402uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4403 const MachO::dysymtab_command &DLC,
4404 unsigned Index) const {
4405 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
4406 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
4407}
4408
4409MachO::data_in_code_entry
4410MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4411 unsigned Index) const {
4412 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
4413 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
4414}
4415
4416MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
4417 if (SymtabLoadCmd)
4418 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
4419
4420 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4421 MachO::symtab_command Cmd;
4422 Cmd.cmd = MachO::LC_SYMTAB;
4423 Cmd.cmdsize = sizeof(MachO::symtab_command);
4424 Cmd.symoff = 0;
4425 Cmd.nsyms = 0;
4426 Cmd.stroff = 0;
4427 Cmd.strsize = 0;
4428 return Cmd;
4429}
4430
4431MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
4432 if (DysymtabLoadCmd)
4433 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
4434
4435 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4436 MachO::dysymtab_command Cmd;
4437 Cmd.cmd = MachO::LC_DYSYMTAB;
4438 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4439 Cmd.ilocalsym = 0;
4440 Cmd.nlocalsym = 0;
4441 Cmd.iextdefsym = 0;
4442 Cmd.nextdefsym = 0;
4443 Cmd.iundefsym = 0;
4444 Cmd.nundefsym = 0;
4445 Cmd.tocoff = 0;
4446 Cmd.ntoc = 0;
4447 Cmd.modtaboff = 0;
4448 Cmd.nmodtab = 0;
4449 Cmd.extrefsymoff = 0;
4450 Cmd.nextrefsyms = 0;
4451 Cmd.indirectsymoff = 0;
4452 Cmd.nindirectsyms = 0;
4453 Cmd.extreloff = 0;
4454 Cmd.nextrel = 0;
4455 Cmd.locreloff = 0;
4456 Cmd.nlocrel = 0;
4457 return Cmd;
4458}
4459
4460MachO::linkedit_data_command
4461MachOObjectFile::getDataInCodeLoadCommand() const {
4462 if (DataInCodeLoadCmd)
4463 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
4464
4465 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4466 MachO::linkedit_data_command Cmd;
4467 Cmd.cmd = MachO::LC_DATA_IN_CODE;
4468 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4469 Cmd.dataoff = 0;
4470 Cmd.datasize = 0;
4471 return Cmd;
4472}
4473
4474MachO::linkedit_data_command
4475MachOObjectFile::getLinkOptHintsLoadCommand() const {
4476 if (LinkOptHintsLoadCmd)
4477 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
4478
4479 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4480 // fields.
4481 MachO::linkedit_data_command Cmd;
4482 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4483 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4484 Cmd.dataoff = 0;
4485 Cmd.datasize = 0;
4486 return Cmd;
4487}
4488
4489ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4490 if (!DyldInfoLoadCmd)
4491 return None;
4492
4493 MachO::dyld_info_command DyldInfo =
4494 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4495 const uint8_t *Ptr =
4496 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
4497 return makeArrayRef(Ptr, DyldInfo.rebase_size);
4498}
4499
4500ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4501 if (!DyldInfoLoadCmd)
4502 return None;
4503
4504 MachO::dyld_info_command DyldInfo =
4505 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4506 const uint8_t *Ptr =
4507 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
4508 return makeArrayRef(Ptr, DyldInfo.bind_size);
4509}
4510
4511ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4512 if (!DyldInfoLoadCmd)
4513 return None;
4514
4515 MachO::dyld_info_command DyldInfo =
4516 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4517 const uint8_t *Ptr =
4518 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
4519 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
4520}
4521
4522ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4523 if (!DyldInfoLoadCmd)
4524 return None;
4525
4526 MachO::dyld_info_command DyldInfo =
4527 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4528 const uint8_t *Ptr =
4529 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
4530 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
4531}
4532
4533ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4534 if (!DyldInfoLoadCmd)
4535 return None;
4536
4537 MachO::dyld_info_command DyldInfo =
4538 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4539 const uint8_t *Ptr =
4540 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
4541 return makeArrayRef(Ptr, DyldInfo.export_size);
4542}
4543
4544ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
4545 if (!UuidLoadCmd)
4546 return None;
4547 // Returning a pointer is fine as uuid doesn't need endian swapping.
4548 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid)__builtin_offsetof(MachO::uuid_command, uuid);
4549 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
4550}
4551
4552StringRef MachOObjectFile::getStringTableData() const {
4553 MachO::symtab_command S = getSymtabLoadCommand();
4554 return getData().substr(S.stroff, S.strsize);
4555}
4556
4557bool MachOObjectFile::is64Bit() const {
4558 return getType() == getMachOType(false, true) ||
4559 getType() == getMachOType(true, true);
4560}
4561
4562void MachOObjectFile::ReadULEB128s(uint64_t Index,
4563 SmallVectorImpl<uint64_t> &Out) const {
4564 DataExtractor extractor(ObjectFile::getData(), true, 0);
4565
4566 uint32_t offset = Index;
4567 uint64_t data = 0;
4568 while (uint64_t delta = extractor.getULEB128(&offset)) {
4569 data += delta;
4570 Out.push_back(data);
4571 }
4572}
4573
4574bool MachOObjectFile::isRelocatableObject() const {
4575 return getHeader().filetype == MachO::MH_OBJECT;
4576}
4577
4578Expected<std::unique_ptr<MachOObjectFile>>
4579ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4580 uint32_t UniversalCputype,
4581 uint32_t UniversalIndex) {
4582 StringRef Magic = Buffer.getBuffer().slice(0, 4);
4583 if (Magic == "\xFE\xED\xFA\xCE")
4584 return MachOObjectFile::create(Buffer, false, false,
4585 UniversalCputype, UniversalIndex);
4586 if (Magic == "\xCE\xFA\xED\xFE")
4587 return MachOObjectFile::create(Buffer, true, false,
4588 UniversalCputype, UniversalIndex);
4589 if (Magic == "\xFE\xED\xFA\xCF")
4590 return MachOObjectFile::create(Buffer, false, true,
4591 UniversalCputype, UniversalIndex);
4592 if (Magic == "\xCF\xFA\xED\xFE")
4593 return MachOObjectFile::create(Buffer, true, true,
4594 UniversalCputype, UniversalIndex);
4595 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
4596 object_error::invalid_file_type);
4597}
4598
4599StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
4600 return StringSwitch<StringRef>(Name)
4601 .Case("debug_str_offs", "debug_str_offsets")
4602 .Default(Name);
4603}

/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/STLExtras.h

1//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- 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 contains some templates that are useful if you are working with the
11// STL at all.
12//
13// No library is required when using these functions.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_ADT_STLEXTRAS_H
18#define LLVM_ADT_STLEXTRAS_H
19
20#include "llvm/ADT/Optional.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/iterator.h"
23#include "llvm/ADT/iterator_range.h"
24#include "llvm/Support/ErrorHandling.h"
25#include <algorithm>
26#include <cassert>
27#include <cstddef>
28#include <cstdint>
29#include <cstdlib>
30#include <functional>
31#include <initializer_list>
32#include <iterator>
33#include <limits>
34#include <memory>
35#include <tuple>
36#include <type_traits>
37#include <utility>
38
39#ifdef EXPENSIVE_CHECKS
40#include <random> // for std::mt19937
41#endif
42
43namespace llvm {
44
45// Only used by compiler if both template types are the same. Useful when
46// using SFINAE to test for the existence of member functions.
47template <typename T, T> struct SameType;
48
49namespace detail {
50
51template <typename RangeT>
52using IterOfRange = decltype(std::begin(std::declval<RangeT &>()));
53
54template <typename RangeT>
55using ValueOfRange = typename std::remove_reference<decltype(
56 *std::begin(std::declval<RangeT &>()))>::type;
57
58} // end namespace detail
59
60//===----------------------------------------------------------------------===//
61// Extra additions to <functional>
62//===----------------------------------------------------------------------===//
63
64template <class Ty> struct identity {
65 using argument_type = Ty;
66
67 Ty &operator()(Ty &self) const {
68 return self;
69 }
70 const Ty &operator()(const Ty &self) const {
71 return self;
72 }
73};
74
75template <class Ty> struct less_ptr {
76 bool operator()(const Ty* left, const Ty* right) const {
77 return *left < *right;
78 }
79};
80
81template <class Ty> struct greater_ptr {
82 bool operator()(const Ty* left, const Ty* right) const {
83 return *right < *left;
84 }
85};
86
87/// An efficient, type-erasing, non-owning reference to a callable. This is
88/// intended for use as the type of a function parameter that is not used
89/// after the function in question returns.
90///
91/// This class does not own the callable, so it is not in general safe to store
92/// a function_ref.
93template<typename Fn> class function_ref;
94
95template<typename Ret, typename ...Params>
96class function_ref<Ret(Params...)> {
97 Ret (*callback)(intptr_t callable, Params ...params) = nullptr;
98 intptr_t callable;
99
100 template<typename Callable>
101 static Ret callback_fn(intptr_t callable, Params ...params) {
102 return (*reinterpret_cast<Callable*>(callable))(
103 std::forward<Params>(params)...);
104 }
105
106public:
107 function_ref() = default;
108 function_ref(std::nullptr_t) {}
109
110 template <typename Callable>
111 function_ref(Callable &&callable,
112 typename std::enable_if<
113 !std::is_same<typename std::remove_reference<Callable>::type,
114 function_ref>::value>::type * = nullptr)
115 : callback(callback_fn<typename std::remove_reference<Callable>::type>),
116 callable(reinterpret_cast<intptr_t>(&callable)) {}
117
118 Ret operator()(Params ...params) const {
119 return callback(callable, std::forward<Params>(params)...);
120 }
121
122 operator bool() const { return callback; }
123};
124
125// deleter - Very very very simple method that is used to invoke operator
126// delete on something. It is used like this:
127//
128// for_each(V.begin(), B.end(), deleter<Interval>);
129template <class T>
130inline void deleter(T *Ptr) {
131 delete Ptr;
132}
133
134//===----------------------------------------------------------------------===//
135// Extra additions to <iterator>
136//===----------------------------------------------------------------------===//
137
138namespace adl_detail {
139
140using std::begin;
141
142template <typename ContainerTy>
143auto adl_begin(ContainerTy &&container)
144 -> decltype(begin(std::forward<ContainerTy>(container))) {
145 return begin(std::forward<ContainerTy>(container));
146}
147
148using std::end;
149
150template <typename ContainerTy>
151auto adl_end(ContainerTy &&container)
152 -> decltype(end(std::forward<ContainerTy>(container))) {
153 return end(std::forward<ContainerTy>(container));
154}
155
156using std::swap;
157
158template <typename T>
159void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(),
160 std::declval<T>()))) {
161 swap(std::forward<T>(lhs), std::forward<T>(rhs));
162}
163
164} // end namespace adl_detail
165
166template <typename ContainerTy>
167auto adl_begin(ContainerTy &&container)
168 -> decltype(adl_detail::adl_begin(std::forward<ContainerTy>(container))) {
169 return adl_detail::adl_begin(std::forward<ContainerTy>(container));
170}
171
172template <typename ContainerTy>
173auto adl_end(ContainerTy &&container)
174 -> decltype(adl_detail::adl_end(std::forward<ContainerTy>(container))) {
175 return adl_detail::adl_end(std::forward<ContainerTy>(container));
176}
177
178template <typename T>
179void adl_swap(T &&lhs, T &&rhs) noexcept(
180 noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) {
181 adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs));
182}
183
184// mapped_iterator - This is a simple iterator adapter that causes a function to
185// be applied whenever operator* is invoked on the iterator.
186
187template <typename ItTy, typename FuncTy,
188 typename FuncReturnTy =
189 decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
190class mapped_iterator
191 : public iterator_adaptor_base<
192 mapped_iterator<ItTy, FuncTy>, ItTy,
193 typename std::iterator_traits<ItTy>::iterator_category,
194 typename std::remove_reference<FuncReturnTy>::type> {
195public:
196 mapped_iterator(ItTy U, FuncTy F)
197 : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {}
198
199 ItTy getCurrent() { return this->I; }
200
201 FuncReturnTy operator*() { return F(*this->I); }
202
203private:
204 FuncTy F;
205};
206
207// map_iterator - Provide a convenient way to create mapped_iterators, just like
208// make_pair is useful for creating pairs...
209template <class ItTy, class FuncTy>
210inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) {
211 return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F));
212}
213
214/// Helper to determine if type T has a member called rbegin().
215template <typename Ty> class has_rbegin_impl {
216 using yes = char[1];
217 using no = char[2];
218
219 template <typename Inner>
220 static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr);
221
222 template <typename>
223 static no& test(...);
224
225public:
226 static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
227};
228
229/// Metafunction to determine if T& or T has a member called rbegin().
230template <typename Ty>
231struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> {
232};
233
234// Returns an iterator_range over the given container which iterates in reverse.
235// Note that the container must have rbegin()/rend() methods for this to work.
236template <typename ContainerTy>
237auto reverse(ContainerTy &&C,
238 typename std::enable_if<has_rbegin<ContainerTy>::value>::type * =
239 nullptr) -> decltype(make_range(C.rbegin(), C.rend())) {
240 return make_range(C.rbegin(), C.rend());
241}
242
243// Returns a std::reverse_iterator wrapped around the given iterator.
244template <typename IteratorTy>
245std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) {
246 return std::reverse_iterator<IteratorTy>(It);
247}
248
249// Returns an iterator_range over the given container which iterates in reverse.
250// Note that the container must have begin()/end() methods which return
251// bidirectional iterators for this to work.
252template <typename ContainerTy>
253auto reverse(
254 ContainerTy &&C,
255 typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr)
256 -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)),
257 llvm::make_reverse_iterator(std::begin(C)))) {
258 return make_range(llvm::make_reverse_iterator(std::end(C)),
259 llvm::make_reverse_iterator(std::begin(C)));
260}
261
262/// An iterator adaptor that filters the elements of given inner iterators.
263///
264/// The predicate parameter should be a callable object that accepts the wrapped
265/// iterator's reference type and returns a bool. When incrementing or
266/// decrementing the iterator, it will call the predicate on each element and
267/// skip any where it returns false.
268///
269/// \code
270/// int A[] = { 1, 2, 3, 4 };
271/// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; });
272/// // R contains { 1, 3 }.
273/// \endcode
274template <typename WrappedIteratorT, typename PredicateT>
275class filter_iterator
276 : public iterator_adaptor_base<
277 filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT,
278 typename std::common_type<
279 std::forward_iterator_tag,
280 typename std::iterator_traits<
281 WrappedIteratorT>::iterator_category>::type> {
282 using BaseT = iterator_adaptor_base<
283 filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT,
284 typename std::common_type<
285 std::forward_iterator_tag,
286 typename std::iterator_traits<WrappedIteratorT>::iterator_category>::
287 type>;
288
289 struct PayloadType {
290 WrappedIteratorT End;
291 PredicateT Pred;
292 };
293
294 Optional<PayloadType> Payload;
295
296 void findNextValid() {
297 assert(Payload && "Payload should be engaged when findNextValid is called")(static_cast <bool> (Payload && "Payload should be engaged when findNextValid is called"
) ? void (0) : __assert_fail ("Payload && \"Payload should be engaged when findNextValid is called\""
, "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/STLExtras.h"
, 297, __extension__ __PRETTY_FUNCTION__))
;
298 while (this->I != Payload->End && !Payload->Pred(*this->I))
299 BaseT::operator++();
300 }
301
302 // Construct the begin iterator. The begin iterator requires to know where end
303 // is, so that it can properly stop when it hits end.
304 filter_iterator(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred)
305 : BaseT(std::move(Begin)),
306 Payload(PayloadType{std::move(End), std::move(Pred)}) {
307 findNextValid();
308 }
309
310 // Construct the end iterator. It's not incrementable, so Payload doesn't
311 // have to be engaged.
312 filter_iterator(WrappedIteratorT End) : BaseT(End) {}
313
314public:
315 using BaseT::operator++;
316
317 filter_iterator &operator++() {
318 BaseT::operator++();
319 findNextValid();
320 return *this;
321 }
322
323 template <typename RT, typename PT>
324 friend iterator_range<filter_iterator<detail::IterOfRange<RT>, PT>>
325 make_filter_range(RT &&, PT);
326};
327
328/// Convenience function that takes a range of elements and a predicate,
329/// and return a new filter_iterator range.
330///
331/// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the
332/// lifetime of that temporary is not kept by the returned range object, and the
333/// temporary is going to be dropped on the floor after the make_iterator_range
334/// full expression that contains this function call.
335template <typename RangeT, typename PredicateT>
336iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>>
337make_filter_range(RangeT &&Range, PredicateT Pred) {
338 using FilterIteratorT =
339 filter_iterator<detail::IterOfRange<RangeT>, PredicateT>;
340 return make_range(FilterIteratorT(std::begin(std::forward<RangeT>(Range)),
341 std::end(std::forward<RangeT>(Range)),
342 std::move(Pred)),
343 FilterIteratorT(std::end(std::forward<RangeT>(Range))));
344}
345
346// forward declarations required by zip_shortest/zip_first
347template <typename R, typename UnaryPredicate>
348bool all_of(R &&range, UnaryPredicate P);
349
350template <size_t... I> struct index_sequence;
351
352template <class... Ts> struct index_sequence_for;
353
354namespace detail {
355
356using std::declval;
357
358// We have to alias this since inlining the actual type at the usage site
359// in the parameter list of iterator_facade_base<> below ICEs MSVC 2017.
360template<typename... Iters> struct ZipTupleType {
361 using type = std::tuple<decltype(*declval<Iters>())...>;
362};
363
364template <typename ZipType, typename... Iters>
365using zip_traits = iterator_facade_base<
366 ZipType, typename std::common_type<std::bidirectional_iterator_tag,
367 typename std::iterator_traits<
368 Iters>::iterator_category...>::type,
369 // ^ TODO: Implement random access methods.
370 typename ZipTupleType<Iters...>::type,
371 typename std::iterator_traits<typename std::tuple_element<
372 0, std::tuple<Iters...>>::type>::difference_type,
373 // ^ FIXME: This follows boost::make_zip_iterator's assumption that all
374 // inner iterators have the same difference_type. It would fail if, for
375 // instance, the second field's difference_type were non-numeric while the
376 // first is.
377 typename ZipTupleType<Iters...>::type *,
378 typename ZipTupleType<Iters...>::type>;
379
380template <typename ZipType, typename... Iters>
381struct zip_common : public zip_traits<ZipType, Iters...> {
382 using Base = zip_traits<ZipType, Iters...>;
383 using value_type = typename Base::value_type;
384
385 std::tuple<Iters...> iterators;
386
387protected:
388 template <size_t... Ns> value_type deref(index_sequence<Ns...>) const {
389 return value_type(*std::get<Ns>(iterators)...);
390 }
391
392 template <size_t... Ns>
393 decltype(iterators) tup_inc(index_sequence<Ns...>) const {
394 return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...);
395 }
396
397 template <size_t... Ns>
398 decltype(iterators) tup_dec(index_sequence<Ns...>) const {
399 return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...);
400 }
401
402public:
403 zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
404
405 value_type operator*() { return deref(index_sequence_for<Iters...>{}); }
406
407 const value_type operator*() const {
408 return deref(index_sequence_for<Iters...>{});
409 }
410
411 ZipType &operator++() {
412 iterators = tup_inc(index_sequence_for<Iters...>{});
413 return *reinterpret_cast<ZipType *>(this);
414 }
415
416 ZipType &operator--() {
417 static_assert(Base::IsBidirectional,
418 "All inner iterators must be at least bidirectional.");
419 iterators = tup_dec(index_sequence_for<Iters...>{});
420 return *reinterpret_cast<ZipType *>(this);
421 }
422};
423
424template <typename... Iters>
425struct zip_first : public zip_common<zip_first<Iters...>, Iters...> {
426 using Base = zip_common<zip_first<Iters...>, Iters...>;
427
428 bool operator==(const zip_first<Iters...> &other) const {
429 return std::get<0>(this->iterators) == std::get<0>(other.iterators);
430 }
431
432 zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
433};
434
435template <typename... Iters>
436class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> {
437 template <size_t... Ns>
438 bool test(const zip_shortest<Iters...> &other, index_sequence<Ns...>) const {
439 return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
440 std::get<Ns>(other.iterators)...},
441 identity<bool>{});
442 }
443
444public:
445 using Base = zip_common<zip_shortest<Iters...>, Iters...>;
446
447 zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
448
449 bool operator==(const zip_shortest<Iters...> &other) const {
450 return !test(other, index_sequence_for<Iters...>{});
451 }
452};
453
454template <template <typename...> class ItType, typename... Args> class zippy {
455public:
456 using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>;
457 using iterator_category = typename iterator::iterator_category;
458 using value_type = typename iterator::value_type;
459 using difference_type = typename iterator::difference_type;
460 using pointer = typename iterator::pointer;
461 using reference = typename iterator::reference;
462
463private:
464 std::tuple<Args...> ts;
465
466 template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const {
467 return iterator(std::begin(std::get<Ns>(ts))...);
468 }
469 template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const {
470 return iterator(std::end(std::get<Ns>(ts))...);
471 }
472
473public:
474 zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
475
476 iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); }
477 iterator end() const { return end_impl(index_sequence_for<Args...>{}); }
478};
479
480} // end namespace detail
481
482/// zip iterator for two or more iteratable types.
483template <typename T, typename U, typename... Args>
484detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u,
485 Args &&... args) {
486 return detail::zippy<detail::zip_shortest, T, U, Args...>(
487 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
488}
489
490/// zip iterator that, for the sake of efficiency, assumes the first iteratee to
491/// be the shortest.
492template <typename T, typename U, typename... Args>
493detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u,
494 Args &&... args) {
495 return detail::zippy<detail::zip_first, T, U, Args...>(
496 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
497}
498
499/// Iterator wrapper that concatenates sequences together.
500///
501/// This can concatenate different iterators, even with different types, into
502/// a single iterator provided the value types of all the concatenated
503/// iterators expose `reference` and `pointer` types that can be converted to
504/// `ValueT &` and `ValueT *` respectively. It doesn't support more
505/// interesting/customized pointer or reference types.
506///
507/// Currently this only supports forward or higher iterator categories as
508/// inputs and always exposes a forward iterator interface.
509template <typename ValueT, typename... IterTs>
510class concat_iterator
511 : public iterator_facade_base<concat_iterator<ValueT, IterTs...>,
512 std::forward_iterator_tag, ValueT> {
513 using BaseT = typename concat_iterator::iterator_facade_base;
514
515 /// We store both the current and end iterators for each concatenated
516 /// sequence in a tuple of pairs.
517 ///
518 /// Note that something like iterator_range seems nice at first here, but the
519 /// range properties are of little benefit and end up getting in the way
520 /// because we need to do mutation on the current iterators.
521 std::tuple<std::pair<IterTs, IterTs>...> IterPairs;
522
523 /// Attempts to increment a specific iterator.
524 ///
525 /// Returns true if it was able to increment the iterator. Returns false if
526 /// the iterator is already at the end iterator.
527 template <size_t Index> bool incrementHelper() {
528 auto &IterPair = std::get<Index>(IterPairs);
529 if (IterPair.first == IterPair.second)
530 return false;
531
532 ++IterPair.first;
533 return true;
534 }
535
536 /// Increments the first non-end iterator.
537 ///
538 /// It is an error to call this with all iterators at the end.
539 template <size_t... Ns> void increment(index_sequence<Ns...>) {
540 // Build a sequence of functions to increment each iterator if possible.
541 bool (concat_iterator::*IncrementHelperFns[])() = {
542 &concat_iterator::incrementHelper<Ns>...};
543
544 // Loop over them, and stop as soon as we succeed at incrementing one.
545 for (auto &IncrementHelperFn : IncrementHelperFns)
546 if ((this->*IncrementHelperFn)())
547 return;
548
549 llvm_unreachable("Attempted to increment an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to increment an end concat iterator!"
, "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/STLExtras.h"
, 549)
;
550 }
551
552 /// Returns null if the specified iterator is at the end. Otherwise,
553 /// dereferences the iterator and returns the address of the resulting
554 /// reference.
555 template <size_t Index> ValueT *getHelper() const {
556 auto &IterPair = std::get<Index>(IterPairs);
557 if (IterPair.first == IterPair.second)
558 return nullptr;
559
560 return &*IterPair.first;
561 }
562
563 /// Finds the first non-end iterator, dereferences, and returns the resulting
564 /// reference.
565 ///
566 /// It is an error to call this with all iterators at the end.
567 template <size_t... Ns> ValueT &get(index_sequence<Ns...>) const {
568 // Build a sequence of functions to get from iterator if possible.
569 ValueT *(concat_iterator::*GetHelperFns[])() const = {
570 &concat_iterator::getHelper<Ns>...};
571
572 // Loop over them, and return the first result we find.
573 for (auto &GetHelperFn : GetHelperFns)
574 if (ValueT *P = (this->*GetHelperFn)())
575 return *P;
576
577 llvm_unreachable("Attempted to get a pointer from an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to get a pointer from an end concat iterator!"
, "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/STLExtras.h"
, 577)
;
578 }
579
580public:
581 /// Constructs an iterator from a squence of ranges.
582 ///
583 /// We need the full range to know how to switch between each of the
584 /// iterators.
585 template <typename... RangeTs>
586 explicit concat_iterator(RangeTs &&... Ranges)
587 : IterPairs({std::begin(Ranges), std::end(Ranges)}...) {}
588
589 using BaseT::operator++;
590
591 concat_iterator &operator++() {
592 increment(index_sequence_for<IterTs...>());
593 return *this;
594 }
595
596 ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); }
597
598 bool operator==(const concat_iterator &RHS) const {
599 return IterPairs == RHS.IterPairs;
600 }
601};
602
603namespace detail {
604
605/// Helper to store a sequence of ranges being concatenated and access them.
606///
607/// This is designed to facilitate providing actual storage when temporaries
608/// are passed into the constructor such that we can use it as part of range
609/// based for loops.
610template <typename ValueT, typename... RangeTs> class concat_range {
611public:
612 using iterator =
613 concat_iterator<ValueT,
614 decltype(std::begin(std::declval<RangeTs &>()))...>;
615
616private:
617 std::tuple<RangeTs...> Ranges;
618
619 template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) {
620 return iterator(std::get<Ns>(Ranges)...);
621 }
622 template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) {
623 return iterator(make_range(std::end(std::get<Ns>(Ranges)),
624 std::end(std::get<Ns>(Ranges)))...);
625 }
626
627public:
628 concat_range(RangeTs &&... Ranges)
629 : Ranges(std::forward<RangeTs>(Ranges)...) {}
630
631 iterator begin() { return begin_impl(index_sequence_for<RangeTs...>{}); }
632 iterator end() { return end_impl(index_sequence_for<RangeTs...>{}); }
633};
634
635} // end namespace detail
636
637/// Concatenated range across two or more ranges.
638///
639/// The desired value type must be explicitly specified.
640template <typename ValueT, typename... RangeTs>
641detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) {
642 static_assert(sizeof...(RangeTs) > 1,
643 "Need more than one range to concatenate!");
644 return detail::concat_range<ValueT, RangeTs...>(
645 std::forward<RangeTs>(Ranges)...);
646}
647
648//===----------------------------------------------------------------------===//
649// Extra additions to <utility>
650//===----------------------------------------------------------------------===//
651
652/// \brief Function object to check whether the first component of a std::pair
653/// compares less than the first component of another std::pair.
654struct less_first {
655 template <typename T> bool operator()(const T &lhs, const T &rhs) const {
656 return lhs.first < rhs.first;
657 }
658};
659
660/// \brief Function object to check whether the second component of a std::pair
661/// compares less than the second component of another std::pair.
662struct less_second {
663 template <typename T> bool operator()(const T &lhs, const T &rhs) const {
664 return lhs.second < rhs.second;
665 }
666};
667
668// A subset of N3658. More stuff can be added as-needed.
669
670/// \brief Represents a compile-time sequence of integers.
671template <class T, T... I> struct integer_sequence {
672 using value_type = T;
673
674 static constexpr size_t size() { return sizeof...(I); }
675};
676
677/// \brief Alias for the common case of a sequence of size_ts.
678template <size_t... I>
679struct index_sequence : integer_sequence<std::size_t, I...> {};
680
681template <std::size_t N, std::size_t... I>
682struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {};
683template <std::size_t... I>
684struct build_index_impl<0, I...> : index_sequence<I...> {};
685
686/// \brief Creates a compile-time integer sequence for a parameter pack.
687template <class... Ts>
688struct index_sequence_for : build_index_impl<sizeof...(Ts)> {};
689
690/// Utility type to build an inheritance chain that makes it easy to rank
691/// overload candidates.
692template <int N> struct rank : rank<N - 1> {};
693template <> struct rank<0> {};
694
695/// \brief traits class for checking whether type T is one of any of the given
696/// types in the variadic list.
697template <typename T, typename... Ts> struct is_one_of {
698 static const bool value = false;
699};
700
701template <typename T, typename U, typename... Ts>
702struct is_one_of<T, U, Ts...> {
703 static const bool value =
704 std::is_same<T, U>::value || is_one_of<T, Ts...>::value;
705};
706
707/// \brief traits class for checking whether type T is a base class for all
708/// the given types in the variadic list.
709template <typename T, typename... Ts> struct are_base_of {
710 static const bool value = true;
711};
712
713template <typename T, typename U, typename... Ts>
714struct are_base_of<T, U, Ts...> {
715 static const bool value =
716 std::is_base_of<T, U>::value && are_base_of<T, Ts...>::value;
717};
718
719//===----------------------------------------------------------------------===//
720// Extra additions for arrays
721//===----------------------------------------------------------------------===//
722
723/// Find the length of an array.
724template <class T, std::size_t N>
725constexpr inline size_t array_lengthof(T (&)[N]) {
726 return N;
727}
728
729/// Adapt std::less<T> for array_pod_sort.
730template<typename T>
731inline int array_pod_sort_comparator(const void *P1, const void *P2) {
732 if (std::less<T>()(*reinterpret_cast<const T*>(P1),
733 *reinterpret_cast<const T*>(P2)))
734 return -1;
735 if (std::less<T>()(*reinterpret_cast<const T*>(P2),
736 *reinterpret_cast<const T*>(P1)))
737 return 1;
738 return 0;
739}
740
741/// get_array_pod_sort_comparator - This is an internal helper function used to
742/// get type deduction of T right.
743template<typename T>
744inline int (*get_array_pod_sort_comparator(const T &))
745 (const void*, const void*) {
746 return array_pod_sort_comparator<T>;
747}
748
749/// array_pod_sort - This sorts an array with the specified start and end
750/// extent. This is just like std::sort, except that it calls qsort instead of
751/// using an inlined template. qsort is slightly slower than std::sort, but
752/// most sorts are not performance critical in LLVM and std::sort has to be
753/// template instantiated for each type, leading to significant measured code
754/// bloat. This function should generally be used instead of std::sort where
755/// possible.
756///
757/// This function assumes that you have simple POD-like types that can be
758/// compared with std::less and can be moved with memcpy. If this isn't true,
759/// you should use std::sort.
760///
761/// NOTE: If qsort_r were portable, we could allow a custom comparator and
762/// default to std::less.
763template<class IteratorTy>
764inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
765 // Don't inefficiently call qsort with one element or trigger undefined
766 // behavior with an empty sequence.
767 auto NElts = End - Start;
768 if (NElts <= 1) return;
769#ifdef EXPENSIVE_CHECKS
770 std::mt19937 Generator(std::random_device{}());
771 std::shuffle(Start, End, Generator);
772#endif
773 qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
774}
775
776template <class IteratorTy>
777inline void array_pod_sort(
778 IteratorTy Start, IteratorTy End,
779 int (*Compare)(
780 const typename std::iterator_traits<IteratorTy>::value_type *,
781 const typename std::iterator_traits<IteratorTy>::value_type *)) {
782 // Don't inefficiently call qsort with one element or trigger undefined
783 // behavior with an empty sequence.
784 auto NElts = End - Start;
785 if (NElts <= 1) return;
786#ifdef EXPENSIVE_CHECKS
787 std::mt19937 Generator(std::random_device{}());
788 std::shuffle(Start, End, Generator);
789#endif
790 qsort(&*Start, NElts, sizeof(*Start),
791 reinterpret_cast<int (*)(const void *, const void *)>(Compare));
792}
793
794// Provide wrappers to std::sort which shuffle the elements before sorting
795// to help uncover non-deterministic behavior (PR35135).
796template <typename IteratorTy>
797inline void sort(IteratorTy Start, IteratorTy End) {
798#ifdef EXPENSIVE_CHECKS
799 std::mt19937 Generator(std::random_device{}());
800 std::shuffle(Start, End, Generator);
801#endif
802 std::sort(Start, End);
803}
804
805template <typename IteratorTy, typename Compare>
806inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
807#ifdef EXPENSIVE_CHECKS
808 std::mt19937 Generator(std::random_device{}());
809 std::shuffle(Start, End, Generator);
810#endif
811 std::sort(Start, End, Comp);
812}
813
814//===----------------------------------------------------------------------===//
815// Extra additions to <algorithm>
816//===----------------------------------------------------------------------===//
817
818/// For a container of pointers, deletes the pointers and then clears the
819/// container.
820template<typename Container>
821void DeleteContainerPointers(Container &C) {
822 for (auto V : C)
823 delete V;
824 C.clear();
825}
826
827/// In a container of pairs (usually a map) whose second element is a pointer,
828/// deletes the second elements and then clears the container.
829template<typename Container>
830void DeleteContainerSeconds(Container &C) {
831 for (auto &V : C)
832 delete V.second;
833 C.clear();
834}
835
836/// Provide wrappers to std::for_each which take ranges instead of having to
837/// pass begin/end explicitly.
838template <typename R, typename UnaryPredicate>
839UnaryPredicate for_each(R &&Range, UnaryPredicate P) {
840 return std::for_each(adl_begin(Range), adl_end(Range), P);
841}
842
843/// Provide wrappers to std::all_of which take ranges instead of having to pass
844/// begin/end explicitly.
845template <typename R, typename UnaryPredicate>
846bool all_of(R &&Range, UnaryPredicate P) {
847 return std::all_of(adl_begin(Range), adl_end(Range), P);
848}
849
850/// Provide wrappers to std::any_of which take ranges instead of having to pass
851/// begin/end explicitly.
852template <typename R, typename UnaryPredicate>
853bool any_of(R &&Range, UnaryPredicate P) {
854 return std::any_of(adl_begin(Range), adl_end(Range), P);
855}
856
857/// Provide wrappers to std::none_of which take ranges instead of having to pass
858/// begin/end explicitly.
859template <typename R, typename UnaryPredicate>
860bool none_of(R &&Range, UnaryPredicate P) {
861 return std::none_of(adl_begin(Range), adl_end(Range), P);
862}
863
864/// Provide wrappers to std::find which take ranges instead of having to pass
865/// begin/end explicitly.
866template <typename R, typename T>
867auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) {
868 return std::find(adl_begin(Range), adl_end(Range), Val);
869}
870
871/// Provide wrappers to std::find_if which take ranges instead of having to pass
872/// begin/end explicitly.
873template <typename R, typename UnaryPredicate>
874auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
875 return std::find_if(adl_begin(Range), adl_end(Range), P);
876}
877
878template <typename R, typename UnaryPredicate>
879auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
880 return std::find_if_not(adl_begin(Range), adl_end(Range), P);
881}
882
883/// Provide wrappers to std::remove_if which take ranges instead of having to
884/// pass begin/end explicitly.
885template <typename R, typename UnaryPredicate>
886auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
887 return std::remove_if(adl_begin(Range), adl_end(Range), P);
888}
889
890/// Provide wrappers to std::copy_if which take ranges instead of having to
891/// pass begin/end explicitly.
892template <typename R, typename OutputIt, typename UnaryPredicate>
893OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) {
894 return std::copy_if(adl_begin(Range), adl_end(Range), Out, P);
895}
896
897template <typename R, typename OutputIt>
898OutputIt copy(R &&Range, OutputIt Out) {
899 return std::copy(adl_begin(Range), adl_end(Range), Out);
900}
901
902/// Wrapper function around std::find to detect if an element exists
903/// in a container.
904template <typename R, typename E>
905bool is_contained(R &&Range, const E &Element) {
906 return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range);
907}
908
909/// Wrapper function around std::count to count the number of times an element
910/// \p Element occurs in the given range \p Range.
911template <typename R, typename E>
912auto count(R &&Range, const E &Element) ->
913 typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type {
914 return std::count(adl_begin(Range), adl_end(Range), Element);
915}
916
917/// Wrapper function around std::count_if to count the number of times an
918/// element satisfying a given predicate occurs in a range.
919template <typename R, typename UnaryPredicate>
920auto count_if(R &&Range, UnaryPredicate P) ->
921 typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type {
922 return std::count_if(adl_begin(Range), adl_end(Range), P);
923}
924
925/// Wrapper function around std::transform to apply a function to a range and
926/// store the result elsewhere.
927template <typename R, typename OutputIt, typename UnaryPredicate>
928OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) {
929 return std::transform(adl_begin(Range), adl_end(Range), d_first, P);
930}
931
932/// Provide wrappers to std::partition which take ranges instead of having to
933/// pass begin/end explicitly.
934template <typename R, typename UnaryPredicate>
935auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
936 return std::partition(adl_begin(Range), adl_end(Range), P);
937}
938
939/// Provide wrappers to std::lower_bound which take ranges instead of having to
940/// pass begin/end explicitly.
941template <typename R, typename ForwardIt>
942auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) {
943 return std::lower_bound(adl_begin(Range), adl_end(Range), I);
944}
945
946/// \brief Given a range of type R, iterate the entire range and return a
947/// SmallVector with elements of the vector. This is useful, for example,
948/// when you want to iterate a range and then sort the results.
949template <unsigned Size, typename R>
950SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size>
951to_vector(R &&Range) {
952 return {adl_begin(Range), adl_end(Range)};
953}
954
955/// Provide a container algorithm similar to C++ Library Fundamentals v2's
956/// `erase_if` which is equivalent to:
957///
958/// C.erase(remove_if(C, pred), C.end());
959///
960/// This version works for any container with an erase method call accepting
961/// two iterators.
962template <typename Container, typename UnaryPredicate>
963void erase_if(Container &C, UnaryPredicate P) {
964 C.erase(remove_if(C, P), C.end());
965}
966
967//===----------------------------------------------------------------------===//
968// Extra additions to <memory>
969//===----------------------------------------------------------------------===//
970
971// Implement make_unique according to N3656.
972
973/// \brief Constructs a `new T()` with the given args and returns a
974/// `unique_ptr<T>` which owns the object.
975///
976/// Example:
977///
978/// auto p = make_unique<int>();
979/// auto p = make_unique<std::tuple<int, int>>(0, 1);
980template <class T, class... Args>
981typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
982make_unique(Args &&... args) {
983 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
4
Calling constructor for 'BindRebaseSegInfo'
984}
985
986/// \brief Constructs a `new T[n]` with the given args and returns a
987/// `unique_ptr<T[]>` which owns the object.
988///
989/// \param n size of the new array.
990///
991/// Example:
992///
993/// auto p = make_unique<int[]>(2); // value-initializes the array with 0's.
994template <class T>
995typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0,
996 std::unique_ptr<T>>::type
997make_unique(size_t n) {
998 return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
999}
1000
1001/// This function isn't used and is only here to provide better compile errors.
1002template <class T, class... Args>
1003typename std::enable_if<std::extent<T>::value != 0>::type
1004make_unique(Args &&...) = delete;
1005
1006struct FreeDeleter {
1007 void operator()(void* v) {
1008 ::free(v);
1009 }
1010};
1011
1012template<typename First, typename Second>
1013struct pair_hash {
1014 size_t operator()(const std::pair<First, Second> &P) const {
1015 return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second);
1016 }
1017};
1018
1019/// A functor like C++14's std::less<void> in its absence.
1020struct less {
1021 template <typename A, typename B> bool operator()(A &&a, B &&b) const {
1022 return std::forward<A>(a) < std::forward<B>(b);
1023 }
1024};
1025
1026/// A functor like C++14's std::equal<void> in its absence.
1027struct equal {
1028 template <typename A, typename B> bool operator()(A &&a, B &&b) const {
1029 return std::forward<A>(a) == std::forward<B>(b);
1030 }
1031};
1032
1033/// Binary functor that adapts to any other binary functor after dereferencing
1034/// operands.
1035template <typename T> struct deref {
1036 T func;
1037
1038 // Could be further improved to cope with non-derivable functors and
1039 // non-binary functors (should be a variadic template member function
1040 // operator()).
1041 template <typename A, typename B>
1042 auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) {
1043 assert(lhs)(static_cast <bool> (lhs) ? void (0) : __assert_fail ("lhs"
, "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/STLExtras.h"
, 1043, __extension__ __PRETTY_FUNCTION__))
;
1044 assert(rhs)(static_cast <bool> (rhs) ? void (0) : __assert_fail ("rhs"
, "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/STLExtras.h"
, 1044, __extension__ __PRETTY_FUNCTION__))
;
1045 return func(*lhs, *rhs);
1046 }
1047};
1048
1049namespace detail {
1050
1051template <typename R> class enumerator_iter;
1052
1053template <typename R> struct result_pair {
1054 friend class enumerator_iter<R>;
1055
1056 result_pair() = default;
1057 result_pair(std::size_t Index, IterOfRange<R> Iter)
1058 : Index(Index), Iter(Iter) {}
1059
1060 result_pair<R> &operator=(const result_pair<R> &Other) {
1061 Index = Other.Index;
1062 Iter = Other.Iter;
1063 return *this;
1064 }
1065
1066 std::size_t index() const { return Index; }
1067 const ValueOfRange<R> &value() const { return *Iter; }
1068 ValueOfRange<R> &value() { return *Iter; }
1069
1070private:
1071 std::size_t Index = std::numeric_limits<std::size_t>::max();
1072 IterOfRange<R> Iter;
1073};
1074
1075template <typename R>
1076class enumerator_iter
1077 : public iterator_facade_base<
1078 enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>,
1079 typename std::iterator_traits<IterOfRange<R>>::difference_type,
1080 typename std::iterator_traits<IterOfRange<R>>::pointer,
1081 typename std::iterator_traits<IterOfRange<R>>::reference> {
1082 using result_type = result_pair<R>;
1083
1084public:
1085 explicit enumerator_iter(IterOfRange<R> EndIter)
1086 : Result(std::numeric_limits<size_t>::max(), EndIter) {}
1087
1088 enumerator_iter(std::size_t Index, IterOfRange<R> Iter)
1089 : Result(Index, Iter) {}
1090
1091 result_type &operator*() { return Result; }
1092 const result_type &operator*() const { return Result; }
1093
1094 enumerator_iter<R> &operator++() {
1095 assert(Result.Index != std::numeric_limits<size_t>::max())(static_cast <bool> (Result.Index != std::numeric_limits
<size_t>::max()) ? void (0) : __assert_fail ("Result.Index != std::numeric_limits<size_t>::max()"
, "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/STLExtras.h"
, 1095, __extension__ __PRETTY_FUNCTION__))
;
1096 ++Result.Iter;
1097 ++Result.Index;
1098 return *this;
1099 }
1100
1101 bool operator==(const enumerator_iter<R> &RHS) const {
1102 // Don't compare indices here, only iterators. It's possible for an end
1103 // iterator to have different indices depending on whether it was created
1104 // by calling std::end() versus incrementing a valid iterator.
1105 return Result.Iter == RHS.Result.Iter;
1106 }
1107
1108 enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) {
1109 Result = Other.Result;
1110 return *this;
1111 }
1112
1113private:
1114 result_type Result;
1115};
1116
1117template <typename R> class enumerator {
1118public:
1119 explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {}
1120
1121 enumerator_iter<R> begin() {
1122 return enumerator_iter<R>(0, std::begin(TheRange));
1123 }
1124
1125 enumerator_iter<R> end() {
1126 return enumerator_iter<R>(std::end(TheRange));