Bug Summary

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

Annotated Source Code

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