Bug Summary

File:lib/Object/MachOObjectFile.cpp
Warning:line 1663, column 7
Value stored to 'NType' is never read

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