Bug Summary

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

Annotated Source Code

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