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