Bug Summary

File:lib/Object/MachOObjectFile.cpp
Warning:line 4016, 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-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 -analyzer-config-compatibility-mode=true -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-9/lib/clang/9.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/lib/Object -I /build/llvm-toolchain-snapshot-9~svn362543/lib/Object -I /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/include -I /build/llvm-toolchain-snapshot-9~svn362543/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/9.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-9/lib/clang/9.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-9~svn362543/build-llvm/lib/Object -fdebug-prefix-map=/build/llvm-toolchain-snapshot-9~svn362543=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2019-06-05-060531-1271-1 -x c++ /build/llvm-toolchain-snapshot-9~svn362543/lib/Object/MachOObjectFile.cpp -faddrsig

/build/llvm-toolchain-snapshot-9~svn362543/lib/Object/MachOObjectFile.cpp

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

/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/STLExtras.h

1//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains some templates that are useful if you are working with the
10// STL at all.
11//
12// No library is required when using these functions.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_ADT_STLEXTRAS_H
17#define LLVM_ADT_STLEXTRAS_H
18
19#include "llvm/ADT/Optional.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/iterator.h"
22#include "llvm/ADT/iterator_range.h"
23#include "llvm/Config/abi-breaking.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 <type_traits>
62//===----------------------------------------------------------------------===//
63
64template <typename T>
65struct negation : std::integral_constant<bool, !bool(T::value)> {};
66
67template <typename...> struct conjunction : std::true_type {};
68template <typename B1> struct conjunction<B1> : B1 {};
69template <typename B1, typename... Bn>
70struct conjunction<B1, Bn...>
71 : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
72
73template <typename T> struct make_const_ptr {
74 using type =
75 typename std::add_pointer<typename std::add_const<T>::type>::type;
76};
77
78template <typename T> struct make_const_ref {
79 using type = typename std::add_lvalue_reference<
80 typename std::add_const<T>::type>::type;
81};
82
83//===----------------------------------------------------------------------===//
84// Extra additions to <functional>
85//===----------------------------------------------------------------------===//
86
87template <class Ty> struct identity {
88 using argument_type = Ty;
89
90 Ty &operator()(Ty &self) const {
91 return self;
92 }
93 const Ty &operator()(const Ty &self) const {
94 return self;
95 }
96};
97
98template <class Ty> struct less_ptr {
99 bool operator()(const Ty* left, const Ty* right) const {
100 return *left < *right;
101 }
102};
103
104template <class Ty> struct greater_ptr {
105 bool operator()(const Ty* left, const Ty* right) const {
106 return *right < *left;
107 }
108};
109
110/// An efficient, type-erasing, non-owning reference to a callable. This is
111/// intended for use as the type of a function parameter that is not used
112/// after the function in question returns.
113///
114/// This class does not own the callable, so it is not in general safe to store
115/// a function_ref.
116template<typename Fn> class function_ref;
117
118template<typename Ret, typename ...Params>
119class function_ref<Ret(Params...)> {
120 Ret (*callback)(intptr_t callable, Params ...params) = nullptr;
121 intptr_t callable;
122
123 template<typename Callable>
124 static Ret callback_fn(intptr_t callable, Params ...params) {
125 return (*reinterpret_cast<Callable*>(callable))(
126 std::forward<Params>(params)...);
127 }
128
129public:
130 function_ref() = default;
131 function_ref(std::nullptr_t) {}
132
133 template <typename Callable>
134 function_ref(Callable &&callable,
135 typename std::enable_if<
136 !std::is_same<typename std::remove_reference<Callable>::type,
137 function_ref>::value>::type * = nullptr)
138 : callback(callback_fn<typename std::remove_reference<Callable>::type>),
139 callable(reinterpret_cast<intptr_t>(&callable)) {}
140
141 Ret operator()(Params ...params) const {
142 return callback(callable, std::forward<Params>(params)...);
143 }
144
145 operator bool() const { return callback; }
146};
147
148// deleter - Very very very simple method that is used to invoke operator
149// delete on something. It is used like this:
150//
151// for_each(V.begin(), B.end(), deleter<Interval>);
152template <class T>
153inline void deleter(T *Ptr) {
154 delete Ptr;
155}
156
157//===----------------------------------------------------------------------===//
158// Extra additions to <iterator>
159//===----------------------------------------------------------------------===//
160
161namespace adl_detail {
162
163using std::begin;
164
165template <typename ContainerTy>
166auto adl_begin(ContainerTy &&container)
167 -> decltype(begin(std::forward<ContainerTy>(container))) {
168 return begin(std::forward<ContainerTy>(container));
169}
170
171using std::end;
172
173template <typename ContainerTy>
174auto adl_end(ContainerTy &&container)
175 -> decltype(end(std::forward<ContainerTy>(container))) {
176 return end(std::forward<ContainerTy>(container));
177}
178
179using std::swap;
180
181template <typename T>
182void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(),
183 std::declval<T>()))) {
184 swap(std::forward<T>(lhs), std::forward<T>(rhs));
185}
186
187} // end namespace adl_detail
188
189template <typename ContainerTy>
190auto adl_begin(ContainerTy &&container)
191 -> decltype(adl_detail::adl_begin(std::forward<ContainerTy>(container))) {
192 return adl_detail::adl_begin(std::forward<ContainerTy>(container));
193}
194
195template <typename ContainerTy>
196auto adl_end(ContainerTy &&container)
197 -> decltype(adl_detail::adl_end(std::forward<ContainerTy>(container))) {
198 return adl_detail::adl_end(std::forward<ContainerTy>(container));
199}
200
201template <typename T>
202void adl_swap(T &&lhs, T &&rhs) noexcept(
203 noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) {
204 adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs));
205}
206
207/// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty.
208template <typename T>
209constexpr bool empty(const T &RangeOrContainer) {
210 return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer);
211}
212
213// mapped_iterator - This is a simple iterator adapter that causes a function to
214// be applied whenever operator* is invoked on the iterator.
215
216template <typename ItTy, typename FuncTy,
217 typename FuncReturnTy =
218 decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
219class mapped_iterator
220 : public iterator_adaptor_base<
221 mapped_iterator<ItTy, FuncTy>, ItTy,
222 typename std::iterator_traits<ItTy>::iterator_category,
223 typename std::remove_reference<FuncReturnTy>::type> {
224public:
225 mapped_iterator(ItTy U, FuncTy F)
226 : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {}
227
228 ItTy getCurrent() { return this->I; }
229
230 FuncReturnTy operator*() { return F(*this->I); }
231
232private:
233 FuncTy F;
234};
235
236// map_iterator - Provide a convenient way to create mapped_iterators, just like
237// make_pair is useful for creating pairs...
238template <class ItTy, class FuncTy>
239inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) {
240 return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F));
241}
242
243/// Helper to determine if type T has a member called rbegin().
244template <typename Ty> class has_rbegin_impl {
245 using yes = char[1];
246 using no = char[2];
247
248 template <typename Inner>
249 static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr);
250
251 template <typename>
252 static no& test(...);
253
254public:
255 static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
256};
257
258/// Metafunction to determine if T& or T has a member called rbegin().
259template <typename Ty>
260struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> {
261};
262
263// Returns an iterator_range over the given container which iterates in reverse.
264// Note that the container must have rbegin()/rend() methods for this to work.
265template <typename ContainerTy>
266auto reverse(ContainerTy &&C,
267 typename std::enable_if<has_rbegin<ContainerTy>::value>::type * =
268 nullptr) -> decltype(make_range(C.rbegin(), C.rend())) {
269 return make_range(C.rbegin(), C.rend());
270}
271
272// Returns a std::reverse_iterator wrapped around the given iterator.
273template <typename IteratorTy>
274std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) {
275 return std::reverse_iterator<IteratorTy>(It);
276}
277
278// Returns an iterator_range over the given container which iterates in reverse.
279// Note that the container must have begin()/end() methods which return
280// bidirectional iterators for this to work.
281template <typename ContainerTy>
282auto reverse(
283 ContainerTy &&C,
284 typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr)
285 -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)),
286 llvm::make_reverse_iterator(std::begin(C)))) {
287 return make_range(llvm::make_reverse_iterator(std::end(C)),
288 llvm::make_reverse_iterator(std::begin(C)));
289}
290
291/// An iterator adaptor that filters the elements of given inner iterators.
292///
293/// The predicate parameter should be a callable object that accepts the wrapped
294/// iterator's reference type and returns a bool. When incrementing or
295/// decrementing the iterator, it will call the predicate on each element and
296/// skip any where it returns false.
297///
298/// \code
299/// int A[] = { 1, 2, 3, 4 };
300/// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; });
301/// // R contains { 1, 3 }.
302/// \endcode
303///
304/// Note: filter_iterator_base implements support for forward iteration.
305/// filter_iterator_impl exists to provide support for bidirectional iteration,
306/// conditional on whether the wrapped iterator supports it.
307template <typename WrappedIteratorT, typename PredicateT, typename IterTag>
308class filter_iterator_base
309 : public iterator_adaptor_base<
310 filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
311 WrappedIteratorT,
312 typename std::common_type<
313 IterTag, typename std::iterator_traits<
314 WrappedIteratorT>::iterator_category>::type> {
315 using BaseT = iterator_adaptor_base<
316 filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
317 WrappedIteratorT,
318 typename std::common_type<
319 IterTag, typename std::iterator_traits<
320 WrappedIteratorT>::iterator_category>::type>;
321
322protected:
323 WrappedIteratorT End;
324 PredicateT Pred;
325
326 void findNextValid() {
327 while (this->I != End && !Pred(*this->I))
328 BaseT::operator++();
329 }
330
331 // Construct the iterator. The begin iterator needs to know where the end
332 // is, so that it can properly stop when it gets there. The end iterator only
333 // needs the predicate to support bidirectional iteration.
334 filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End,
335 PredicateT Pred)
336 : BaseT(Begin), End(End), Pred(Pred) {
337 findNextValid();
338 }
339
340public:
341 using BaseT::operator++;
342
343 filter_iterator_base &operator++() {
344 BaseT::operator++();
345 findNextValid();
346 return *this;
347 }
348};
349
350/// Specialization of filter_iterator_base for forward iteration only.
351template <typename WrappedIteratorT, typename PredicateT,
352 typename IterTag = std::forward_iterator_tag>
353class filter_iterator_impl
354 : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> {
355 using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>;
356
357public:
358 filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
359 PredicateT Pred)
360 : BaseT(Begin, End, Pred) {}
361};
362
363/// Specialization of filter_iterator_base for bidirectional iteration.
364template <typename WrappedIteratorT, typename PredicateT>
365class filter_iterator_impl<WrappedIteratorT, PredicateT,
366 std::bidirectional_iterator_tag>
367 : public filter_iterator_base<WrappedIteratorT, PredicateT,
368 std::bidirectional_iterator_tag> {
369 using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT,
370 std::bidirectional_iterator_tag>;
371 void findPrevValid() {
372 while (!this->Pred(*this->I))
373 BaseT::operator--();
374 }
375
376public:
377 using BaseT::operator--;
378
379 filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
380 PredicateT Pred)
381 : BaseT(Begin, End, Pred) {}
382
383 filter_iterator_impl &operator--() {
384 BaseT::operator--();
385 findPrevValid();
386 return *this;
387 }
388};
389
390namespace detail {
391
392template <bool is_bidirectional> struct fwd_or_bidi_tag_impl {
393 using type = std::forward_iterator_tag;
394};
395
396template <> struct fwd_or_bidi_tag_impl<true> {
397 using type = std::bidirectional_iterator_tag;
398};
399
400/// Helper which sets its type member to forward_iterator_tag if the category
401/// of \p IterT does not derive from bidirectional_iterator_tag, and to
402/// bidirectional_iterator_tag otherwise.
403template <typename IterT> struct fwd_or_bidi_tag {
404 using type = typename fwd_or_bidi_tag_impl<std::is_base_of<
405 std::bidirectional_iterator_tag,
406 typename std::iterator_traits<IterT>::iterator_category>::value>::type;
407};
408
409} // namespace detail
410
411/// Defines filter_iterator to a suitable specialization of
412/// filter_iterator_impl, based on the underlying iterator's category.
413template <typename WrappedIteratorT, typename PredicateT>
414using filter_iterator = filter_iterator_impl<
415 WrappedIteratorT, PredicateT,
416 typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>;
417
418/// Convenience function that takes a range of elements and a predicate,
419/// and return a new filter_iterator range.
420///
421/// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the
422/// lifetime of that temporary is not kept by the returned range object, and the
423/// temporary is going to be dropped on the floor after the make_iterator_range
424/// full expression that contains this function call.
425template <typename RangeT, typename PredicateT>
426iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>>
427make_filter_range(RangeT &&Range, PredicateT Pred) {
428 using FilterIteratorT =
429 filter_iterator<detail::IterOfRange<RangeT>, PredicateT>;
430 return make_range(
431 FilterIteratorT(std::begin(std::forward<RangeT>(Range)),
432 std::end(std::forward<RangeT>(Range)), Pred),
433 FilterIteratorT(std::end(std::forward<RangeT>(Range)),
434 std::end(std::forward<RangeT>(Range)), Pred));
435}
436
437/// A pseudo-iterator adaptor that is designed to implement "early increment"
438/// style loops.
439///
440/// This is *not a normal iterator* and should almost never be used directly. It
441/// is intended primarily to be used with range based for loops and some range
442/// algorithms.
443///
444/// The iterator isn't quite an `OutputIterator` or an `InputIterator` but
445/// somewhere between them. The constraints of these iterators are:
446///
447/// - On construction or after being incremented, it is comparable and
448/// dereferencable. It is *not* incrementable.
449/// - After being dereferenced, it is neither comparable nor dereferencable, it
450/// is only incrementable.
451///
452/// This means you can only dereference the iterator once, and you can only
453/// increment it once between dereferences.
454template <typename WrappedIteratorT>
455class early_inc_iterator_impl
456 : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
457 WrappedIteratorT, std::input_iterator_tag> {
458 using BaseT =
459 iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
460 WrappedIteratorT, std::input_iterator_tag>;
461
462 using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer;
463
464protected:
465#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
466 bool IsEarlyIncremented = false;
467#endif
468
469public:
470 early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {}
471
472 using BaseT::operator*;
473 typename BaseT::reference operator*() {
474#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
475 assert(!IsEarlyIncremented && "Cannot dereference twice!")((!IsEarlyIncremented && "Cannot dereference twice!")
? static_cast<void> (0) : __assert_fail ("!IsEarlyIncremented && \"Cannot dereference twice!\""
, "/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/STLExtras.h"
, 475, __PRETTY_FUNCTION__))
;
476 IsEarlyIncremented = true;
477#endif
478 return *(this->I)++;
479 }
480
481 using BaseT::operator++;
482 early_inc_iterator_impl &operator++() {
483#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
484 assert(IsEarlyIncremented && "Cannot increment before dereferencing!")((IsEarlyIncremented && "Cannot increment before dereferencing!"
) ? static_cast<void> (0) : __assert_fail ("IsEarlyIncremented && \"Cannot increment before dereferencing!\""
, "/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/STLExtras.h"
, 484, __PRETTY_FUNCTION__))
;
485 IsEarlyIncremented = false;
486#endif
487 return *this;
488 }
489
490 using BaseT::operator==;
491 bool operator==(const early_inc_iterator_impl &RHS) const {
492#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
493 assert(!IsEarlyIncremented && "Cannot compare after dereferencing!")((!IsEarlyIncremented && "Cannot compare after dereferencing!"
) ? static_cast<void> (0) : __assert_fail ("!IsEarlyIncremented && \"Cannot compare after dereferencing!\""
, "/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/STLExtras.h"
, 493, __PRETTY_FUNCTION__))
;
494#endif
495 return BaseT::operator==(RHS);
496 }
497};
498
499/// Make a range that does early increment to allow mutation of the underlying
500/// range without disrupting iteration.
501///
502/// The underlying iterator will be incremented immediately after it is
503/// dereferenced, allowing deletion of the current node or insertion of nodes to
504/// not disrupt iteration provided they do not invalidate the *next* iterator --
505/// the current iterator can be invalidated.
506///
507/// This requires a very exact pattern of use that is only really suitable to
508/// range based for loops and other range algorithms that explicitly guarantee
509/// to dereference exactly once each element, and to increment exactly once each
510/// element.
511template <typename RangeT>
512iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>>
513make_early_inc_range(RangeT &&Range) {
514 using EarlyIncIteratorT =
515 early_inc_iterator_impl<detail::IterOfRange<RangeT>>;
516 return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))),
517 EarlyIncIteratorT(std::end(std::forward<RangeT>(Range))));
518}
519
520// forward declarations required by zip_shortest/zip_first/zip_longest
521template <typename R, typename UnaryPredicate>
522bool all_of(R &&range, UnaryPredicate P);
523template <typename R, typename UnaryPredicate>
524bool any_of(R &&range, UnaryPredicate P);
525
526template <size_t... I> struct index_sequence;
527
528template <class... Ts> struct index_sequence_for;
529
530namespace detail {
531
532using std::declval;
533
534// We have to alias this since inlining the actual type at the usage site
535// in the parameter list of iterator_facade_base<> below ICEs MSVC 2017.
536template<typename... Iters> struct ZipTupleType {
537 using type = std::tuple<decltype(*declval<Iters>())...>;
538};
539
540template <typename ZipType, typename... Iters>
541using zip_traits = iterator_facade_base<
542 ZipType, typename std::common_type<std::bidirectional_iterator_tag,
543 typename std::iterator_traits<
544 Iters>::iterator_category...>::type,
545 // ^ TODO: Implement random access methods.
546 typename ZipTupleType<Iters...>::type,
547 typename std::iterator_traits<typename std::tuple_element<
548 0, std::tuple<Iters...>>::type>::difference_type,
549 // ^ FIXME: This follows boost::make_zip_iterator's assumption that all
550 // inner iterators have the same difference_type. It would fail if, for
551 // instance, the second field's difference_type were non-numeric while the
552 // first is.
553 typename ZipTupleType<Iters...>::type *,
554 typename ZipTupleType<Iters...>::type>;
555
556template <typename ZipType, typename... Iters>
557struct zip_common : public zip_traits<ZipType, Iters...> {
558 using Base = zip_traits<ZipType, Iters...>;
559 using value_type = typename Base::value_type;
560
561 std::tuple<Iters...> iterators;
562
563protected:
564 template <size_t... Ns> value_type deref(index_sequence<Ns...>) const {
565 return value_type(*std::get<Ns>(iterators)...);
566 }
567
568 template <size_t... Ns>
569 decltype(iterators) tup_inc(index_sequence<Ns...>) const {
570 return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...);
571 }
572
573 template <size_t... Ns>
574 decltype(iterators) tup_dec(index_sequence<Ns...>) const {
575 return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...);
576 }
577
578public:
579 zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
580
581 value_type operator*() { return deref(index_sequence_for<Iters...>{}); }
582
583 const value_type operator*() const {
584 return deref(index_sequence_for<Iters...>{});
585 }
586
587 ZipType &operator++() {
588 iterators = tup_inc(index_sequence_for<Iters...>{});
589 return *reinterpret_cast<ZipType *>(this);
590 }
591
592 ZipType &operator--() {
593 static_assert(Base::IsBidirectional,
594 "All inner iterators must be at least bidirectional.");
595 iterators = tup_dec(index_sequence_for<Iters...>{});
596 return *reinterpret_cast<ZipType *>(this);
597 }
598};
599
600template <typename... Iters>
601struct zip_first : public zip_common<zip_first<Iters...>, Iters...> {
602 using Base = zip_common<zip_first<Iters...>, Iters...>;
603
604 bool operator==(const zip_first<Iters...> &other) const {
605 return std::get<0>(this->iterators) == std::get<0>(other.iterators);
606 }
607
608 zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
609};
610
611template <typename... Iters>
612class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> {
613 template <size_t... Ns>
614 bool test(const zip_shortest<Iters...> &other, index_sequence<Ns...>) const {
615 return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
616 std::get<Ns>(other.iterators)...},
617 identity<bool>{});
618 }
619
620public:
621 using Base = zip_common<zip_shortest<Iters...>, Iters...>;
622
623 zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
624
625 bool operator==(const zip_shortest<Iters...> &other) const {
626 return !test(other, index_sequence_for<Iters...>{});
627 }
628};
629
630template <template <typename...> class ItType, typename... Args> class zippy {
631public:
632 using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>;
633 using iterator_category = typename iterator::iterator_category;
634 using value_type = typename iterator::value_type;
635 using difference_type = typename iterator::difference_type;
636 using pointer = typename iterator::pointer;
637 using reference = typename iterator::reference;
638
639private:
640 std::tuple<Args...> ts;
641
642 template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const {
643 return iterator(std::begin(std::get<Ns>(ts))...);
644 }
645 template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const {
646 return iterator(std::end(std::get<Ns>(ts))...);
647 }
648
649public:
650 zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
651
652 iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); }
653 iterator end() const { return end_impl(index_sequence_for<Args...>{}); }
654};
655
656} // end namespace detail
657
658/// zip iterator for two or more iteratable types.
659template <typename T, typename U, typename... Args>
660detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u,
661 Args &&... args) {
662 return detail::zippy<detail::zip_shortest, T, U, Args...>(
663 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
664}
665
666/// zip iterator that, for the sake of efficiency, assumes the first iteratee to
667/// be the shortest.
668template <typename T, typename U, typename... Args>
669detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u,
670 Args &&... args) {
671 return detail::zippy<detail::zip_first, T, U, Args...>(
672 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
673}
674
675namespace detail {
676template <typename Iter>
677static Iter next_or_end(const Iter &I, const Iter &End) {
678 if (I == End)
679 return End;
680 return std::next(I);
681}
682
683template <typename Iter>
684static auto deref_or_none(const Iter &I, const Iter &End)
685 -> llvm::Optional<typename std::remove_const<
686 typename std::remove_reference<decltype(*I)>::type>::type> {
687 if (I == End)
688 return None;
689 return *I;
690}
691
692template <typename Iter> struct ZipLongestItemType {
693 using type =
694 llvm::Optional<typename std::remove_const<typename std::remove_reference<
695 decltype(*std::declval<Iter>())>::type>::type>;
696};
697
698template <typename... Iters> struct ZipLongestTupleType {
699 using type = std::tuple<typename ZipLongestItemType<Iters>::type...>;
700};
701
702template <typename... Iters>
703class zip_longest_iterator
704 : public iterator_facade_base<
705 zip_longest_iterator<Iters...>,
706 typename std::common_type<
707 std::forward_iterator_tag,
708 typename std::iterator_traits<Iters>::iterator_category...>::type,
709 typename ZipLongestTupleType<Iters...>::type,
710 typename std::iterator_traits<typename std::tuple_element<
711 0, std::tuple<Iters...>>::type>::difference_type,
712 typename ZipLongestTupleType<Iters...>::type *,
713 typename ZipLongestTupleType<Iters...>::type> {
714public:
715 using value_type = typename ZipLongestTupleType<Iters...>::type;
716
717private:
718 std::tuple<Iters...> iterators;
719 std::tuple<Iters...> end_iterators;
720
721 template <size_t... Ns>
722 bool test(const zip_longest_iterator<Iters...> &other,
723 index_sequence<Ns...>) const {
724 return llvm::any_of(
725 std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
726 std::get<Ns>(other.iterators)...},
727 identity<bool>{});
728 }
729
730 template <size_t... Ns> value_type deref(index_sequence<Ns...>) const {
731 return value_type(
732 deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
733 }
734
735 template <size_t... Ns>
736 decltype(iterators) tup_inc(index_sequence<Ns...>) const {
737 return std::tuple<Iters...>(
738 next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
739 }
740
741public:
742 zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts)
743 : iterators(std::forward<Iters>(ts.first)...),
744 end_iterators(std::forward<Iters>(ts.second)...) {}
745
746 value_type operator*() { return deref(index_sequence_for<Iters...>{}); }
747
748 value_type operator*() const { return deref(index_sequence_for<Iters...>{}); }
749
750 zip_longest_iterator<Iters...> &operator++() {
751 iterators = tup_inc(index_sequence_for<Iters...>{});
752 return *this;
753 }
754
755 bool operator==(const zip_longest_iterator<Iters...> &other) const {
756 return !test(other, index_sequence_for<Iters...>{});
757 }
758};
759
760template <typename... Args> class zip_longest_range {
761public:
762 using iterator =
763 zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>;
764 using iterator_category = typename iterator::iterator_category;
765 using value_type = typename iterator::value_type;
766 using difference_type = typename iterator::difference_type;
767 using pointer = typename iterator::pointer;
768 using reference = typename iterator::reference;
769
770private:
771 std::tuple<Args...> ts;
772
773 template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const {
774 return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)),
775 adl_end(std::get<Ns>(ts)))...);
776 }
777
778 template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const {
779 return iterator(std::make_pair(adl_end(std::get<Ns>(ts)),
780 adl_end(std::get<Ns>(ts)))...);
781 }
782
783public:
784 zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
785
786 iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); }
787 iterator end() const { return end_impl(index_sequence_for<Args...>{}); }
788};
789} // namespace detail
790
791/// Iterate over two or more iterators at the same time. Iteration continues
792/// until all iterators reach the end. The llvm::Optional only contains a value
793/// if the iterator has not reached the end.
794template <typename T, typename U, typename... Args>
795detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u,
796 Args &&... args) {
797 return detail::zip_longest_range<T, U, Args...>(
798 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
799}
800
801/// Iterator wrapper that concatenates sequences together.
802///
803/// This can concatenate different iterators, even with different types, into
804/// a single iterator provided the value types of all the concatenated
805/// iterators expose `reference` and `pointer` types that can be converted to
806/// `ValueT &` and `ValueT *` respectively. It doesn't support more
807/// interesting/customized pointer or reference types.
808///
809/// Currently this only supports forward or higher iterator categories as
810/// inputs and always exposes a forward iterator interface.
811template <typename ValueT, typename... IterTs>
812class concat_iterator
813 : public iterator_facade_base<concat_iterator<ValueT, IterTs...>,
814 std::forward_iterator_tag, ValueT> {
815 using BaseT = typename concat_iterator::iterator_facade_base;
816
817 /// We store both the current and end iterators for each concatenated
818 /// sequence in a tuple of pairs.
819 ///
820 /// Note that something like iterator_range seems nice at first here, but the
821 /// range properties are of little benefit and end up getting in the way
822 /// because we need to do mutation on the current iterators.
823 std::tuple<IterTs...> Begins;
824 std::tuple<IterTs...> Ends;
825
826 /// Attempts to increment a specific iterator.
827 ///
828 /// Returns true if it was able to increment the iterator. Returns false if
829 /// the iterator is already at the end iterator.
830 template <size_t Index> bool incrementHelper() {
831 auto &Begin = std::get<Index>(Begins);
832 auto &End = std::get<Index>(Ends);
833 if (Begin == End)
834 return false;
835
836 ++Begin;
837 return true;
838 }
839
840 /// Increments the first non-end iterator.
841 ///
842 /// It is an error to call this with all iterators at the end.
843 template <size_t... Ns> void increment(index_sequence<Ns...>) {
844 // Build a sequence of functions to increment each iterator if possible.
845 bool (concat_iterator::*IncrementHelperFns[])() = {
846 &concat_iterator::incrementHelper<Ns>...};
847
848 // Loop over them, and stop as soon as we succeed at incrementing one.
849 for (auto &IncrementHelperFn : IncrementHelperFns)
850 if ((this->*IncrementHelperFn)())
851 return;
852
853 llvm_unreachable("Attempted to increment an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to increment an end concat iterator!"
, "/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/STLExtras.h"
, 853)
;
854 }
855
856 /// Returns null if the specified iterator is at the end. Otherwise,
857 /// dereferences the iterator and returns the address of the resulting
858 /// reference.
859 template <size_t Index> ValueT *getHelper() const {
860 auto &Begin = std::get<Index>(Begins);
861 auto &End = std::get<Index>(Ends);
862 if (Begin == End)
863 return nullptr;
864
865 return &*Begin;
866 }
867
868 /// Finds the first non-end iterator, dereferences, and returns the resulting
869 /// reference.
870 ///
871 /// It is an error to call this with all iterators at the end.
872 template <size_t... Ns> ValueT &get(index_sequence<Ns...>) const {
873 // Build a sequence of functions to get from iterator if possible.
874 ValueT *(concat_iterator::*GetHelperFns[])() const = {
875 &concat_iterator::getHelper<Ns>...};
876
877 // Loop over them, and return the first result we find.
878 for (auto &GetHelperFn : GetHelperFns)
879 if (ValueT *P = (this->*GetHelperFn)())
880 return *P;
881
882 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-9~svn362543/include/llvm/ADT/STLExtras.h"
, 882)
;
883 }
884
885public:
886 /// Constructs an iterator from a squence of ranges.
887 ///
888 /// We need the full range to know how to switch between each of the
889 /// iterators.
890 template <typename... RangeTs>
891 explicit concat_iterator(RangeTs &&... Ranges)
892 : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {}
893
894 using BaseT::operator++;
895
896 concat_iterator &operator++() {
897 increment(index_sequence_for<IterTs...>());
898 return *this;
899 }
900
901 ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); }
902
903 bool operator==(const concat_iterator &RHS) const {
904 return Begins == RHS.Begins && Ends == RHS.Ends;
905 }
906};
907
908namespace detail {
909
910/// Helper to store a sequence of ranges being concatenated and access them.
911///
912/// This is designed to facilitate providing actual storage when temporaries
913/// are passed into the constructor such that we can use it as part of range
914/// based for loops.
915template <typename ValueT, typename... RangeTs> class concat_range {
916public:
917 using iterator =
918 concat_iterator<ValueT,
919 decltype(std::begin(std::declval<RangeTs &>()))...>;
920
921private:
922 std::tuple<RangeTs...> Ranges;
923
924 template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) {
925 return iterator(std::get<Ns>(Ranges)...);
926 }
927 template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) {
928 return iterator(make_range(std::end(std::get<Ns>(Ranges)),
929 std::end(std::get<Ns>(Ranges)))...);
930 }
931
932public:
933 concat_range(RangeTs &&... Ranges)
934 : Ranges(std::forward<RangeTs>(Ranges)...) {}
935
936 iterator begin() { return begin_impl(index_sequence_for<RangeTs...>{}); }
937 iterator end() { return end_impl(index_sequence_for<RangeTs...>{}); }
938};
939
940} // end namespace detail
941
942/// Concatenated range across two or more ranges.
943///
944/// The desired value type must be explicitly specified.
945template <typename ValueT, typename... RangeTs>
946detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) {
947 static_assert(sizeof...(RangeTs) > 1,
948 "Need more than one range to concatenate!");
949 return detail::concat_range<ValueT, RangeTs...>(
950 std::forward<RangeTs>(Ranges)...);
951}
952
953//===----------------------------------------------------------------------===//
954// Extra additions to <utility>
955//===----------------------------------------------------------------------===//
956
957/// Function object to check whether the first component of a std::pair
958/// compares less than the first component of another std::pair.
959struct less_first {
960 template <typename T> bool operator()(const T &lhs, const T &rhs) const {
961 return lhs.first < rhs.first;
962 }
963};
964
965/// Function object to check whether the second component of a std::pair
966/// compares less than the second component of another std::pair.
967struct less_second {
968 template <typename T> bool operator()(const T &lhs, const T &rhs) const {
969 return lhs.second < rhs.second;
970 }
971};
972
973/// \brief Function object to apply a binary function to the first component of
974/// a std::pair.
975template<typename FuncTy>
976struct on_first {
977 FuncTy func;
978
979 template <typename T>
980 auto operator()(const T &lhs, const T &rhs) const
981 -> decltype(func(lhs.first, rhs.first)) {
982 return func(lhs.first, rhs.first);
983 }
984};
985
986// A subset of N3658. More stuff can be added as-needed.
987
988/// Represents a compile-time sequence of integers.
989template <class T, T... I> struct integer_sequence {
990 using value_type = T;
991
992 static constexpr size_t size() { return sizeof...(I); }
993};
994
995/// Alias for the common case of a sequence of size_ts.
996template <size_t... I>
997struct index_sequence : integer_sequence<std::size_t, I...> {};
998
999template <std::size_t N, std::size_t... I>
1000struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {};
1001template <std::size_t... I>
1002struct build_index_impl<0, I...> : index_sequence<I...> {};
1003
1004/// Creates a compile-time integer sequence for a parameter pack.
1005template <class... Ts>
1006struct index_sequence_for : build_index_impl<sizeof...(Ts)> {};
1007
1008/// Utility type to build an inheritance chain that makes it easy to rank
1009/// overload candidates.
1010template <int N> struct rank : rank<N - 1> {};
1011template <> struct rank<0> {};
1012
1013/// traits class for checking whether type T is one of any of the given
1014/// types in the variadic list.
1015template <typename T, typename... Ts> struct is_one_of {
1016 static const bool value = false;
1017};
1018
1019template <typename T, typename U, typename... Ts>
1020struct is_one_of<T, U, Ts...> {
1021 static const bool value =
1022 std::is_same<T, U>::value || is_one_of<T, Ts...>::value;
1023};
1024
1025/// traits class for checking whether type T is a base class for all
1026/// the given types in the variadic list.
1027template <typename T, typename... Ts> struct are_base_of {
1028 static const bool value = true;
1029};
1030
1031template <typename T, typename U, typename... Ts>
1032struct are_base_of<T, U, Ts...> {
1033 static const bool value =
1034 std::is_base_of<T, U>::value && are_base_of<T, Ts...>::value;
1035};
1036
1037//===----------------------------------------------------------------------===//
1038// Extra additions for arrays
1039//===----------------------------------------------------------------------===//
1040
1041/// Find the length of an array.
1042template <class T, std::size_t N>
1043constexpr inline size_t array_lengthof(T (&)[N]) {
1044 return N;
1045}
1046
1047/// Adapt std::less<T> for array_pod_sort.
1048template<typename T>
1049inline int array_pod_sort_comparator(const void *P1, const void *P2) {
1050 if (std::less<T>()(*reinterpret_cast<const T*>(P1),
1051 *reinterpret_cast<const T*>(P2)))
1052 return -1;
1053 if (std::less<T>()(*reinterpret_cast<const T*>(P2),
1054 *reinterpret_cast<const T*>(P1)))
1055 return 1;
1056 return 0;
1057}
1058
1059/// get_array_pod_sort_comparator - This is an internal helper function used to
1060/// get type deduction of T right.
1061template<typename T>
1062inline int (*get_array_pod_sort_comparator(const T &))
1063 (const void*, const void*) {
1064 return array_pod_sort_comparator<T>;
1065}
1066
1067/// array_pod_sort - This sorts an array with the specified start and end
1068/// extent. This is just like std::sort, except that it calls qsort instead of
1069/// using an inlined template. qsort is slightly slower than std::sort, but
1070/// most sorts are not performance critical in LLVM and std::sort has to be
1071/// template instantiated for each type, leading to significant measured code
1072/// bloat. This function should generally be used instead of std::sort where
1073/// possible.
1074///
1075/// This function assumes that you have simple POD-like types that can be
1076/// compared with std::less and can be moved with memcpy. If this isn't true,
1077/// you should use std::sort.
1078///
1079/// NOTE: If qsort_r were portable, we could allow a custom comparator and
1080/// default to std::less.
1081template<class IteratorTy>
1082inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
1083 // Don't inefficiently call qsort with one element or trigger undefined
1084 // behavior with an empty sequence.
1085 auto NElts = End - Start;
1086 if (NElts <= 1) return;
1087#ifdef EXPENSIVE_CHECKS
1088 std::mt19937 Generator(std::random_device{}());
1089 std::shuffle(Start, End, Generator);
1090#endif
1091 qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
1092}
1093
1094template <class IteratorTy>
1095inline void array_pod_sort(
1096 IteratorTy Start, IteratorTy End,
1097 int (*Compare)(
1098 const typename std::iterator_traits<IteratorTy>::value_type *,
1099 const typename std::iterator_traits<IteratorTy>::value_type *)) {
1100 // Don't inefficiently call qsort with one element or trigger undefined
1101 // behavior with an empty sequence.
1102 auto NElts = End - Start;
1103 if (NElts <= 1) return;
1104#ifdef EXPENSIVE_CHECKS
1105 std::mt19937 Generator(std::random_device{}());
1106 std::shuffle(Start, End, Generator);
1107#endif
1108 qsort(&*Start, NElts, sizeof(*Start),
1109 reinterpret_cast<int (*)(const void *, const void *)>(Compare));
1110}
1111
1112// Provide wrappers to std::sort which shuffle the elements before sorting
1113// to help uncover non-deterministic behavior (PR35135).
1114template <typename IteratorTy>
1115inline void sort(IteratorTy Start, IteratorTy End) {
1116#ifdef EXPENSIVE_CHECKS
1117 std::mt19937 Generator(std::random_device{}());
1118 std::shuffle(Start, End, Generator);
1119#endif
1120 std::sort(Start, End);
1121}
1122
1123template <typename Container> inline void sort(Container &&C) {
1124 llvm::sort(adl_begin(C), adl_end(C));
1125}
1126
1127template <typename IteratorTy, typename Compare>
1128inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
1129#ifdef EXPENSIVE_CHECKS
1130 std::mt19937 Generator(std::random_device{}());
1131 std::shuffle(Start, End, Generator);
1132#endif
1133 std::sort(Start, End, Comp);
1134}
1135
1136template <typename Container, typename Compare>
1137inline void sort(Container &&C, Compare Comp) {
1138 llvm::sort(adl_begin(C), adl_end(C), Comp);
1139}
1140
1141//===----------------------------------------------------------------------===//
1142// Extra additions to <algorithm>
1143//===----------------------------------------------------------------------===//
1144
1145/// For a container of pointers, deletes the pointers and then clears the
1146/// container.
1147template<typename Container>
1148void DeleteContainerPointers(Container &C) {
1149 for (auto V : C)
1150 delete V;
1151 C.clear();
1152}
1153
1154/// In a container of pairs (usually a map) whose second element is a pointer,
1155/// deletes the second elements and then clears the container.
1156template<typename Container>
1157void DeleteContainerSeconds(Container &C) {
1158 for (auto &V : C)
1159 delete V.second;
1160 C.clear();
1161}
1162
1163/// Get the size of a range. This is a wrapper function around std::distance
1164/// which is only enabled when the operation is O(1).
1165template <typename R>
1166auto size(R &&Range, typename std::enable_if<
1167 std::is_same<typename std::iterator_traits<decltype(
1168 Range.begin())>::iterator_category,
1169 std::random_access_iterator_tag>::value,
1170 void>::type * = nullptr)
1171 -> decltype(std::distance(Range.begin(), Range.end())) {
1172 return std::distance(Range.begin(), Range.end());
1173}
1174
1175/// Provide wrappers to std::for_each which take ranges instead of having to
1176/// pass begin/end explicitly.
1177template <typename R, typename UnaryPredicate>
1178UnaryPredicate for_each(R &&Range, UnaryPredicate P) {
1179 return std::for_each(adl_begin(Range), adl_end(Range), P);
1180}
1181
1182/// Provide wrappers to std::all_of which take ranges instead of having to pass
1183/// begin/end explicitly.
1184template <typename R, typename UnaryPredicate>
1185bool all_of(R &&Range, UnaryPredicate P) {
1186 return std::all_of(adl_begin(Range), adl_end(Range), P);
1187}
1188
1189/// Provide wrappers to std::any_of which take ranges instead of having to pass
1190/// begin/end explicitly.
1191template <typename R, typename UnaryPredicate>
1192bool any_of(R &&Range, UnaryPredicate P) {
1193 return std::any_of(adl_begin(Range), adl_end(Range), P);
1194}
1195
1196/// Provide wrappers to std::none_of which take ranges instead of having to pass
1197/// begin/end explicitly.
1198template <typename R, typename UnaryPredicate>
1199bool none_of(R &&Range, UnaryPredicate P) {
1200 return std::none_of(adl_begin(Range), adl_end(Range), P);
1201}
1202
1203/// Provide wrappers to std::find which take ranges instead of having to pass
1204/// begin/end explicitly.
1205template <typename R, typename T>
1206auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) {
1207 return std::find(adl_begin(Range), adl_end(Range), Val);
1208}
1209
1210/// Provide wrappers to std::find_if which take ranges instead of having to pass
1211/// begin/end explicitly.
1212template <typename R, typename UnaryPredicate>
1213auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
1214 return std::find_if(adl_begin(Range), adl_end(Range), P);
1215}
1216
1217template <typename R, typename UnaryPredicate>
1218auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
1219 return std::find_if_not(adl_begin(Range), adl_end(Range), P);
1220}
1221
1222/// Provide wrappers to std::remove_if which take ranges instead of having to
1223/// pass begin/end explicitly.
1224template <typename R, typename UnaryPredicate>
1225auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
1226 return std::remove_if(adl_begin(Range), adl_end(Range), P);
1227}
1228
1229/// Provide wrappers to std::copy_if which take ranges instead of having to
1230/// pass begin/end explicitly.
1231template <typename R, typename OutputIt, typename UnaryPredicate>
1232OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) {
1233 return std::copy_if(adl_begin(Range), adl_end(Range), Out, P);
1234}
1235
1236template <typename R, typename OutputIt>
1237OutputIt copy(R &&Range, OutputIt Out) {
1238 return std::copy(adl_begin(Range), adl_end(Range), Out);
1239}
1240
1241/// Wrapper function around std::find to detect if an element exists
1242/// in a container.
1243template <typename R, typename E>
1244bool is_contained(R &&Range, const E &Element) {
1245 return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range);
1246}
1247
1248/// Wrapper function around std::count to count the number of times an element
1249/// \p Element occurs in the given range \p Range.
1250template <typename R, typename E>
1251auto count(R &&Range, const E &Element) ->
1252 typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type {
1253 return std::count(adl_begin(Range), adl_end(Range), Element);
1254}
1255
1256/// Wrapper function around std::count_if to count the number of times an
1257/// element satisfying a given predicate occurs in a range.
1258template <typename R, typename UnaryPredicate>
1259auto count_if(R &&Range, UnaryPredicate P) ->
1260 typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type {
1261 return std::count_if(adl_begin(Range), adl_end(Range), P);
1262}
1263
1264/// Wrapper function around std::transform to apply a function to a range and
1265/// store the result elsewhere.
1266template <typename R, typename OutputIt, typename UnaryPredicate>
1267OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) {
1268 return std::transform(adl_begin(Range), adl_end(Range), d_first, P);
1269}
1270
1271/// Provide wrappers to std::partition which take ranges instead of having to
1272/// pass begin/end explicitly.
1273template <typename R, typename UnaryPredicate>
1274auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
1275 return std::partition(adl_begin(Range), adl_end(Range), P);
1276}
1277
1278/// Provide wrappers to std::lower_bound which take ranges instead of having to
1279/// pass begin/end explicitly.
1280template <typename R, typename T>
1281auto lower_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) {
1282 return std::lower_bound(adl_begin(Range), adl_end(Range),
1283 std::forward<T>(Value));
1284}
1285
1286template <typename R, typename T, typename Compare>
1287auto lower_bound(R &&Range, T &&Value, Compare C)
1288 -> decltype(adl_begin(Range)) {
1289 return std::lower_bound(adl_begin(Range), adl_end(Range),
1290 std::forward<T>(Value), C);
1291}
1292
1293/// Provide wrappers to std::upper_bound which take ranges instead of having to
1294/// pass begin/end explicitly.
1295template <typename R, typename T>
1296auto upper_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) {
1297 return std::upper_bound(adl_begin(Range), adl_end(Range),
1298 std::forward<T>(Value));
1299}
1300
1301template <typename R, typename T, typename Compare>
1302auto upper_bound(R &&Range, T &&Value, Compare C)
1303 -> decltype(adl_begin(Range)) {
1304 return std::upper_bound(adl_begin(Range), adl_end(Range),
1305 std::forward<T>(Value), C);
1306}
1307
1308template <typename R>
1309void stable_sort(R &&Range) {
1310 std::stable_sort(adl_begin(Range), adl_end(Range));
1311}
1312
1313template <typename R, typename Compare>
1314void stable_sort(R &&Range, Compare C) {
1315 std::stable_sort(adl_begin(Range), adl_end(Range), C);
1316}
1317
1318/// Binary search for the first index where a predicate is true.
1319/// Returns the first I in [Lo, Hi) where C(I) is true, or Hi if it never is.
1320/// Requires that C is always false below some limit, and always true above it.
1321///
1322/// Example:
1323/// size_t DawnModernEra = bsearch(1776, 2050, [](size_t Year){
1324/// return Presidents.for(Year).twitterHandle() != None;
1325/// });
1326///
1327/// Note the return value differs from std::binary_search!
1328template <typename Predicate>
1329size_t bsearch(size_t Lo, size_t Hi, Predicate P) {
1330 while (Lo != Hi) {
1331 assert(Hi > Lo)((Hi > Lo) ? static_cast<void> (0) : __assert_fail (
"Hi > Lo", "/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/STLExtras.h"
, 1331, __PRETTY_FUNCTION__))
;
1332 size_t Mid = Lo + (Hi - Lo) / 2;
1333 if (P(Mid))
1334 Hi = Mid;
1335 else
1336 Lo = Mid + 1;
1337 }
1338 return Hi;
1339}
1340
1341/// Binary search for the first iterator where a predicate is true.
1342/// Returns the first I in [Lo, Hi) where C(*I) is true, or Hi if it never is.
1343/// Requires that C is always false below some limit, and always true above it.
1344template <typename It, typename Predicate,
1345 typename Val = decltype(*std::declval<It>())>
1346It bsearch(It Lo, It Hi, Predicate P) {
1347 return std::lower_bound(Lo, Hi, 0u,
1348 [&](const Val &V, unsigned) { return !P(V); });
1349}
1350
1351/// Binary search for the first iterator in a range where a predicate is true.
1352/// Requires that C is always false below some limit, and always true above it.
1353template <typename R, typename Predicate>
1354auto bsearch(R &&Range, Predicate P) -> decltype(adl_begin(Range)) {
1355 return bsearch(adl_begin(Range), adl_end(Range), P);
1356}
1357
1358/// Wrapper function around std::equal to detect if all elements
1359/// in a container are same.
1360template <typename R>
1361bool is_splat(R &&Range) {
1362 size_t range_size = size(Range);
1363 return range_size != 0 && (range_size == 1 ||
1364 std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range)));
1365}
1366
1367/// Given a range of type R, iterate the entire range and return a
1368/// SmallVector with elements of the vector. This is useful, for example,
1369/// when you want to iterate a range and then sort the results.
1370template <unsigned Size, typename R>
1371SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size>
1372to_vector(R &&Range) {
1373 return {adl_begin(Range), adl_end(Range)};
1374}
1375
1376/// Provide a container algorithm similar to C++ Library Fundamentals v2's
1377/// `erase_if` which is equivalent to:
1378///
1379/// C.erase(remove_if(C, pred), C.end());
1380///
1381/// This version works for any container with an erase method call accepting
1382/// two iterators.
1383template <typename Container, typename UnaryPredicate>
1384void erase_if(Container &C, UnaryPredicate P) {
1385 C.erase(remove_if(C, P), C.end());
1386}
1387
1388//===----------------------------------------------------------------------===//
1389// Extra additions to <memory>
1390//===----------------------------------------------------------------------===//
1391
1392// Implement make_unique according to N3656.
1393
1394/// Constructs a `new T()` with the given args and returns a
1395/// `unique_ptr<T>` which owns the object.
1396///
1397/// Example:
1398///
1399/// auto p = make_unique<int>();
1400/// auto p = make_unique<std::tuple<int, int>>(0, 1);
1401template <class T, class... Args>
1402typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
1403make_unique(Args &&... args) {
1404 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
4
Calling constructor for 'BindRebaseSegInfo'
1405}
1406
1407/// Constructs a `new T[n]` with the given args and returns a
1408/// `unique_ptr<T[]>` which owns the object.
1409///
1410/// \param n size of the new array.
1411///
1412/// Example:
1413///
1414/// auto p = make_unique<int[]>(2); // value-initializes the array with 0's.
1415template <class T>
1416typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0,
1417 std::unique_ptr<T>>::type
1418make_unique(size_t n) {
1419 return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
1420}
1421
1422/// This function isn't used and is only here to provide better compile errors.
1423template <class T, class... Args>
1424typename std::enable_if<std::extent<T>::value != 0>::type
1425make_unique(Args &&...) = delete;
1426
1427struct FreeDeleter {
1428 void operator()(void* v) {
1429 ::free(v);
1430 }
1431};
1432
1433template<typename First, typename Second>
1434struct pair_hash {
1435 size_t operator()(const std::pair<First, Second> &P) const {
1436 return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second);
1437 }
1438};
1439
1440/// A functor like C++14's std::less<void> in its absence.
1441struct less {
1442 template <typename A, typename B> bool operator()(A &&a, B &&b) const {
1443 return std::forward<A>(a) < std::forward<B>(b);
1444 }
1445};
1446
1447/// A functor like C++14's std::equal<void> in its absence.
1448struct equal {
1449 template <typename A, typename B> bool operator()(A &&a, B &&b) const {
1450 return std::forward<A>(a) == std::forward<B>(b);
1451 }
1452};
1453
1454/// Binary functor that adapts to any other binary functor after dereferencing
1455/// operands.
1456template <typename T> struct deref {
1457 T func;
1458
1459 // Could be further improved to cope with non-derivable functors and
1460 // non-binary functors (should be a variadic template member function
1461 // operator()).
1462 template <typename A, typename B>
1463 auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) {
1464 assert(lhs)((lhs) ? static_cast<void> (0) : __assert_fail ("lhs", "/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/STLExtras.h"
, 1464, __PRETTY_FUNCTION__))
;
1465 assert(rhs)((rhs) ? static_cast<void> (0) : __assert_fail ("rhs", "/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/STLExtras.h"
, 1465, __PRETTY_FUNCTION__))
;
1466 return func(*lhs, *rhs);
1467 }
1468};
1469
1470namespace detail {
1471
1472template <typename R> class enumerator_iter;
1473
1474template <typename R> struct result_pair {
1475 friend class enumerator_iter<R>;
1476
1477 result_pair() = default;
1478 result_pair(std::size_t Index, IterOfRange<R> Iter)
1479 : Index(Index), Iter(Iter) {}
1480
1481 result_pair<R> &operator=(const result_pair<R> &Other) {
1482 Index = Other.Index;
1483 Iter = Other.Iter;
1484 return *this;
1485 }
1486
1487 std::size_t index() const { return Index; }
1488 const ValueOfRange<R> &value() const { return *Iter; }
1489 ValueOfRange<R> &value() { return *Iter; }
1490
1491private:
1492 std::size_t Index = std::numeric_limits<std::size_t>::max();
1493 IterOfRange<R> Iter;
1494};
1495
1496template <typename R>
1497class enumerator_iter
1498 : public iterator_facade_base<
1499 enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>,
1500 typename std::iterator_traits<IterOfRange<R>>::difference_type,
1501 typename std::iterator_traits<IterOfRange<R>>::pointer,
1502 typename std::iterator_traits<IterOfRange<R>>::reference> {
1503 using result_type = result_pair<R>;
1504
1505public:
1506 explicit enumerator_iter(IterOfRange<R> EndIter)
1507 : Result(std::numeric_limits<size_t>::max(), EndIter) {}
1508
1509 enumerator_iter(std::size_t Index, IterOfRange<R> Iter)
1510 : Result(Index, Iter) {}
1511
1512 result_type &operator*() { return Result; }
1513 const result_type &operator*() const { return Result; }
1514
1515 enumerator_iter<R> &operator++() {
1516 assert(Result.Index != std::numeric_limits<size_t>::max())((Result.Index != std::numeric_limits<size_t>::max()) ?
static_cast<void> (0) : __assert_fail ("Result.Index != std::numeric_limits<size_t>::max()"
, "/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/STLExtras.h"
, 1516, __PRETTY_FUNCTION__))
;
1517 ++Result.Iter;
1518 ++Result.Index;
1519 return *this;
1520 }
1521
1522 bool operator==(const enumerator_iter<R> &RHS) const {
1523 // Don't compare indices here, only iterators. It's possible for an end
1524 // iterator to have different indices depending on whether it was created
1525 // by calling std::end() versus incrementing a valid iterator.
1526 return Result.Iter == RHS.Result.Iter;
1527 }
1528
1529 enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) {
1530 Result = Other.Result;
1531 return *this;
1532 }
1533
1534private:
1535 result_type Result;
1536};
1537
1538template <typename R> class enumerator {
1539public:
1540 explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {}
1541
1542 enumerator_iter<R> begin() {
1543 return enumerator_iter<R>(0, std::begin(TheRange));
1544 }
1545
1546 enumerator_iter<R> end() {
1547 return enumerator_iter<R>(std::end(TheRange));
1548 }
1549
1550private:
1551 R TheRange;
1552};
1553
1554} // end namespace detail
1555
1556/// Given an input range, returns a new range whose values are are pair (A,B)
1557/// such that A is the 0-based index of the item in the sequence, and B is
1558/// the value from the original sequence. Example:
1559///
1560/// std::vector<char> Items = {'A', 'B', 'C', 'D'};
1561/// for (auto X : enumerate(Items)) {
1562/// printf("Item %d - %c\n", X.index(), X.value());
1563/// }
1564///
1565/// Output:
1566/// Item 0 - A
1567/// Item 1 - B
1568/// Item 2 - C
1569/// Item 3 - D
1570///
1571template <typename R> detail::enumerator<R> enumerate(R &&TheRange) {
1572 return detail::enumerator<R>(std::forward<R>(TheRange));
1573}
1574
1575namespace detail {
1576
1577template <typename F, typename Tuple, std::size_t... I>
1578auto apply_tuple_impl(F &&f, Tuple &&t, index_sequence<I...>)
1579 -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...)) {
1580 return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
1581}
1582
1583} // end namespace detail
1584
1585/// Given an input tuple (a1, a2, ..., an), pass the arguments of the
1586/// tuple variadically to f as if by calling f(a1, a2, ..., an) and
1587/// return the result.
1588template <typename F, typename Tuple>
1589auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl(
1590 std::forward<F>(f), std::forward<Tuple>(t),
1591 build_index_impl<
1592 std::tuple_size<typename std::decay<Tuple>::type>::value>{})) {
1593 using Indices = build_index_impl<
1594 std::tuple_size<typename std::decay<Tuple>::type>::value>;
1595
1596 return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t),
1597 Indices{});
1598}
1599
1600/// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N)
1601/// time. Not meant for use with random-access iterators.
1602template <typename IterTy>
1603bool hasNItems(
1604 IterTy &&Begin, IterTy &&End, unsigned N,
1605 typename std::enable_if<
1606 !std::is_same<
1607 typename std::iterator_traits<typename std::remove_reference<
1608 decltype(Begin)>::type>::iterator_category,
1609 std::random_access_iterator_tag>::value,
1610 void>::type * = nullptr) {
1611 for (; N; --N, ++Begin)
1612 if (Begin == End)
1613 return false; // Too few.
1614 return Begin == End;
1615}
1616
1617/// Return true if the sequence [Begin, End) has N or more items. Runs in O(N)
1618/// time. Not meant for use with random-access iterators.
1619template <typename IterTy>
1620bool hasNItemsOrMore(
1621 IterTy &&Begin, IterTy &&End, unsigned N,
1622 typename std::enable_if<
1623 !std::is_same<
1624 typename std::iterator_traits<typename std::remove_reference<
1625 decltype(Begin)>::type>::iterator_category,
1626 std::random_access_iterator_tag>::value,
1627 void>::type * = nullptr) {
1628 for (; N; --N, ++Begin)
1629 if (Begin == End)
1630 return false; // Too few.
1631 return true;
1632}
1633
1634/// Returns a raw pointer that represents the same address as the argument.
1635///
1636/// The late bound return should be removed once we move to C++14 to better
1637/// align with the C++20 declaration. Also, this implementation can be removed
1638/// once we move to C++20 where it's defined as std::to_addres()
1639///
1640/// The std::pointer_traits<>::to_address(p) variations of these overloads has
1641/// not been implemented.
1642template <class Ptr> auto to_address(const Ptr &P) -> decltype(P.operator->()) {
1643 return P.operator->();
1644}
1645template <class T> constexpr T *to_address(T *P) { return P; }
1646
1647} // end namespace llvm
1648
1649#endif // LLVM_ADT_STLEXTRAS_H