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