Bug Summary

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

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