Bug Summary

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

Annotated Source Code

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