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