1 //===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
45 #include <system_error>
48 using namespace object
;
57 } // end anonymous namespace
59 static Error
malformedError(const Twine
&Msg
) {
60 return make_error
<GenericBinaryError
>("truncated or malformed object (" +
62 object_error::parse_failed
);
65 // FIXME: Replace all uses of this function with getStructOrErr.
67 static T
getStruct(const MachOObjectFile
&O
, const char *P
) {
68 // Don't read before the beginning or past the end of the file
69 if (P
< O
.getData().begin() || P
+ sizeof(T
) > O
.getData().end())
70 report_fatal_error("Malformed MachO file.");
73 memcpy(&Cmd
, P
, sizeof(T
));
74 if (O
.isLittleEndian() != sys::IsLittleEndianHost
)
75 MachO::swapStruct(Cmd
);
80 static Expected
<T
> getStructOrErr(const MachOObjectFile
&O
, const char *P
) {
81 // Don't read before the beginning or past the end of the file
82 if (P
< O
.getData().begin() || P
+ sizeof(T
) > O
.getData().end())
83 return malformedError("Structure read out-of-range");
86 memcpy(&Cmd
, P
, sizeof(T
));
87 if (O
.isLittleEndian() != sys::IsLittleEndianHost
)
88 MachO::swapStruct(Cmd
);
93 getSectionPtr(const MachOObjectFile
&O
, MachOObjectFile::LoadCommandInfo L
,
95 uintptr_t CommandAddr
= reinterpret_cast<uintptr_t>(L
.Ptr
);
97 bool Is64
= O
.is64Bit();
98 unsigned SegmentLoadSize
= Is64
? sizeof(MachO::segment_command_64
) :
99 sizeof(MachO::segment_command
);
100 unsigned SectionSize
= Is64
? sizeof(MachO::section_64
) :
101 sizeof(MachO::section
);
103 uintptr_t SectionAddr
= CommandAddr
+ SegmentLoadSize
+ Sec
* SectionSize
;
104 return reinterpret_cast<const char*>(SectionAddr
);
107 static const char *getPtr(const MachOObjectFile
&O
, size_t Offset
) {
108 assert(Offset
<= O
.getData().size());
109 return O
.getData().data() + Offset
;
112 static MachO::nlist_base
113 getSymbolTableEntryBase(const MachOObjectFile
&O
, DataRefImpl DRI
) {
114 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
115 return getStruct
<MachO::nlist_base
>(O
, P
);
118 static StringRef
parseSegmentOrSectionName(const char *P
) {
122 // Not null terminated, so this is a 16 char string.
123 return StringRef(P
, 16);
126 static unsigned getCPUType(const MachOObjectFile
&O
) {
127 return O
.getHeader().cputype
;
130 static unsigned getCPUSubType(const MachOObjectFile
&O
) {
131 return O
.getHeader().cpusubtype
;
135 getPlainRelocationAddress(const MachO::any_relocation_info
&RE
) {
140 getScatteredRelocationAddress(const MachO::any_relocation_info
&RE
) {
141 return RE
.r_word0
& 0xffffff;
144 static bool getPlainRelocationPCRel(const MachOObjectFile
&O
,
145 const MachO::any_relocation_info
&RE
) {
146 if (O
.isLittleEndian())
147 return (RE
.r_word1
>> 24) & 1;
148 return (RE
.r_word1
>> 7) & 1;
152 getScatteredRelocationPCRel(const MachO::any_relocation_info
&RE
) {
153 return (RE
.r_word0
>> 30) & 1;
156 static unsigned getPlainRelocationLength(const MachOObjectFile
&O
,
157 const MachO::any_relocation_info
&RE
) {
158 if (O
.isLittleEndian())
159 return (RE
.r_word1
>> 25) & 3;
160 return (RE
.r_word1
>> 5) & 3;
164 getScatteredRelocationLength(const MachO::any_relocation_info
&RE
) {
165 return (RE
.r_word0
>> 28) & 3;
168 static unsigned getPlainRelocationType(const MachOObjectFile
&O
,
169 const MachO::any_relocation_info
&RE
) {
170 if (O
.isLittleEndian())
171 return RE
.r_word1
>> 28;
172 return RE
.r_word1
& 0xf;
175 static uint32_t getSectionFlags(const MachOObjectFile
&O
,
178 MachO::section_64 Sect
= O
.getSection64(Sec
);
181 MachO::section Sect
= O
.getSection(Sec
);
185 static Expected
<MachOObjectFile::LoadCommandInfo
>
186 getLoadCommandInfo(const MachOObjectFile
&Obj
, const char *Ptr
,
187 uint32_t LoadCommandIndex
) {
188 if (auto CmdOrErr
= getStructOrErr
<MachO::load_command
>(Obj
, Ptr
)) {
189 if (CmdOrErr
->cmdsize
+ Ptr
> Obj
.getData().end())
190 return malformedError("load command " + Twine(LoadCommandIndex
) +
191 " extends past end of file");
192 if (CmdOrErr
->cmdsize
< 8)
193 return malformedError("load command " + Twine(LoadCommandIndex
) +
194 " with size less than 8 bytes");
195 return MachOObjectFile::LoadCommandInfo({Ptr
, *CmdOrErr
});
197 return CmdOrErr
.takeError();
200 static Expected
<MachOObjectFile::LoadCommandInfo
>
201 getFirstLoadCommandInfo(const MachOObjectFile
&Obj
) {
202 unsigned HeaderSize
= Obj
.is64Bit() ? sizeof(MachO::mach_header_64
)
203 : sizeof(MachO::mach_header
);
204 if (sizeof(MachO::load_command
) > Obj
.getHeader().sizeofcmds
)
205 return malformedError("load command 0 extends past the end all load "
206 "commands in the file");
207 return getLoadCommandInfo(Obj
, getPtr(Obj
, HeaderSize
), 0);
210 static Expected
<MachOObjectFile::LoadCommandInfo
>
211 getNextLoadCommandInfo(const MachOObjectFile
&Obj
, uint32_t LoadCommandIndex
,
212 const MachOObjectFile::LoadCommandInfo
&L
) {
213 unsigned HeaderSize
= Obj
.is64Bit() ? sizeof(MachO::mach_header_64
)
214 : sizeof(MachO::mach_header
);
215 if (L
.Ptr
+ L
.C
.cmdsize
+ sizeof(MachO::load_command
) >
216 Obj
.getData().data() + HeaderSize
+ Obj
.getHeader().sizeofcmds
)
217 return malformedError("load command " + Twine(LoadCommandIndex
+ 1) +
218 " extends past the end all load commands in the file");
219 return getLoadCommandInfo(Obj
, L
.Ptr
+ L
.C
.cmdsize
, LoadCommandIndex
+ 1);
222 template <typename T
>
223 static void parseHeader(const MachOObjectFile
&Obj
, T
&Header
,
225 if (sizeof(T
) > Obj
.getData().size()) {
226 Err
= malformedError("the mach header extends past the end of the "
230 if (auto HeaderOrErr
= getStructOrErr
<T
>(Obj
, getPtr(Obj
, 0)))
231 Header
= *HeaderOrErr
;
233 Err
= HeaderOrErr
.takeError();
236 // This is used to check for overlapping of Mach-O elements.
237 struct MachOElement
{
243 static Error
checkOverlappingElement(std::list
<MachOElement
> &Elements
,
244 uint64_t Offset
, uint64_t Size
,
247 return Error::success();
249 for (auto it
=Elements
.begin() ; it
!= Elements
.end(); ++it
) {
251 if ((Offset
>= E
.Offset
&& Offset
< E
.Offset
+ E
.Size
) ||
252 (Offset
+ Size
> E
.Offset
&& Offset
+ Size
< E
.Offset
+ E
.Size
) ||
253 (Offset
<= E
.Offset
&& Offset
+ Size
>= E
.Offset
+ E
.Size
))
254 return malformedError(Twine(Name
) + " at offset " + Twine(Offset
) +
255 " with a size of " + Twine(Size
) + ", overlaps " +
256 E
.Name
+ " at offset " + Twine(E
.Offset
) + " with "
257 "a size of " + Twine(E
.Size
));
260 if (nt
!= Elements
.end()) {
262 if (Offset
+ Size
<= N
.Offset
) {
263 Elements
.insert(nt
, {Offset
, Size
, Name
});
264 return Error::success();
268 Elements
.push_back({Offset
, Size
, Name
});
269 return Error::success();
272 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
273 // sections to \param Sections, and optionally sets
274 // \param IsPageZeroSegment to true.
275 template <typename Segment
, typename Section
>
276 static Error
parseSegmentLoadCommand(
277 const MachOObjectFile
&Obj
, const MachOObjectFile::LoadCommandInfo
&Load
,
278 SmallVectorImpl
<const char *> &Sections
, bool &IsPageZeroSegment
,
279 uint32_t LoadCommandIndex
, const char *CmdName
, uint64_t SizeOfHeaders
,
280 std::list
<MachOElement
> &Elements
) {
281 const unsigned SegmentLoadSize
= sizeof(Segment
);
282 if (Load
.C
.cmdsize
< SegmentLoadSize
)
283 return malformedError("load command " + Twine(LoadCommandIndex
) +
284 " " + CmdName
+ " cmdsize too small");
285 if (auto SegOrErr
= getStructOrErr
<Segment
>(Obj
, Load
.Ptr
)) {
286 Segment S
= SegOrErr
.get();
287 const unsigned SectionSize
= sizeof(Section
);
288 uint64_t FileSize
= Obj
.getData().size();
289 if (S
.nsects
> std::numeric_limits
<uint32_t>::max() / SectionSize
||
290 S
.nsects
* SectionSize
> Load
.C
.cmdsize
- SegmentLoadSize
)
291 return malformedError("load command " + Twine(LoadCommandIndex
) +
292 " inconsistent cmdsize in " + CmdName
+
293 " for the number of sections");
294 for (unsigned J
= 0; J
< S
.nsects
; ++J
) {
295 const char *Sec
= getSectionPtr(Obj
, Load
, J
);
296 Sections
.push_back(Sec
);
297 auto SectionOrErr
= getStructOrErr
<Section
>(Obj
, Sec
);
299 return SectionOrErr
.takeError();
300 Section s
= SectionOrErr
.get();
301 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
302 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
303 s
.flags
!= MachO::S_ZEROFILL
&&
304 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
306 return malformedError("offset field of section " + Twine(J
) + " in " +
307 CmdName
+ " command " + Twine(LoadCommandIndex
) +
308 " extends past the end of the file");
309 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
310 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
311 s
.flags
!= MachO::S_ZEROFILL
&&
312 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&& S
.fileoff
== 0 &&
313 s
.offset
< SizeOfHeaders
&& s
.size
!= 0)
314 return malformedError("offset field of section " + Twine(J
) + " in " +
315 CmdName
+ " command " + Twine(LoadCommandIndex
) +
316 " not past the headers of the file");
317 uint64_t BigSize
= s
.offset
;
319 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
320 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
321 s
.flags
!= MachO::S_ZEROFILL
&&
322 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
324 return malformedError("offset field plus size field of section " +
325 Twine(J
) + " in " + CmdName
+ " command " +
326 Twine(LoadCommandIndex
) +
327 " extends past the end of the file");
328 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
329 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
330 s
.flags
!= MachO::S_ZEROFILL
&&
331 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
333 return malformedError("size field of section " +
334 Twine(J
) + " in " + CmdName
+ " command " +
335 Twine(LoadCommandIndex
) +
336 " greater than the segment");
337 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
338 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&& s
.size
!= 0 &&
340 return malformedError("addr field of section " + Twine(J
) + " in " +
341 CmdName
+ " command " + Twine(LoadCommandIndex
) +
342 " less than the segment's vmaddr");
345 uint64_t BigEnd
= S
.vmaddr
;
347 if (S
.vmsize
!= 0 && s
.size
!= 0 && BigSize
> BigEnd
)
348 return malformedError("addr field plus size of section " + Twine(J
) +
349 " in " + CmdName
+ " command " +
350 Twine(LoadCommandIndex
) +
351 " greater than than "
352 "the segment's vmaddr plus vmsize");
353 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
354 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
355 s
.flags
!= MachO::S_ZEROFILL
&&
356 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
)
357 if (Error Err
= checkOverlappingElement(Elements
, s
.offset
, s
.size
,
360 if (s
.reloff
> FileSize
)
361 return malformedError("reloff field of section " + Twine(J
) + " in " +
362 CmdName
+ " command " + Twine(LoadCommandIndex
) +
363 " extends past the end of the file");
365 BigSize
*= sizeof(struct MachO::relocation_info
);
367 if (BigSize
> FileSize
)
368 return malformedError("reloff field plus nreloc field times sizeof("
369 "struct relocation_info) of section " +
370 Twine(J
) + " in " + CmdName
+ " command " +
371 Twine(LoadCommandIndex
) +
372 " extends past the end of the file");
373 if (Error Err
= checkOverlappingElement(Elements
, s
.reloff
, s
.nreloc
*
375 MachO::relocation_info
),
376 "section relocation entries"))
379 if (S
.fileoff
> FileSize
)
380 return malformedError("load command " + Twine(LoadCommandIndex
) +
381 " fileoff field in " + CmdName
+
382 " extends past the end of the file");
383 uint64_t BigSize
= S
.fileoff
;
384 BigSize
+= S
.filesize
;
385 if (BigSize
> FileSize
)
386 return malformedError("load command " + Twine(LoadCommandIndex
) +
387 " fileoff field plus filesize field in " +
388 CmdName
+ " extends past the end of the file");
389 if (S
.vmsize
!= 0 && S
.filesize
> S
.vmsize
)
390 return malformedError("load command " + Twine(LoadCommandIndex
) +
391 " filesize field in " + CmdName
+
392 " greater than vmsize field");
393 IsPageZeroSegment
|= StringRef("__PAGEZERO").equals(S
.segname
);
395 return SegOrErr
.takeError();
397 return Error::success();
400 static Error
checkSymtabCommand(const MachOObjectFile
&Obj
,
401 const MachOObjectFile::LoadCommandInfo
&Load
,
402 uint32_t LoadCommandIndex
,
403 const char **SymtabLoadCmd
,
404 std::list
<MachOElement
> &Elements
) {
405 if (Load
.C
.cmdsize
< sizeof(MachO::symtab_command
))
406 return malformedError("load command " + Twine(LoadCommandIndex
) +
407 " LC_SYMTAB cmdsize too small");
408 if (*SymtabLoadCmd
!= nullptr)
409 return malformedError("more than one LC_SYMTAB command");
410 auto SymtabOrErr
= getStructOrErr
<MachO::symtab_command
>(Obj
, Load
.Ptr
);
412 return SymtabOrErr
.takeError();
413 MachO::symtab_command Symtab
= SymtabOrErr
.get();
414 if (Symtab
.cmdsize
!= sizeof(MachO::symtab_command
))
415 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex
) +
416 " has incorrect cmdsize");
417 uint64_t FileSize
= Obj
.getData().size();
418 if (Symtab
.symoff
> FileSize
)
419 return malformedError("symoff field of LC_SYMTAB command " +
420 Twine(LoadCommandIndex
) + " extends past the end "
422 uint64_t SymtabSize
= Symtab
.nsyms
;
423 const char *struct_nlist_name
;
425 SymtabSize
*= sizeof(MachO::nlist_64
);
426 struct_nlist_name
= "struct nlist_64";
428 SymtabSize
*= sizeof(MachO::nlist
);
429 struct_nlist_name
= "struct nlist";
431 uint64_t BigSize
= SymtabSize
;
432 BigSize
+= Symtab
.symoff
;
433 if (BigSize
> FileSize
)
434 return malformedError("symoff field plus nsyms field times sizeof(" +
435 Twine(struct_nlist_name
) + ") of LC_SYMTAB command " +
436 Twine(LoadCommandIndex
) + " extends past the end "
438 if (Error Err
= checkOverlappingElement(Elements
, Symtab
.symoff
, SymtabSize
,
441 if (Symtab
.stroff
> FileSize
)
442 return malformedError("stroff field of LC_SYMTAB command " +
443 Twine(LoadCommandIndex
) + " extends past the end "
445 BigSize
= Symtab
.stroff
;
446 BigSize
+= Symtab
.strsize
;
447 if (BigSize
> FileSize
)
448 return malformedError("stroff field plus strsize field of LC_SYMTAB "
449 "command " + Twine(LoadCommandIndex
) + " extends "
450 "past the end of the file");
451 if (Error Err
= checkOverlappingElement(Elements
, Symtab
.stroff
,
452 Symtab
.strsize
, "string table"))
454 *SymtabLoadCmd
= Load
.Ptr
;
455 return Error::success();
458 static Error
checkDysymtabCommand(const MachOObjectFile
&Obj
,
459 const MachOObjectFile::LoadCommandInfo
&Load
,
460 uint32_t LoadCommandIndex
,
461 const char **DysymtabLoadCmd
,
462 std::list
<MachOElement
> &Elements
) {
463 if (Load
.C
.cmdsize
< sizeof(MachO::dysymtab_command
))
464 return malformedError("load command " + Twine(LoadCommandIndex
) +
465 " LC_DYSYMTAB cmdsize too small");
466 if (*DysymtabLoadCmd
!= nullptr)
467 return malformedError("more than one LC_DYSYMTAB command");
469 getStructOrErr
<MachO::dysymtab_command
>(Obj
, Load
.Ptr
);
471 return DysymtabOrErr
.takeError();
472 MachO::dysymtab_command Dysymtab
= DysymtabOrErr
.get();
473 if (Dysymtab
.cmdsize
!= sizeof(MachO::dysymtab_command
))
474 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex
) +
475 " has incorrect cmdsize");
476 uint64_t FileSize
= Obj
.getData().size();
477 if (Dysymtab
.tocoff
> FileSize
)
478 return malformedError("tocoff field of LC_DYSYMTAB command " +
479 Twine(LoadCommandIndex
) + " extends past the end of "
481 uint64_t BigSize
= Dysymtab
.ntoc
;
482 BigSize
*= sizeof(MachO::dylib_table_of_contents
);
483 BigSize
+= Dysymtab
.tocoff
;
484 if (BigSize
> FileSize
)
485 return malformedError("tocoff field plus ntoc field times sizeof(struct "
486 "dylib_table_of_contents) of LC_DYSYMTAB command " +
487 Twine(LoadCommandIndex
) + " extends past the end of "
489 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.tocoff
,
490 Dysymtab
.ntoc
* sizeof(struct
491 MachO::dylib_table_of_contents
),
492 "table of contents"))
494 if (Dysymtab
.modtaboff
> FileSize
)
495 return malformedError("modtaboff field of LC_DYSYMTAB command " +
496 Twine(LoadCommandIndex
) + " extends past the end of "
498 BigSize
= Dysymtab
.nmodtab
;
499 const char *struct_dylib_module_name
;
500 uint64_t sizeof_modtab
;
502 sizeof_modtab
= sizeof(MachO::dylib_module_64
);
503 struct_dylib_module_name
= "struct dylib_module_64";
505 sizeof_modtab
= sizeof(MachO::dylib_module
);
506 struct_dylib_module_name
= "struct dylib_module";
508 BigSize
*= sizeof_modtab
;
509 BigSize
+= Dysymtab
.modtaboff
;
510 if (BigSize
> FileSize
)
511 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
512 Twine(struct_dylib_module_name
) + ") of LC_DYSYMTAB "
513 "command " + Twine(LoadCommandIndex
) + " extends "
514 "past the end of the file");
515 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.modtaboff
,
516 Dysymtab
.nmodtab
* sizeof_modtab
,
519 if (Dysymtab
.extrefsymoff
> FileSize
)
520 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
521 Twine(LoadCommandIndex
) + " extends past the end of "
523 BigSize
= Dysymtab
.nextrefsyms
;
524 BigSize
*= sizeof(MachO::dylib_reference
);
525 BigSize
+= Dysymtab
.extrefsymoff
;
526 if (BigSize
> FileSize
)
527 return malformedError("extrefsymoff field plus nextrefsyms field times "
528 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
529 "command " + Twine(LoadCommandIndex
) + " extends "
530 "past the end of the file");
531 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.extrefsymoff
,
532 Dysymtab
.nextrefsyms
*
533 sizeof(MachO::dylib_reference
),
536 if (Dysymtab
.indirectsymoff
> FileSize
)
537 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
538 Twine(LoadCommandIndex
) + " extends past the end of "
540 BigSize
= Dysymtab
.nindirectsyms
;
541 BigSize
*= sizeof(uint32_t);
542 BigSize
+= Dysymtab
.indirectsymoff
;
543 if (BigSize
> FileSize
)
544 return malformedError("indirectsymoff field plus nindirectsyms field times "
545 "sizeof(uint32_t) of LC_DYSYMTAB command " +
546 Twine(LoadCommandIndex
) + " extends past the end of "
548 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.indirectsymoff
,
549 Dysymtab
.nindirectsyms
*
553 if (Dysymtab
.extreloff
> FileSize
)
554 return malformedError("extreloff field of LC_DYSYMTAB command " +
555 Twine(LoadCommandIndex
) + " extends past the end of "
557 BigSize
= Dysymtab
.nextrel
;
558 BigSize
*= sizeof(MachO::relocation_info
);
559 BigSize
+= Dysymtab
.extreloff
;
560 if (BigSize
> FileSize
)
561 return malformedError("extreloff field plus nextrel field times sizeof"
562 "(struct relocation_info) of LC_DYSYMTAB command " +
563 Twine(LoadCommandIndex
) + " extends past the end of "
565 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.extreloff
,
567 sizeof(MachO::relocation_info
),
568 "external relocation table"))
570 if (Dysymtab
.locreloff
> FileSize
)
571 return malformedError("locreloff field of LC_DYSYMTAB command " +
572 Twine(LoadCommandIndex
) + " extends past the end of "
574 BigSize
= Dysymtab
.nlocrel
;
575 BigSize
*= sizeof(MachO::relocation_info
);
576 BigSize
+= Dysymtab
.locreloff
;
577 if (BigSize
> FileSize
)
578 return malformedError("locreloff field plus nlocrel field times sizeof"
579 "(struct relocation_info) of LC_DYSYMTAB command " +
580 Twine(LoadCommandIndex
) + " extends past the end of "
582 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.locreloff
,
584 sizeof(MachO::relocation_info
),
585 "local relocation table"))
587 *DysymtabLoadCmd
= Load
.Ptr
;
588 return Error::success();
591 static Error
checkLinkeditDataCommand(const MachOObjectFile
&Obj
,
592 const MachOObjectFile::LoadCommandInfo
&Load
,
593 uint32_t LoadCommandIndex
,
594 const char **LoadCmd
, const char *CmdName
,
595 std::list
<MachOElement
> &Elements
,
596 const char *ElementName
) {
597 if (Load
.C
.cmdsize
< sizeof(MachO::linkedit_data_command
))
598 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
599 CmdName
+ " cmdsize too small");
600 if (*LoadCmd
!= nullptr)
601 return malformedError("more than one " + Twine(CmdName
) + " command");
602 auto LinkDataOrError
=
603 getStructOrErr
<MachO::linkedit_data_command
>(Obj
, Load
.Ptr
);
604 if (!LinkDataOrError
)
605 return LinkDataOrError
.takeError();
606 MachO::linkedit_data_command LinkData
= LinkDataOrError
.get();
607 if (LinkData
.cmdsize
!= sizeof(MachO::linkedit_data_command
))
608 return malformedError(Twine(CmdName
) + " command " +
609 Twine(LoadCommandIndex
) + " has incorrect cmdsize");
610 uint64_t FileSize
= Obj
.getData().size();
611 if (LinkData
.dataoff
> FileSize
)
612 return malformedError("dataoff field of " + Twine(CmdName
) + " command " +
613 Twine(LoadCommandIndex
) + " extends past the end of "
615 uint64_t BigSize
= LinkData
.dataoff
;
616 BigSize
+= LinkData
.datasize
;
617 if (BigSize
> FileSize
)
618 return malformedError("dataoff field plus datasize field of " +
619 Twine(CmdName
) + " command " +
620 Twine(LoadCommandIndex
) + " extends past the end of "
622 if (Error Err
= checkOverlappingElement(Elements
, LinkData
.dataoff
,
623 LinkData
.datasize
, ElementName
))
626 return Error::success();
629 static Error
checkDyldInfoCommand(const MachOObjectFile
&Obj
,
630 const MachOObjectFile::LoadCommandInfo
&Load
,
631 uint32_t LoadCommandIndex
,
632 const char **LoadCmd
, const char *CmdName
,
633 std::list
<MachOElement
> &Elements
) {
634 if (Load
.C
.cmdsize
< sizeof(MachO::dyld_info_command
))
635 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
636 CmdName
+ " cmdsize too small");
637 if (*LoadCmd
!= nullptr)
638 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
641 getStructOrErr
<MachO::dyld_info_command
>(Obj
, Load
.Ptr
);
643 return DyldInfoOrErr
.takeError();
644 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
645 if (DyldInfo
.cmdsize
!= sizeof(MachO::dyld_info_command
))
646 return malformedError(Twine(CmdName
) + " command " +
647 Twine(LoadCommandIndex
) + " has incorrect cmdsize");
648 uint64_t FileSize
= Obj
.getData().size();
649 if (DyldInfo
.rebase_off
> FileSize
)
650 return malformedError("rebase_off field of " + Twine(CmdName
) +
651 " command " + Twine(LoadCommandIndex
) + " extends "
652 "past the end of the file");
653 uint64_t BigSize
= DyldInfo
.rebase_off
;
654 BigSize
+= DyldInfo
.rebase_size
;
655 if (BigSize
> FileSize
)
656 return malformedError("rebase_off field plus rebase_size field of " +
657 Twine(CmdName
) + " command " +
658 Twine(LoadCommandIndex
) + " extends past the end of "
660 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.rebase_off
,
661 DyldInfo
.rebase_size
,
664 if (DyldInfo
.bind_off
> FileSize
)
665 return malformedError("bind_off field of " + Twine(CmdName
) +
666 " command " + Twine(LoadCommandIndex
) + " extends "
667 "past the end of the file");
668 BigSize
= DyldInfo
.bind_off
;
669 BigSize
+= DyldInfo
.bind_size
;
670 if (BigSize
> FileSize
)
671 return malformedError("bind_off field plus bind_size field of " +
672 Twine(CmdName
) + " command " +
673 Twine(LoadCommandIndex
) + " extends past the end of "
675 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.bind_off
,
679 if (DyldInfo
.weak_bind_off
> FileSize
)
680 return malformedError("weak_bind_off field of " + Twine(CmdName
) +
681 " command " + Twine(LoadCommandIndex
) + " extends "
682 "past the end of the file");
683 BigSize
= DyldInfo
.weak_bind_off
;
684 BigSize
+= DyldInfo
.weak_bind_size
;
685 if (BigSize
> FileSize
)
686 return malformedError("weak_bind_off field plus weak_bind_size field of " +
687 Twine(CmdName
) + " command " +
688 Twine(LoadCommandIndex
) + " extends past the end of "
690 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.weak_bind_off
,
691 DyldInfo
.weak_bind_size
,
692 "dyld weak bind info"))
694 if (DyldInfo
.lazy_bind_off
> FileSize
)
695 return malformedError("lazy_bind_off field of " + Twine(CmdName
) +
696 " command " + Twine(LoadCommandIndex
) + " extends "
697 "past the end of the file");
698 BigSize
= DyldInfo
.lazy_bind_off
;
699 BigSize
+= DyldInfo
.lazy_bind_size
;
700 if (BigSize
> FileSize
)
701 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
702 Twine(CmdName
) + " command " +
703 Twine(LoadCommandIndex
) + " extends past the end of "
705 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.lazy_bind_off
,
706 DyldInfo
.lazy_bind_size
,
707 "dyld lazy bind info"))
709 if (DyldInfo
.export_off
> FileSize
)
710 return malformedError("export_off field of " + Twine(CmdName
) +
711 " command " + Twine(LoadCommandIndex
) + " extends "
712 "past the end of the file");
713 BigSize
= DyldInfo
.export_off
;
714 BigSize
+= DyldInfo
.export_size
;
715 if (BigSize
> FileSize
)
716 return malformedError("export_off field plus export_size field of " +
717 Twine(CmdName
) + " command " +
718 Twine(LoadCommandIndex
) + " extends past the end of "
720 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.export_off
,
721 DyldInfo
.export_size
,
725 return Error::success();
728 static Error
checkDylibCommand(const MachOObjectFile
&Obj
,
729 const MachOObjectFile::LoadCommandInfo
&Load
,
730 uint32_t LoadCommandIndex
, const char *CmdName
) {
731 if (Load
.C
.cmdsize
< sizeof(MachO::dylib_command
))
732 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
733 CmdName
+ " cmdsize too small");
734 auto CommandOrErr
= getStructOrErr
<MachO::dylib_command
>(Obj
, Load
.Ptr
);
736 return CommandOrErr
.takeError();
737 MachO::dylib_command D
= CommandOrErr
.get();
738 if (D
.dylib
.name
< sizeof(MachO::dylib_command
))
739 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
740 CmdName
+ " name.offset field too small, not past "
741 "the end of the dylib_command struct");
742 if (D
.dylib
.name
>= D
.cmdsize
)
743 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
744 CmdName
+ " name.offset field extends past the end "
745 "of the load command");
746 // Make sure there is a null between the starting offset of the name and
747 // the end of the load command.
749 const char *P
= (const char *)Load
.Ptr
;
750 for (i
= D
.dylib
.name
; i
< D
.cmdsize
; i
++)
754 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
755 CmdName
+ " library name extends past the end of the "
757 return Error::success();
760 static Error
checkDylibIdCommand(const MachOObjectFile
&Obj
,
761 const MachOObjectFile::LoadCommandInfo
&Load
,
762 uint32_t LoadCommandIndex
,
763 const char **LoadCmd
) {
764 if (Error Err
= checkDylibCommand(Obj
, Load
, LoadCommandIndex
,
767 if (*LoadCmd
!= nullptr)
768 return malformedError("more than one LC_ID_DYLIB command");
769 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB
&&
770 Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
)
771 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
774 return Error::success();
777 static Error
checkDyldCommand(const MachOObjectFile
&Obj
,
778 const MachOObjectFile::LoadCommandInfo
&Load
,
779 uint32_t LoadCommandIndex
, const char *CmdName
) {
780 if (Load
.C
.cmdsize
< sizeof(MachO::dylinker_command
))
781 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
782 CmdName
+ " cmdsize too small");
783 auto CommandOrErr
= getStructOrErr
<MachO::dylinker_command
>(Obj
, Load
.Ptr
);
785 return CommandOrErr
.takeError();
786 MachO::dylinker_command D
= CommandOrErr
.get();
787 if (D
.name
< sizeof(MachO::dylinker_command
))
788 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
789 CmdName
+ " name.offset field too small, not past "
790 "the end of the dylinker_command struct");
791 if (D
.name
>= D
.cmdsize
)
792 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
793 CmdName
+ " name.offset field extends past the end "
794 "of the load command");
795 // Make sure there is a null between the starting offset of the name and
796 // the end of the load command.
798 const char *P
= (const char *)Load
.Ptr
;
799 for (i
= D
.name
; i
< D
.cmdsize
; i
++)
803 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
804 CmdName
+ " dyld name extends past the end of the "
806 return Error::success();
809 static Error
checkVersCommand(const MachOObjectFile
&Obj
,
810 const MachOObjectFile::LoadCommandInfo
&Load
,
811 uint32_t LoadCommandIndex
,
812 const char **LoadCmd
, const char *CmdName
) {
813 if (Load
.C
.cmdsize
!= sizeof(MachO::version_min_command
))
814 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
815 CmdName
+ " has incorrect cmdsize");
816 if (*LoadCmd
!= nullptr)
817 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
818 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
819 "LC_VERSION_MIN_WATCHOS command");
821 return Error::success();
824 static Error
checkNoteCommand(const MachOObjectFile
&Obj
,
825 const MachOObjectFile::LoadCommandInfo
&Load
,
826 uint32_t LoadCommandIndex
,
827 std::list
<MachOElement
> &Elements
) {
828 if (Load
.C
.cmdsize
!= sizeof(MachO::note_command
))
829 return malformedError("load command " + Twine(LoadCommandIndex
) +
830 " LC_NOTE has incorrect cmdsize");
831 auto NoteCmdOrErr
= getStructOrErr
<MachO::note_command
>(Obj
, Load
.Ptr
);
833 return NoteCmdOrErr
.takeError();
834 MachO::note_command Nt
= NoteCmdOrErr
.get();
835 uint64_t FileSize
= Obj
.getData().size();
836 if (Nt
.offset
> FileSize
)
837 return malformedError("offset field of LC_NOTE command " +
838 Twine(LoadCommandIndex
) + " extends "
839 "past the end of the file");
840 uint64_t BigSize
= Nt
.offset
;
842 if (BigSize
> FileSize
)
843 return malformedError("size field plus offset field of LC_NOTE command " +
844 Twine(LoadCommandIndex
) + " extends past the end of "
846 if (Error Err
= checkOverlappingElement(Elements
, Nt
.offset
, Nt
.size
,
849 return Error::success();
853 parseBuildVersionCommand(const MachOObjectFile
&Obj
,
854 const MachOObjectFile::LoadCommandInfo
&Load
,
855 SmallVectorImpl
<const char*> &BuildTools
,
856 uint32_t LoadCommandIndex
) {
858 getStructOrErr
<MachO::build_version_command
>(Obj
, Load
.Ptr
);
860 return BVCOrErr
.takeError();
861 MachO::build_version_command BVC
= BVCOrErr
.get();
862 if (Load
.C
.cmdsize
!=
863 sizeof(MachO::build_version_command
) +
864 BVC
.ntools
* sizeof(MachO::build_tool_version
))
865 return malformedError("load command " + Twine(LoadCommandIndex
) +
866 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
868 auto Start
= Load
.Ptr
+ sizeof(MachO::build_version_command
);
869 BuildTools
.resize(BVC
.ntools
);
870 for (unsigned i
= 0; i
< BVC
.ntools
; ++i
)
871 BuildTools
[i
] = Start
+ i
* sizeof(MachO::build_tool_version
);
873 return Error::success();
876 static Error
checkRpathCommand(const MachOObjectFile
&Obj
,
877 const MachOObjectFile::LoadCommandInfo
&Load
,
878 uint32_t LoadCommandIndex
) {
879 if (Load
.C
.cmdsize
< sizeof(MachO::rpath_command
))
880 return malformedError("load command " + Twine(LoadCommandIndex
) +
881 " LC_RPATH cmdsize too small");
882 auto ROrErr
= getStructOrErr
<MachO::rpath_command
>(Obj
, Load
.Ptr
);
884 return ROrErr
.takeError();
885 MachO::rpath_command R
= ROrErr
.get();
886 if (R
.path
< sizeof(MachO::rpath_command
))
887 return malformedError("load command " + Twine(LoadCommandIndex
) +
888 " LC_RPATH path.offset field too small, not past "
889 "the end of the rpath_command struct");
890 if (R
.path
>= R
.cmdsize
)
891 return malformedError("load command " + Twine(LoadCommandIndex
) +
892 " LC_RPATH path.offset field extends past the end "
893 "of the load command");
894 // Make sure there is a null between the starting offset of the path and
895 // the end of the load command.
897 const char *P
= (const char *)Load
.Ptr
;
898 for (i
= R
.path
; i
< R
.cmdsize
; i
++)
902 return malformedError("load command " + Twine(LoadCommandIndex
) +
903 " LC_RPATH library name extends past the end of the "
905 return Error::success();
908 static Error
checkEncryptCommand(const MachOObjectFile
&Obj
,
909 const MachOObjectFile::LoadCommandInfo
&Load
,
910 uint32_t LoadCommandIndex
,
911 uint64_t cryptoff
, uint64_t cryptsize
,
912 const char **LoadCmd
, const char *CmdName
) {
913 if (*LoadCmd
!= nullptr)
914 return malformedError("more than one LC_ENCRYPTION_INFO and or "
915 "LC_ENCRYPTION_INFO_64 command");
916 uint64_t FileSize
= Obj
.getData().size();
917 if (cryptoff
> FileSize
)
918 return malformedError("cryptoff field of " + Twine(CmdName
) +
919 " command " + Twine(LoadCommandIndex
) + " extends "
920 "past the end of the file");
921 uint64_t BigSize
= cryptoff
;
922 BigSize
+= cryptsize
;
923 if (BigSize
> FileSize
)
924 return malformedError("cryptoff field plus cryptsize field of " +
925 Twine(CmdName
) + " command " +
926 Twine(LoadCommandIndex
) + " extends past the end of "
929 return Error::success();
932 static Error
checkLinkerOptCommand(const MachOObjectFile
&Obj
,
933 const MachOObjectFile::LoadCommandInfo
&Load
,
934 uint32_t LoadCommandIndex
) {
935 if (Load
.C
.cmdsize
< sizeof(MachO::linker_option_command
))
936 return malformedError("load command " + Twine(LoadCommandIndex
) +
937 " LC_LINKER_OPTION cmdsize too small");
938 auto LinkOptionOrErr
=
939 getStructOrErr
<MachO::linker_option_command
>(Obj
, Load
.Ptr
);
940 if (!LinkOptionOrErr
)
941 return LinkOptionOrErr
.takeError();
942 MachO::linker_option_command L
= LinkOptionOrErr
.get();
943 // Make sure the count of strings is correct.
944 const char *string
= (const char *)Load
.Ptr
+
945 sizeof(struct MachO::linker_option_command
);
946 uint32_t left
= L
.cmdsize
- sizeof(struct MachO::linker_option_command
);
949 while (*string
== '\0' && left
> 0) {
955 uint32_t NullPos
= StringRef(string
, left
).find('\0');
956 if (0xffffffff == NullPos
)
957 return malformedError("load command " + Twine(LoadCommandIndex
) +
958 " LC_LINKER_OPTION string #" + Twine(i
) +
959 " is not NULL terminated");
960 uint32_t len
= std::min(NullPos
, left
) + 1;
966 return malformedError("load command " + Twine(LoadCommandIndex
) +
967 " LC_LINKER_OPTION string count " + Twine(L
.count
) +
968 " does not match number of strings");
969 return Error::success();
972 static Error
checkSubCommand(const MachOObjectFile
&Obj
,
973 const MachOObjectFile::LoadCommandInfo
&Load
,
974 uint32_t LoadCommandIndex
, const char *CmdName
,
975 size_t SizeOfCmd
, const char *CmdStructName
,
976 uint32_t PathOffset
, const char *PathFieldName
) {
977 if (PathOffset
< SizeOfCmd
)
978 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
979 CmdName
+ " " + PathFieldName
+ ".offset field too "
980 "small, not past the end of the " + CmdStructName
);
981 if (PathOffset
>= Load
.C
.cmdsize
)
982 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
983 CmdName
+ " " + PathFieldName
+ ".offset field "
984 "extends past the end of the load command");
985 // Make sure there is a null between the starting offset of the path and
986 // the end of the load command.
988 const char *P
= (const char *)Load
.Ptr
;
989 for (i
= PathOffset
; i
< Load
.C
.cmdsize
; i
++)
992 if (i
>= Load
.C
.cmdsize
)
993 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
994 CmdName
+ " " + PathFieldName
+ " name extends past "
995 "the end of the load command");
996 return Error::success();
999 static Error
checkThreadCommand(const MachOObjectFile
&Obj
,
1000 const MachOObjectFile::LoadCommandInfo
&Load
,
1001 uint32_t LoadCommandIndex
,
1002 const char *CmdName
) {
1003 if (Load
.C
.cmdsize
< sizeof(MachO::thread_command
))
1004 return malformedError("load command " + Twine(LoadCommandIndex
) +
1005 CmdName
+ " cmdsize too small");
1006 auto ThreadCommandOrErr
=
1007 getStructOrErr
<MachO::thread_command
>(Obj
, Load
.Ptr
);
1008 if (!ThreadCommandOrErr
)
1009 return ThreadCommandOrErr
.takeError();
1010 MachO::thread_command T
= ThreadCommandOrErr
.get();
1011 const char *state
= Load
.Ptr
+ sizeof(MachO::thread_command
);
1012 const char *end
= Load
.Ptr
+ T
.cmdsize
;
1013 uint32_t nflavor
= 0;
1014 uint32_t cputype
= getCPUType(Obj
);
1015 while (state
< end
) {
1016 if(state
+ sizeof(uint32_t) > end
)
1017 return malformedError("load command " + Twine(LoadCommandIndex
) +
1018 "flavor in " + CmdName
+ " extends past end of "
1021 memcpy(&flavor
, state
, sizeof(uint32_t));
1022 if (Obj
.isLittleEndian() != sys::IsLittleEndianHost
)
1023 sys::swapByteOrder(flavor
);
1024 state
+= sizeof(uint32_t);
1026 if(state
+ sizeof(uint32_t) > end
)
1027 return malformedError("load command " + Twine(LoadCommandIndex
) +
1028 " count in " + CmdName
+ " extends past end of "
1031 memcpy(&count
, state
, sizeof(uint32_t));
1032 if (Obj
.isLittleEndian() != sys::IsLittleEndianHost
)
1033 sys::swapByteOrder(count
);
1034 state
+= sizeof(uint32_t);
1036 if (cputype
== MachO::CPU_TYPE_I386
) {
1037 if (flavor
== MachO::x86_THREAD_STATE32
) {
1038 if (count
!= MachO::x86_THREAD_STATE32_COUNT
)
1039 return malformedError("load command " + Twine(LoadCommandIndex
) +
1040 " count not x86_THREAD_STATE32_COUNT for "
1041 "flavor number " + Twine(nflavor
) + " which is "
1042 "a x86_THREAD_STATE32 flavor in " + CmdName
+
1044 if (state
+ sizeof(MachO::x86_thread_state32_t
) > end
)
1045 return malformedError("load command " + Twine(LoadCommandIndex
) +
1046 " x86_THREAD_STATE32 extends past end of "
1047 "command in " + CmdName
+ " command");
1048 state
+= sizeof(MachO::x86_thread_state32_t
);
1050 return malformedError("load command " + Twine(LoadCommandIndex
) +
1051 " unknown flavor (" + Twine(flavor
) + ") for "
1052 "flavor number " + Twine(nflavor
) + " in " +
1053 CmdName
+ " command");
1055 } else if (cputype
== MachO::CPU_TYPE_X86_64
) {
1056 if (flavor
== MachO::x86_THREAD_STATE
) {
1057 if (count
!= MachO::x86_THREAD_STATE_COUNT
)
1058 return malformedError("load command " + Twine(LoadCommandIndex
) +
1059 " count not x86_THREAD_STATE_COUNT for "
1060 "flavor number " + Twine(nflavor
) + " which is "
1061 "a x86_THREAD_STATE flavor in " + CmdName
+
1063 if (state
+ sizeof(MachO::x86_thread_state_t
) > end
)
1064 return malformedError("load command " + Twine(LoadCommandIndex
) +
1065 " x86_THREAD_STATE extends past end of "
1066 "command in " + CmdName
+ " command");
1067 state
+= sizeof(MachO::x86_thread_state_t
);
1068 } else if (flavor
== MachO::x86_FLOAT_STATE
) {
1069 if (count
!= MachO::x86_FLOAT_STATE_COUNT
)
1070 return malformedError("load command " + Twine(LoadCommandIndex
) +
1071 " count not x86_FLOAT_STATE_COUNT for "
1072 "flavor number " + Twine(nflavor
) + " which is "
1073 "a x86_FLOAT_STATE flavor in " + CmdName
+
1075 if (state
+ sizeof(MachO::x86_float_state_t
) > end
)
1076 return malformedError("load command " + Twine(LoadCommandIndex
) +
1077 " x86_FLOAT_STATE extends past end of "
1078 "command in " + CmdName
+ " command");
1079 state
+= sizeof(MachO::x86_float_state_t
);
1080 } else if (flavor
== MachO::x86_EXCEPTION_STATE
) {
1081 if (count
!= MachO::x86_EXCEPTION_STATE_COUNT
)
1082 return malformedError("load command " + Twine(LoadCommandIndex
) +
1083 " count not x86_EXCEPTION_STATE_COUNT for "
1084 "flavor number " + Twine(nflavor
) + " which is "
1085 "a x86_EXCEPTION_STATE flavor in " + CmdName
+
1087 if (state
+ sizeof(MachO::x86_exception_state_t
) > end
)
1088 return malformedError("load command " + Twine(LoadCommandIndex
) +
1089 " x86_EXCEPTION_STATE extends past end of "
1090 "command in " + CmdName
+ " command");
1091 state
+= sizeof(MachO::x86_exception_state_t
);
1092 } else if (flavor
== MachO::x86_THREAD_STATE64
) {
1093 if (count
!= MachO::x86_THREAD_STATE64_COUNT
)
1094 return malformedError("load command " + Twine(LoadCommandIndex
) +
1095 " count not x86_THREAD_STATE64_COUNT for "
1096 "flavor number " + Twine(nflavor
) + " which is "
1097 "a x86_THREAD_STATE64 flavor in " + CmdName
+
1099 if (state
+ sizeof(MachO::x86_thread_state64_t
) > end
)
1100 return malformedError("load command " + Twine(LoadCommandIndex
) +
1101 " x86_THREAD_STATE64 extends past end of "
1102 "command in " + CmdName
+ " command");
1103 state
+= sizeof(MachO::x86_thread_state64_t
);
1104 } else if (flavor
== MachO::x86_EXCEPTION_STATE64
) {
1105 if (count
!= MachO::x86_EXCEPTION_STATE64_COUNT
)
1106 return malformedError("load command " + Twine(LoadCommandIndex
) +
1107 " count not x86_EXCEPTION_STATE64_COUNT for "
1108 "flavor number " + Twine(nflavor
) + " which is "
1109 "a x86_EXCEPTION_STATE64 flavor in " + CmdName
+
1111 if (state
+ sizeof(MachO::x86_exception_state64_t
) > end
)
1112 return malformedError("load command " + Twine(LoadCommandIndex
) +
1113 " x86_EXCEPTION_STATE64 extends past end of "
1114 "command in " + CmdName
+ " command");
1115 state
+= sizeof(MachO::x86_exception_state64_t
);
1117 return malformedError("load command " + Twine(LoadCommandIndex
) +
1118 " unknown flavor (" + Twine(flavor
) + ") for "
1119 "flavor number " + Twine(nflavor
) + " in " +
1120 CmdName
+ " command");
1122 } else if (cputype
== MachO::CPU_TYPE_ARM
) {
1123 if (flavor
== MachO::ARM_THREAD_STATE
) {
1124 if (count
!= MachO::ARM_THREAD_STATE_COUNT
)
1125 return malformedError("load command " + Twine(LoadCommandIndex
) +
1126 " count not ARM_THREAD_STATE_COUNT for "
1127 "flavor number " + Twine(nflavor
) + " which is "
1128 "a ARM_THREAD_STATE flavor in " + CmdName
+
1130 if (state
+ sizeof(MachO::arm_thread_state32_t
) > end
)
1131 return malformedError("load command " + Twine(LoadCommandIndex
) +
1132 " ARM_THREAD_STATE extends past end of "
1133 "command in " + CmdName
+ " command");
1134 state
+= sizeof(MachO::arm_thread_state32_t
);
1136 return malformedError("load command " + Twine(LoadCommandIndex
) +
1137 " unknown flavor (" + Twine(flavor
) + ") for "
1138 "flavor number " + Twine(nflavor
) + " in " +
1139 CmdName
+ " command");
1141 } else if (cputype
== MachO::CPU_TYPE_ARM64
||
1142 cputype
== MachO::CPU_TYPE_ARM64_32
) {
1143 if (flavor
== MachO::ARM_THREAD_STATE64
) {
1144 if (count
!= MachO::ARM_THREAD_STATE64_COUNT
)
1145 return malformedError("load command " + Twine(LoadCommandIndex
) +
1146 " count not ARM_THREAD_STATE64_COUNT for "
1147 "flavor number " + Twine(nflavor
) + " which is "
1148 "a ARM_THREAD_STATE64 flavor in " + CmdName
+
1150 if (state
+ sizeof(MachO::arm_thread_state64_t
) > end
)
1151 return malformedError("load command " + Twine(LoadCommandIndex
) +
1152 " ARM_THREAD_STATE64 extends past end of "
1153 "command in " + CmdName
+ " command");
1154 state
+= sizeof(MachO::arm_thread_state64_t
);
1156 return malformedError("load command " + Twine(LoadCommandIndex
) +
1157 " unknown flavor (" + Twine(flavor
) + ") for "
1158 "flavor number " + Twine(nflavor
) + " in " +
1159 CmdName
+ " command");
1161 } else if (cputype
== MachO::CPU_TYPE_POWERPC
) {
1162 if (flavor
== MachO::PPC_THREAD_STATE
) {
1163 if (count
!= MachO::PPC_THREAD_STATE_COUNT
)
1164 return malformedError("load command " + Twine(LoadCommandIndex
) +
1165 " count not PPC_THREAD_STATE_COUNT for "
1166 "flavor number " + Twine(nflavor
) + " which is "
1167 "a PPC_THREAD_STATE flavor in " + CmdName
+
1169 if (state
+ sizeof(MachO::ppc_thread_state32_t
) > end
)
1170 return malformedError("load command " + Twine(LoadCommandIndex
) +
1171 " PPC_THREAD_STATE extends past end of "
1172 "command in " + CmdName
+ " command");
1173 state
+= sizeof(MachO::ppc_thread_state32_t
);
1175 return malformedError("load command " + Twine(LoadCommandIndex
) +
1176 " unknown flavor (" + Twine(flavor
) + ") for "
1177 "flavor number " + Twine(nflavor
) + " in " +
1178 CmdName
+ " command");
1181 return malformedError("unknown cputype (" + Twine(cputype
) + ") load "
1182 "command " + Twine(LoadCommandIndex
) + " for " +
1183 CmdName
+ " command can't be checked");
1187 return Error::success();
1190 static Error
checkTwoLevelHintsCommand(const MachOObjectFile
&Obj
,
1191 const MachOObjectFile::LoadCommandInfo
1193 uint32_t LoadCommandIndex
,
1194 const char **LoadCmd
,
1195 std::list
<MachOElement
> &Elements
) {
1196 if (Load
.C
.cmdsize
!= sizeof(MachO::twolevel_hints_command
))
1197 return malformedError("load command " + Twine(LoadCommandIndex
) +
1198 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1199 if (*LoadCmd
!= nullptr)
1200 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1201 auto HintsOrErr
= getStructOrErr
<MachO::twolevel_hints_command
>(Obj
, Load
.Ptr
);
1203 return HintsOrErr
.takeError();
1204 MachO::twolevel_hints_command Hints
= HintsOrErr
.get();
1205 uint64_t FileSize
= Obj
.getData().size();
1206 if (Hints
.offset
> FileSize
)
1207 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1208 Twine(LoadCommandIndex
) + " extends past the end of "
1210 uint64_t BigSize
= Hints
.nhints
;
1211 BigSize
*= sizeof(MachO::twolevel_hint
);
1212 BigSize
+= Hints
.offset
;
1213 if (BigSize
> FileSize
)
1214 return malformedError("offset field plus nhints times sizeof(struct "
1215 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1216 Twine(LoadCommandIndex
) + " extends past the end of "
1218 if (Error Err
= checkOverlappingElement(Elements
, Hints
.offset
, Hints
.nhints
*
1219 sizeof(MachO::twolevel_hint
),
1222 *LoadCmd
= Load
.Ptr
;
1223 return Error::success();
1226 // Returns true if the libObject code does not support the load command and its
1227 // contents. The cmd value it is treated as an unknown load command but with
1228 // an error message that says the cmd value is obsolete.
1229 static bool isLoadCommandObsolete(uint32_t cmd
) {
1230 if (cmd
== MachO::LC_SYMSEG
||
1231 cmd
== MachO::LC_LOADFVMLIB
||
1232 cmd
== MachO::LC_IDFVMLIB
||
1233 cmd
== MachO::LC_IDENT
||
1234 cmd
== MachO::LC_FVMFILE
||
1235 cmd
== MachO::LC_PREPAGE
||
1236 cmd
== MachO::LC_PREBOUND_DYLIB
||
1237 cmd
== MachO::LC_TWOLEVEL_HINTS
||
1238 cmd
== MachO::LC_PREBIND_CKSUM
)
1243 Expected
<std::unique_ptr
<MachOObjectFile
>>
1244 MachOObjectFile::create(MemoryBufferRef Object
, bool IsLittleEndian
,
1245 bool Is64Bits
, uint32_t UniversalCputype
,
1246 uint32_t UniversalIndex
) {
1247 Error Err
= Error::success();
1248 std::unique_ptr
<MachOObjectFile
> Obj(
1249 new MachOObjectFile(std::move(Object
), IsLittleEndian
,
1250 Is64Bits
, Err
, UniversalCputype
,
1253 return std::move(Err
);
1254 return std::move(Obj
);
1257 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object
, bool IsLittleEndian
,
1258 bool Is64bits
, Error
&Err
,
1259 uint32_t UniversalCputype
,
1260 uint32_t UniversalIndex
)
1261 : ObjectFile(getMachOType(IsLittleEndian
, Is64bits
), Object
) {
1262 ErrorAsOutParameter
ErrAsOutParam(&Err
);
1263 uint64_t SizeOfHeaders
;
1266 parseHeader(*this, Header64
, Err
);
1267 SizeOfHeaders
= sizeof(MachO::mach_header_64
);
1268 cputype
= Header64
.cputype
;
1270 parseHeader(*this, Header
, Err
);
1271 SizeOfHeaders
= sizeof(MachO::mach_header
);
1272 cputype
= Header
.cputype
;
1276 SizeOfHeaders
+= getHeader().sizeofcmds
;
1277 if (getData().data() + SizeOfHeaders
> getData().end()) {
1278 Err
= malformedError("load commands extend past the end of the file");
1281 if (UniversalCputype
!= 0 && cputype
!= UniversalCputype
) {
1282 Err
= malformedError("universal header architecture: " +
1283 Twine(UniversalIndex
) + "'s cputype does not match "
1284 "object file's mach header");
1287 std::list
<MachOElement
> Elements
;
1288 Elements
.push_back({0, SizeOfHeaders
, "Mach-O headers"});
1290 uint32_t LoadCommandCount
= getHeader().ncmds
;
1291 LoadCommandInfo Load
;
1292 if (LoadCommandCount
!= 0) {
1293 if (auto LoadOrErr
= getFirstLoadCommandInfo(*this))
1296 Err
= LoadOrErr
.takeError();
1301 const char *DyldIdLoadCmd
= nullptr;
1302 const char *FuncStartsLoadCmd
= nullptr;
1303 const char *SplitInfoLoadCmd
= nullptr;
1304 const char *CodeSignDrsLoadCmd
= nullptr;
1305 const char *CodeSignLoadCmd
= nullptr;
1306 const char *VersLoadCmd
= nullptr;
1307 const char *SourceLoadCmd
= nullptr;
1308 const char *EntryPointLoadCmd
= nullptr;
1309 const char *EncryptLoadCmd
= nullptr;
1310 const char *RoutinesLoadCmd
= nullptr;
1311 const char *UnixThreadLoadCmd
= nullptr;
1312 const char *TwoLevelHintsLoadCmd
= nullptr;
1313 for (unsigned I
= 0; I
< LoadCommandCount
; ++I
) {
1315 if (Load
.C
.cmdsize
% 8 != 0) {
1316 // We have a hack here to allow 64-bit Mach-O core files to have
1317 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1318 // allowed since the macOS kernel produces them.
1319 if (getHeader().filetype
!= MachO::MH_CORE
||
1320 Load
.C
.cmd
!= MachO::LC_THREAD
|| Load
.C
.cmdsize
% 4) {
1321 Err
= malformedError("load command " + Twine(I
) + " cmdsize not a "
1327 if (Load
.C
.cmdsize
% 4 != 0) {
1328 Err
= malformedError("load command " + Twine(I
) + " cmdsize not a "
1333 LoadCommands
.push_back(Load
);
1334 if (Load
.C
.cmd
== MachO::LC_SYMTAB
) {
1335 if ((Err
= checkSymtabCommand(*this, Load
, I
, &SymtabLoadCmd
, Elements
)))
1337 } else if (Load
.C
.cmd
== MachO::LC_DYSYMTAB
) {
1338 if ((Err
= checkDysymtabCommand(*this, Load
, I
, &DysymtabLoadCmd
,
1341 } else if (Load
.C
.cmd
== MachO::LC_DATA_IN_CODE
) {
1342 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &DataInCodeLoadCmd
,
1343 "LC_DATA_IN_CODE", Elements
,
1344 "data in code info")))
1346 } else if (Load
.C
.cmd
== MachO::LC_LINKER_OPTIMIZATION_HINT
) {
1347 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &LinkOptHintsLoadCmd
,
1348 "LC_LINKER_OPTIMIZATION_HINT",
1349 Elements
, "linker optimization "
1352 } else if (Load
.C
.cmd
== MachO::LC_FUNCTION_STARTS
) {
1353 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &FuncStartsLoadCmd
,
1354 "LC_FUNCTION_STARTS", Elements
,
1355 "function starts data")))
1357 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT_SPLIT_INFO
) {
1358 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &SplitInfoLoadCmd
,
1359 "LC_SEGMENT_SPLIT_INFO", Elements
,
1360 "split info data")))
1362 } else if (Load
.C
.cmd
== MachO::LC_DYLIB_CODE_SIGN_DRS
) {
1363 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &CodeSignDrsLoadCmd
,
1364 "LC_DYLIB_CODE_SIGN_DRS", Elements
,
1365 "code signing RDs data")))
1367 } else if (Load
.C
.cmd
== MachO::LC_CODE_SIGNATURE
) {
1368 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &CodeSignLoadCmd
,
1369 "LC_CODE_SIGNATURE", Elements
,
1370 "code signature data")))
1372 } else if (Load
.C
.cmd
== MachO::LC_DYLD_INFO
) {
1373 if ((Err
= checkDyldInfoCommand(*this, Load
, I
, &DyldInfoLoadCmd
,
1374 "LC_DYLD_INFO", Elements
)))
1376 } else if (Load
.C
.cmd
== MachO::LC_DYLD_INFO_ONLY
) {
1377 if ((Err
= checkDyldInfoCommand(*this, Load
, I
, &DyldInfoLoadCmd
,
1378 "LC_DYLD_INFO_ONLY", Elements
)))
1380 } else if (Load
.C
.cmd
== MachO::LC_UUID
) {
1381 if (Load
.C
.cmdsize
!= sizeof(MachO::uuid_command
)) {
1382 Err
= malformedError("LC_UUID command " + Twine(I
) + " has incorrect "
1387 Err
= malformedError("more than one LC_UUID command");
1390 UuidLoadCmd
= Load
.Ptr
;
1391 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
1392 if ((Err
= parseSegmentLoadCommand
<MachO::segment_command_64
,
1394 *this, Load
, Sections
, HasPageZeroSegment
, I
,
1395 "LC_SEGMENT_64", SizeOfHeaders
, Elements
)))
1397 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
1398 if ((Err
= parseSegmentLoadCommand
<MachO::segment_command
,
1400 *this, Load
, Sections
, HasPageZeroSegment
, I
,
1401 "LC_SEGMENT", SizeOfHeaders
, Elements
)))
1403 } else if (Load
.C
.cmd
== MachO::LC_ID_DYLIB
) {
1404 if ((Err
= checkDylibIdCommand(*this, Load
, I
, &DyldIdLoadCmd
)))
1406 } else if (Load
.C
.cmd
== MachO::LC_LOAD_DYLIB
) {
1407 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_DYLIB")))
1409 Libraries
.push_back(Load
.Ptr
);
1410 } else if (Load
.C
.cmd
== MachO::LC_LOAD_WEAK_DYLIB
) {
1411 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_WEAK_DYLIB")))
1413 Libraries
.push_back(Load
.Ptr
);
1414 } else if (Load
.C
.cmd
== MachO::LC_LAZY_LOAD_DYLIB
) {
1415 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LAZY_LOAD_DYLIB")))
1417 Libraries
.push_back(Load
.Ptr
);
1418 } else if (Load
.C
.cmd
== MachO::LC_REEXPORT_DYLIB
) {
1419 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_REEXPORT_DYLIB")))
1421 Libraries
.push_back(Load
.Ptr
);
1422 } else if (Load
.C
.cmd
== MachO::LC_LOAD_UPWARD_DYLIB
) {
1423 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_UPWARD_DYLIB")))
1425 Libraries
.push_back(Load
.Ptr
);
1426 } else if (Load
.C
.cmd
== MachO::LC_ID_DYLINKER
) {
1427 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_ID_DYLINKER")))
1429 } else if (Load
.C
.cmd
== MachO::LC_LOAD_DYLINKER
) {
1430 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_LOAD_DYLINKER")))
1432 } else if (Load
.C
.cmd
== MachO::LC_DYLD_ENVIRONMENT
) {
1433 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_DYLD_ENVIRONMENT")))
1435 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_MACOSX
) {
1436 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1437 "LC_VERSION_MIN_MACOSX")))
1439 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_IPHONEOS
) {
1440 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1441 "LC_VERSION_MIN_IPHONEOS")))
1443 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_TVOS
) {
1444 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1445 "LC_VERSION_MIN_TVOS")))
1447 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_WATCHOS
) {
1448 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1449 "LC_VERSION_MIN_WATCHOS")))
1451 } else if (Load
.C
.cmd
== MachO::LC_NOTE
) {
1452 if ((Err
= checkNoteCommand(*this, Load
, I
, Elements
)))
1454 } else if (Load
.C
.cmd
== MachO::LC_BUILD_VERSION
) {
1455 if ((Err
= parseBuildVersionCommand(*this, Load
, BuildTools
, I
)))
1457 } else if (Load
.C
.cmd
== MachO::LC_RPATH
) {
1458 if ((Err
= checkRpathCommand(*this, Load
, I
)))
1460 } else if (Load
.C
.cmd
== MachO::LC_SOURCE_VERSION
) {
1461 if (Load
.C
.cmdsize
!= sizeof(MachO::source_version_command
)) {
1462 Err
= malformedError("LC_SOURCE_VERSION command " + Twine(I
) +
1463 " has incorrect cmdsize");
1466 if (SourceLoadCmd
) {
1467 Err
= malformedError("more than one LC_SOURCE_VERSION command");
1470 SourceLoadCmd
= Load
.Ptr
;
1471 } else if (Load
.C
.cmd
== MachO::LC_MAIN
) {
1472 if (Load
.C
.cmdsize
!= sizeof(MachO::entry_point_command
)) {
1473 Err
= malformedError("LC_MAIN command " + Twine(I
) +
1474 " has incorrect cmdsize");
1477 if (EntryPointLoadCmd
) {
1478 Err
= malformedError("more than one LC_MAIN command");
1481 EntryPointLoadCmd
= Load
.Ptr
;
1482 } else if (Load
.C
.cmd
== MachO::LC_ENCRYPTION_INFO
) {
1483 if (Load
.C
.cmdsize
!= sizeof(MachO::encryption_info_command
)) {
1484 Err
= malformedError("LC_ENCRYPTION_INFO command " + Twine(I
) +
1485 " has incorrect cmdsize");
1488 MachO::encryption_info_command E
=
1489 getStruct
<MachO::encryption_info_command
>(*this, Load
.Ptr
);
1490 if ((Err
= checkEncryptCommand(*this, Load
, I
, E
.cryptoff
, E
.cryptsize
,
1491 &EncryptLoadCmd
, "LC_ENCRYPTION_INFO")))
1493 } else if (Load
.C
.cmd
== MachO::LC_ENCRYPTION_INFO_64
) {
1494 if (Load
.C
.cmdsize
!= sizeof(MachO::encryption_info_command_64
)) {
1495 Err
= malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I
) +
1496 " has incorrect cmdsize");
1499 MachO::encryption_info_command_64 E
=
1500 getStruct
<MachO::encryption_info_command_64
>(*this, Load
.Ptr
);
1501 if ((Err
= checkEncryptCommand(*this, Load
, I
, E
.cryptoff
, E
.cryptsize
,
1502 &EncryptLoadCmd
, "LC_ENCRYPTION_INFO_64")))
1504 } else if (Load
.C
.cmd
== MachO::LC_LINKER_OPTION
) {
1505 if ((Err
= checkLinkerOptCommand(*this, Load
, I
)))
1507 } else if (Load
.C
.cmd
== MachO::LC_SUB_FRAMEWORK
) {
1508 if (Load
.C
.cmdsize
< sizeof(MachO::sub_framework_command
)) {
1509 Err
= malformedError("load command " + Twine(I
) +
1510 " LC_SUB_FRAMEWORK cmdsize too small");
1513 MachO::sub_framework_command S
=
1514 getStruct
<MachO::sub_framework_command
>(*this, Load
.Ptr
);
1515 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_FRAMEWORK",
1516 sizeof(MachO::sub_framework_command
),
1517 "sub_framework_command", S
.umbrella
,
1520 } else if (Load
.C
.cmd
== MachO::LC_SUB_UMBRELLA
) {
1521 if (Load
.C
.cmdsize
< sizeof(MachO::sub_umbrella_command
)) {
1522 Err
= malformedError("load command " + Twine(I
) +
1523 " LC_SUB_UMBRELLA cmdsize too small");
1526 MachO::sub_umbrella_command S
=
1527 getStruct
<MachO::sub_umbrella_command
>(*this, Load
.Ptr
);
1528 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_UMBRELLA",
1529 sizeof(MachO::sub_umbrella_command
),
1530 "sub_umbrella_command", S
.sub_umbrella
,
1533 } else if (Load
.C
.cmd
== MachO::LC_SUB_LIBRARY
) {
1534 if (Load
.C
.cmdsize
< sizeof(MachO::sub_library_command
)) {
1535 Err
= malformedError("load command " + Twine(I
) +
1536 " LC_SUB_LIBRARY cmdsize too small");
1539 MachO::sub_library_command S
=
1540 getStruct
<MachO::sub_library_command
>(*this, Load
.Ptr
);
1541 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_LIBRARY",
1542 sizeof(MachO::sub_library_command
),
1543 "sub_library_command", S
.sub_library
,
1546 } else if (Load
.C
.cmd
== MachO::LC_SUB_CLIENT
) {
1547 if (Load
.C
.cmdsize
< sizeof(MachO::sub_client_command
)) {
1548 Err
= malformedError("load command " + Twine(I
) +
1549 " LC_SUB_CLIENT cmdsize too small");
1552 MachO::sub_client_command S
=
1553 getStruct
<MachO::sub_client_command
>(*this, Load
.Ptr
);
1554 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_CLIENT",
1555 sizeof(MachO::sub_client_command
),
1556 "sub_client_command", S
.client
, "client")))
1558 } else if (Load
.C
.cmd
== MachO::LC_ROUTINES
) {
1559 if (Load
.C
.cmdsize
!= sizeof(MachO::routines_command
)) {
1560 Err
= malformedError("LC_ROUTINES command " + Twine(I
) +
1561 " has incorrect cmdsize");
1564 if (RoutinesLoadCmd
) {
1565 Err
= malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1569 RoutinesLoadCmd
= Load
.Ptr
;
1570 } else if (Load
.C
.cmd
== MachO::LC_ROUTINES_64
) {
1571 if (Load
.C
.cmdsize
!= sizeof(MachO::routines_command_64
)) {
1572 Err
= malformedError("LC_ROUTINES_64 command " + Twine(I
) +
1573 " has incorrect cmdsize");
1576 if (RoutinesLoadCmd
) {
1577 Err
= malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1581 RoutinesLoadCmd
= Load
.Ptr
;
1582 } else if (Load
.C
.cmd
== MachO::LC_UNIXTHREAD
) {
1583 if ((Err
= checkThreadCommand(*this, Load
, I
, "LC_UNIXTHREAD")))
1585 if (UnixThreadLoadCmd
) {
1586 Err
= malformedError("more than one LC_UNIXTHREAD command");
1589 UnixThreadLoadCmd
= Load
.Ptr
;
1590 } else if (Load
.C
.cmd
== MachO::LC_THREAD
) {
1591 if ((Err
= checkThreadCommand(*this, Load
, I
, "LC_THREAD")))
1593 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1594 } else if (Load
.C
.cmd
== MachO::LC_TWOLEVEL_HINTS
) {
1595 if ((Err
= checkTwoLevelHintsCommand(*this, Load
, I
,
1596 &TwoLevelHintsLoadCmd
, Elements
)))
1598 } else if (Load
.C
.cmd
== MachO::LC_IDENT
) {
1599 // Note: LC_IDENT is ignored.
1601 } else if (isLoadCommandObsolete(Load
.C
.cmd
)) {
1602 Err
= malformedError("load command " + Twine(I
) + " for cmd value of: " +
1603 Twine(Load
.C
.cmd
) + " is obsolete and not "
1607 // TODO: generate a error for unknown load commands by default. But still
1608 // need work out an approach to allow or not allow unknown values like this
1609 // as an option for some uses like lldb.
1610 if (I
< LoadCommandCount
- 1) {
1611 if (auto LoadOrErr
= getNextLoadCommandInfo(*this, I
, Load
))
1614 Err
= LoadOrErr
.takeError();
1619 if (!SymtabLoadCmd
) {
1620 if (DysymtabLoadCmd
) {
1621 Err
= malformedError("contains LC_DYSYMTAB load command without a "
1622 "LC_SYMTAB load command");
1625 } else if (DysymtabLoadCmd
) {
1626 MachO::symtab_command Symtab
=
1627 getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
1628 MachO::dysymtab_command Dysymtab
=
1629 getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
1630 if (Dysymtab
.nlocalsym
!= 0 && Dysymtab
.ilocalsym
> Symtab
.nsyms
) {
1631 Err
= malformedError("ilocalsym in LC_DYSYMTAB load command "
1632 "extends past the end of the symbol table");
1635 uint64_t BigSize
= Dysymtab
.ilocalsym
;
1636 BigSize
+= Dysymtab
.nlocalsym
;
1637 if (Dysymtab
.nlocalsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1638 Err
= malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1639 "command extends past the end of the symbol table");
1642 if (Dysymtab
.nextdefsym
!= 0 && Dysymtab
.iextdefsym
> Symtab
.nsyms
) {
1643 Err
= malformedError("iextdefsym in LC_DYSYMTAB load command "
1644 "extends past the end of the symbol table");
1647 BigSize
= Dysymtab
.iextdefsym
;
1648 BigSize
+= Dysymtab
.nextdefsym
;
1649 if (Dysymtab
.nextdefsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1650 Err
= malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1651 "load command extends past the end of the symbol "
1655 if (Dysymtab
.nundefsym
!= 0 && Dysymtab
.iundefsym
> Symtab
.nsyms
) {
1656 Err
= malformedError("iundefsym in LC_DYSYMTAB load command "
1657 "extends past the end of the symbol table");
1660 BigSize
= Dysymtab
.iundefsym
;
1661 BigSize
+= Dysymtab
.nundefsym
;
1662 if (Dysymtab
.nundefsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1663 Err
= malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1664 " command extends past the end of the symbol table");
1668 if ((getHeader().filetype
== MachO::MH_DYLIB
||
1669 getHeader().filetype
== MachO::MH_DYLIB_STUB
) &&
1670 DyldIdLoadCmd
== nullptr) {
1671 Err
= malformedError("no LC_ID_DYLIB load command in dynamic library "
1675 assert(LoadCommands
.size() == LoadCommandCount
);
1677 Err
= Error::success();
1680 Error
MachOObjectFile::checkSymbolTable() const {
1683 MachO::mach_header_64 H_64
= MachOObjectFile::getHeader64();
1686 MachO::mach_header H
= MachOObjectFile::getHeader();
1693 uint64_t NValue
= 0;
1694 uint32_t SymbolIndex
= 0;
1695 MachO::symtab_command S
= getSymtabLoadCommand();
1696 for (const SymbolRef
&Symbol
: symbols()) {
1697 DataRefImpl SymDRI
= Symbol
.getRawDataRefImpl();
1699 MachO::nlist_64 STE_64
= getSymbol64TableEntry(SymDRI
);
1700 NType
= STE_64
.n_type
;
1701 NSect
= STE_64
.n_sect
;
1702 NDesc
= STE_64
.n_desc
;
1703 NStrx
= STE_64
.n_strx
;
1704 NValue
= STE_64
.n_value
;
1706 MachO::nlist STE
= getSymbolTableEntry(SymDRI
);
1711 NValue
= STE
.n_value
;
1713 if ((NType
& MachO::N_STAB
) == 0) {
1714 if ((NType
& MachO::N_TYPE
) == MachO::N_SECT
) {
1715 if (NSect
== 0 || NSect
> Sections
.size())
1716 return malformedError("bad section index: " + Twine((int)NSect
) +
1717 " for symbol at index " + Twine(SymbolIndex
));
1719 if ((NType
& MachO::N_TYPE
) == MachO::N_INDR
) {
1720 if (NValue
>= S
.strsize
)
1721 return malformedError("bad n_value: " + Twine((int)NValue
) + " past "
1722 "the end of string table, for N_INDR symbol at "
1723 "index " + Twine(SymbolIndex
));
1725 if ((Flags
& MachO::MH_TWOLEVEL
) == MachO::MH_TWOLEVEL
&&
1726 (((NType
& MachO::N_TYPE
) == MachO::N_UNDF
&& NValue
== 0) ||
1727 (NType
& MachO::N_TYPE
) == MachO::N_PBUD
)) {
1728 uint32_t LibraryOrdinal
= MachO::GET_LIBRARY_ORDINAL(NDesc
);
1729 if (LibraryOrdinal
!= 0 &&
1730 LibraryOrdinal
!= MachO::EXECUTABLE_ORDINAL
&&
1731 LibraryOrdinal
!= MachO::DYNAMIC_LOOKUP_ORDINAL
&&
1732 LibraryOrdinal
- 1 >= Libraries
.size() ) {
1733 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal
) +
1734 " for symbol at index " + Twine(SymbolIndex
));
1738 if (NStrx
>= S
.strsize
)
1739 return malformedError("bad string table index: " + Twine((int)NStrx
) +
1740 " past the end of string table, for symbol at "
1741 "index " + Twine(SymbolIndex
));
1744 return Error::success();
1747 void MachOObjectFile::moveSymbolNext(DataRefImpl
&Symb
) const {
1748 unsigned SymbolTableEntrySize
= is64Bit() ?
1749 sizeof(MachO::nlist_64
) :
1750 sizeof(MachO::nlist
);
1751 Symb
.p
+= SymbolTableEntrySize
;
1754 Expected
<StringRef
> MachOObjectFile::getSymbolName(DataRefImpl Symb
) const {
1755 StringRef StringTable
= getStringTableData();
1756 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1757 if (Entry
.n_strx
== 0)
1758 // A n_strx value of 0 indicates that no name is associated with a
1759 // particular symbol table entry.
1761 const char *Start
= &StringTable
.data()[Entry
.n_strx
];
1762 if (Start
< getData().begin() || Start
>= getData().end()) {
1763 return malformedError("bad string index: " + Twine(Entry
.n_strx
) +
1764 " for symbol at index " + Twine(getSymbolIndex(Symb
)));
1766 return StringRef(Start
);
1769 unsigned MachOObjectFile::getSectionType(SectionRef Sec
) const {
1770 DataRefImpl DRI
= Sec
.getRawDataRefImpl();
1771 uint32_t Flags
= getSectionFlags(*this, DRI
);
1772 return Flags
& MachO::SECTION_TYPE
;
1775 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym
) const {
1777 MachO::nlist_64 Entry
= getSymbol64TableEntry(Sym
);
1778 return Entry
.n_value
;
1780 MachO::nlist Entry
= getSymbolTableEntry(Sym
);
1781 return Entry
.n_value
;
1784 // getIndirectName() returns the name of the alias'ed symbol who's string table
1785 // index is in the n_value field.
1786 std::error_code
MachOObjectFile::getIndirectName(DataRefImpl Symb
,
1787 StringRef
&Res
) const {
1788 StringRef StringTable
= getStringTableData();
1789 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1790 if ((Entry
.n_type
& MachO::N_TYPE
) != MachO::N_INDR
)
1791 return object_error::parse_failed
;
1792 uint64_t NValue
= getNValue(Symb
);
1793 if (NValue
>= StringTable
.size())
1794 return object_error::parse_failed
;
1795 const char *Start
= &StringTable
.data()[NValue
];
1796 Res
= StringRef(Start
);
1797 return std::error_code();
1800 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym
) const {
1801 return getNValue(Sym
);
1804 Expected
<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym
) const {
1805 return getSymbolValue(Sym
);
1808 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI
) const {
1809 uint32_t Flags
= cantFail(getSymbolFlags(DRI
));
1810 if (Flags
& SymbolRef::SF_Common
) {
1811 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, DRI
);
1812 return 1 << MachO::GET_COMM_ALIGN(Entry
.n_desc
);
1817 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI
) const {
1818 return getNValue(DRI
);
1821 Expected
<SymbolRef::Type
>
1822 MachOObjectFile::getSymbolType(DataRefImpl Symb
) const {
1823 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1824 uint8_t n_type
= Entry
.n_type
;
1826 // If this is a STAB debugging symbol, we can do nothing more.
1827 if (n_type
& MachO::N_STAB
)
1828 return SymbolRef::ST_Debug
;
1830 switch (n_type
& MachO::N_TYPE
) {
1831 case MachO::N_UNDF
:
1832 return SymbolRef::ST_Unknown
;
1833 case MachO::N_SECT
:
1834 Expected
<section_iterator
> SecOrError
= getSymbolSection(Symb
);
1836 return SecOrError
.takeError();
1837 section_iterator Sec
= *SecOrError
;
1838 if (Sec
== section_end())
1839 return SymbolRef::ST_Other
;
1840 if (Sec
->isData() || Sec
->isBSS())
1841 return SymbolRef::ST_Data
;
1842 return SymbolRef::ST_Function
;
1844 return SymbolRef::ST_Other
;
1847 Expected
<uint32_t> MachOObjectFile::getSymbolFlags(DataRefImpl DRI
) const {
1848 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, DRI
);
1850 uint8_t MachOType
= Entry
.n_type
;
1851 uint16_t MachOFlags
= Entry
.n_desc
;
1853 uint32_t Result
= SymbolRef::SF_None
;
1855 if ((MachOType
& MachO::N_TYPE
) == MachO::N_INDR
)
1856 Result
|= SymbolRef::SF_Indirect
;
1858 if (MachOType
& MachO::N_STAB
)
1859 Result
|= SymbolRef::SF_FormatSpecific
;
1861 if (MachOType
& MachO::N_EXT
) {
1862 Result
|= SymbolRef::SF_Global
;
1863 if ((MachOType
& MachO::N_TYPE
) == MachO::N_UNDF
) {
1865 Result
|= SymbolRef::SF_Common
;
1867 Result
|= SymbolRef::SF_Undefined
;
1870 if (!(MachOType
& MachO::N_PEXT
))
1871 Result
|= SymbolRef::SF_Exported
;
1874 if (MachOFlags
& (MachO::N_WEAK_REF
| MachO::N_WEAK_DEF
))
1875 Result
|= SymbolRef::SF_Weak
;
1877 if (MachOFlags
& (MachO::N_ARM_THUMB_DEF
))
1878 Result
|= SymbolRef::SF_Thumb
;
1880 if ((MachOType
& MachO::N_TYPE
) == MachO::N_ABS
)
1881 Result
|= SymbolRef::SF_Absolute
;
1886 Expected
<section_iterator
>
1887 MachOObjectFile::getSymbolSection(DataRefImpl Symb
) const {
1888 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1889 uint8_t index
= Entry
.n_sect
;
1892 return section_end();
1894 DRI
.d
.a
= index
- 1;
1895 if (DRI
.d
.a
>= Sections
.size()){
1896 return malformedError("bad section index: " + Twine((int)index
) +
1897 " for symbol at index " + Twine(getSymbolIndex(Symb
)));
1899 return section_iterator(SectionRef(DRI
, this));
1902 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym
) const {
1903 MachO::nlist_base Entry
=
1904 getSymbolTableEntryBase(*this, Sym
.getRawDataRefImpl());
1905 return Entry
.n_sect
- 1;
1908 void MachOObjectFile::moveSectionNext(DataRefImpl
&Sec
) const {
1912 Expected
<StringRef
> MachOObjectFile::getSectionName(DataRefImpl Sec
) const {
1913 ArrayRef
<char> Raw
= getSectionRawName(Sec
);
1914 return parseSegmentOrSectionName(Raw
.data());
1917 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec
) const {
1919 return getSection64(Sec
).addr
;
1920 return getSection(Sec
).addr
;
1923 uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec
) const {
1927 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec
) const {
1928 // In the case if a malformed Mach-O file where the section offset is past
1929 // the end of the file or some part of the section size is past the end of
1930 // the file return a size of zero or a size that covers the rest of the file
1931 // but does not extend past the end of the file.
1932 uint32_t SectOffset
, SectType
;
1936 MachO::section_64 Sect
= getSection64(Sec
);
1937 SectOffset
= Sect
.offset
;
1938 SectSize
= Sect
.size
;
1939 SectType
= Sect
.flags
& MachO::SECTION_TYPE
;
1941 MachO::section Sect
= getSection(Sec
);
1942 SectOffset
= Sect
.offset
;
1943 SectSize
= Sect
.size
;
1944 SectType
= Sect
.flags
& MachO::SECTION_TYPE
;
1946 if (SectType
== MachO::S_ZEROFILL
|| SectType
== MachO::S_GB_ZEROFILL
)
1948 uint64_t FileSize
= getData().size();
1949 if (SectOffset
> FileSize
)
1951 if (FileSize
- SectOffset
< SectSize
)
1952 return FileSize
- SectOffset
;
1956 ArrayRef
<uint8_t> MachOObjectFile::getSectionContents(uint32_t Offset
,
1957 uint64_t Size
) const {
1958 return arrayRefFromStringRef(getData().substr(Offset
, Size
));
1961 Expected
<ArrayRef
<uint8_t>>
1962 MachOObjectFile::getSectionContents(DataRefImpl Sec
) const {
1967 MachO::section_64 Sect
= getSection64(Sec
);
1968 Offset
= Sect
.offset
;
1971 MachO::section Sect
= getSection(Sec
);
1972 Offset
= Sect
.offset
;
1976 return getSectionContents(Offset
, Size
);
1979 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
1982 MachO::section_64 Sect
= getSection64(Sec
);
1985 MachO::section Sect
= getSection(Sec
);
1989 return uint64_t(1) << Align
;
1992 Expected
<SectionRef
> MachOObjectFile::getSection(unsigned SectionIndex
) const {
1993 if (SectionIndex
< 1 || SectionIndex
> Sections
.size())
1994 return malformedError("bad section index: " + Twine((int)SectionIndex
));
1997 DRI
.d
.a
= SectionIndex
- 1;
1998 return SectionRef(DRI
, this);
2001 Expected
<SectionRef
> MachOObjectFile::getSection(StringRef SectionName
) const {
2002 for (const SectionRef
&Section
: sections()) {
2003 auto NameOrErr
= Section
.getName();
2005 return NameOrErr
.takeError();
2006 if (*NameOrErr
== SectionName
)
2009 return errorCodeToError(object_error::parse_failed
);
2012 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
2016 bool MachOObjectFile::isSectionText(DataRefImpl Sec
) const {
2017 uint32_t Flags
= getSectionFlags(*this, Sec
);
2018 return Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
;
2021 bool MachOObjectFile::isSectionData(DataRefImpl Sec
) const {
2022 uint32_t Flags
= getSectionFlags(*this, Sec
);
2023 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2024 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
2025 !(SectionType
== MachO::S_ZEROFILL
||
2026 SectionType
== MachO::S_GB_ZEROFILL
);
2029 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec
) const {
2030 uint32_t Flags
= getSectionFlags(*this, Sec
);
2031 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2032 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
2033 (SectionType
== MachO::S_ZEROFILL
||
2034 SectionType
== MachO::S_GB_ZEROFILL
);
2037 bool MachOObjectFile::isDebugSection(DataRefImpl Sec
) const {
2038 Expected
<StringRef
> SectionNameOrErr
= getSectionName(Sec
);
2039 if (!SectionNameOrErr
) {
2040 // TODO: Report the error message properly.
2041 consumeError(SectionNameOrErr
.takeError());
2044 StringRef SectionName
= SectionNameOrErr
.get();
2045 return SectionName
.startswith("__debug") ||
2046 SectionName
.startswith("__zdebug") ||
2047 SectionName
.startswith("__apple") || SectionName
== "__gdb_index" ||
2048 SectionName
== "__swift_ast";
2051 unsigned MachOObjectFile::getSectionID(SectionRef Sec
) const {
2052 return Sec
.getRawDataRefImpl().d
.a
;
2055 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec
) const {
2056 uint32_t Flags
= getSectionFlags(*this, Sec
);
2057 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2058 return SectionType
== MachO::S_ZEROFILL
||
2059 SectionType
== MachO::S_GB_ZEROFILL
;
2062 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec
) const {
2063 StringRef SegmentName
= getSectionFinalSegmentName(Sec
);
2064 if (Expected
<StringRef
> NameOrErr
= getSectionName(Sec
))
2065 return (SegmentName
== "__LLVM" && *NameOrErr
== "__bitcode");
2069 bool MachOObjectFile::isSectionStripped(DataRefImpl Sec
) const {
2071 return getSection64(Sec
).offset
== 0;
2072 return getSection(Sec
).offset
== 0;
2075 relocation_iterator
MachOObjectFile::section_rel_begin(DataRefImpl Sec
) const {
2079 return relocation_iterator(RelocationRef(Ret
, this));
2083 MachOObjectFile::section_rel_end(DataRefImpl Sec
) const {
2086 MachO::section_64 Sect
= getSection64(Sec
);
2089 MachO::section Sect
= getSection(Sec
);
2096 return relocation_iterator(RelocationRef(Ret
, this));
2099 relocation_iterator
MachOObjectFile::extrel_begin() const {
2101 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2102 Ret
.d
.a
= 0; // Would normally be a section index.
2103 Ret
.d
.b
= 0; // Index into the external relocations
2104 return relocation_iterator(RelocationRef(Ret
, this));
2107 relocation_iterator
MachOObjectFile::extrel_end() const {
2108 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2110 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2111 Ret
.d
.a
= 0; // Would normally be a section index.
2112 Ret
.d
.b
= DysymtabLoadCmd
.nextrel
; // Index into the external relocations
2113 return relocation_iterator(RelocationRef(Ret
, this));
2116 relocation_iterator
MachOObjectFile::locrel_begin() const {
2118 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2119 Ret
.d
.a
= 1; // Would normally be a section index.
2120 Ret
.d
.b
= 0; // Index into the local relocations
2121 return relocation_iterator(RelocationRef(Ret
, this));
2124 relocation_iterator
MachOObjectFile::locrel_end() const {
2125 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2127 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2128 Ret
.d
.a
= 1; // Would normally be a section index.
2129 Ret
.d
.b
= DysymtabLoadCmd
.nlocrel
; // Index into the local relocations
2130 return relocation_iterator(RelocationRef(Ret
, this));
2133 void MachOObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
2137 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
2138 assert((getHeader().filetype
== MachO::MH_OBJECT
||
2139 getHeader().filetype
== MachO::MH_KEXT_BUNDLE
) &&
2140 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2141 MachO::any_relocation_info RE
= getRelocation(Rel
);
2142 return getAnyRelocationAddress(RE
);
2146 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
2147 MachO::any_relocation_info RE
= getRelocation(Rel
);
2148 if (isRelocationScattered(RE
))
2149 return symbol_end();
2151 uint32_t SymbolIdx
= getPlainRelocationSymbolNum(RE
);
2152 bool isExtern
= getPlainRelocationExternal(RE
);
2154 return symbol_end();
2156 MachO::symtab_command S
= getSymtabLoadCommand();
2157 unsigned SymbolTableEntrySize
= is64Bit() ?
2158 sizeof(MachO::nlist_64
) :
2159 sizeof(MachO::nlist
);
2160 uint64_t Offset
= S
.symoff
+ SymbolIdx
* SymbolTableEntrySize
;
2162 Sym
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2163 return symbol_iterator(SymbolRef(Sym
, this));
2167 MachOObjectFile::getRelocationSection(DataRefImpl Rel
) const {
2168 return section_iterator(getAnyRelocationSection(getRelocation(Rel
)));
2171 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel
) const {
2172 MachO::any_relocation_info RE
= getRelocation(Rel
);
2173 return getAnyRelocationType(RE
);
2176 void MachOObjectFile::getRelocationTypeName(
2177 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
2179 uint64_t RType
= getRelocationType(Rel
);
2181 unsigned Arch
= this->getArch();
2185 static const char *const Table
[] = {
2186 "GENERIC_RELOC_VANILLA",
2187 "GENERIC_RELOC_PAIR",
2188 "GENERIC_RELOC_SECTDIFF",
2189 "GENERIC_RELOC_PB_LA_PTR",
2190 "GENERIC_RELOC_LOCAL_SECTDIFF",
2191 "GENERIC_RELOC_TLV" };
2199 case Triple::x86_64
: {
2200 static const char *const Table
[] = {
2201 "X86_64_RELOC_UNSIGNED",
2202 "X86_64_RELOC_SIGNED",
2203 "X86_64_RELOC_BRANCH",
2204 "X86_64_RELOC_GOT_LOAD",
2206 "X86_64_RELOC_SUBTRACTOR",
2207 "X86_64_RELOC_SIGNED_1",
2208 "X86_64_RELOC_SIGNED_2",
2209 "X86_64_RELOC_SIGNED_4",
2210 "X86_64_RELOC_TLV" };
2219 static const char *const Table
[] = {
2220 "ARM_RELOC_VANILLA",
2222 "ARM_RELOC_SECTDIFF",
2223 "ARM_RELOC_LOCAL_SECTDIFF",
2224 "ARM_RELOC_PB_LA_PTR",
2226 "ARM_THUMB_RELOC_BR22",
2227 "ARM_THUMB_32BIT_BRANCH",
2229 "ARM_RELOC_HALF_SECTDIFF" };
2237 case Triple::aarch64
:
2238 case Triple::aarch64_32
: {
2239 static const char *const Table
[] = {
2240 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2241 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2242 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2243 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2244 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2245 "ARM64_RELOC_ADDEND"
2248 if (RType
>= array_lengthof(Table
))
2255 static const char *const Table
[] = {
2256 "PPC_RELOC_VANILLA",
2264 "PPC_RELOC_SECTDIFF",
2265 "PPC_RELOC_PB_LA_PTR",
2266 "PPC_RELOC_HI16_SECTDIFF",
2267 "PPC_RELOC_LO16_SECTDIFF",
2268 "PPC_RELOC_HA16_SECTDIFF",
2270 "PPC_RELOC_LO14_SECTDIFF",
2271 "PPC_RELOC_LOCAL_SECTDIFF" };
2279 case Triple::UnknownArch
:
2283 Result
.append(res
.begin(), res
.end());
2286 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel
) const {
2287 MachO::any_relocation_info RE
= getRelocation(Rel
);
2288 return getAnyRelocationLength(RE
);
2292 // guessLibraryShortName() is passed a name of a dynamic library and returns a
2293 // guess on what the short name is. Then name is returned as a substring of the
2294 // StringRef Name passed in. The name of the dynamic library is recognized as
2295 // a framework if it has one of the two following forms:
2296 // Foo.framework/Versions/A/Foo
2297 // Foo.framework/Foo
2298 // Where A and Foo can be any string. And may contain a trailing suffix
2299 // starting with an underbar. If the Name is recognized as a framework then
2300 // isFramework is set to true else it is set to false. If the Name has a
2301 // suffix then Suffix is set to the substring in Name that contains the suffix
2302 // else it is set to a NULL StringRef.
2304 // The Name of the dynamic library is recognized as a library name if it has
2305 // one of the two following forms:
2309 // The library may have a suffix trailing the name Foo of the form:
2310 // libFoo_profile.A.dylib
2311 // libFoo_profile.dylib
2312 // These dyld image suffixes are separated from the short name by a '_'
2313 // character. Because the '_' character is commonly used to separate words in
2314 // filenames guessLibraryShortName() cannot reliably separate a dylib's short
2315 // name from an arbitrary image suffix; imagine if both the short name and the
2316 // suffix contains an '_' character! To better deal with this ambiguity,
2317 // guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
2318 // Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
2319 // guessing incorrectly.
2321 // The Name of the dynamic library is also recognized as a library name if it
2322 // has the following form:
2325 // If the Name of the dynamic library is none of the forms above then a NULL
2326 // StringRef is returned.
2327 StringRef
MachOObjectFile::guessLibraryShortName(StringRef Name
,
2329 StringRef
&Suffix
) {
2330 StringRef Foo
, F
, DotFramework
, V
, Dylib
, Lib
, Dot
, Qtx
;
2331 size_t a
, b
, c
, d
, Idx
;
2333 isFramework
= false;
2334 Suffix
= StringRef();
2336 // Pull off the last component and make Foo point to it
2337 a
= Name
.rfind('/');
2338 if (a
== Name
.npos
|| a
== 0)
2340 Foo
= Name
.slice(a
+1, Name
.npos
);
2342 // Look for a suffix starting with a '_'
2343 Idx
= Foo
.rfind('_');
2344 if (Idx
!= Foo
.npos
&& Foo
.size() >= 2) {
2345 Suffix
= Foo
.slice(Idx
, Foo
.npos
);
2346 if (Suffix
!= "_debug" && Suffix
!= "_profile")
2347 Suffix
= StringRef();
2349 Foo
= Foo
.slice(0, Idx
);
2352 // First look for the form Foo.framework/Foo
2353 b
= Name
.rfind('/', a
);
2358 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2359 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2360 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2361 if (F
== Foo
&& DotFramework
== ".framework/") {
2366 // Next look for the form Foo.framework/Versions/A/Foo
2369 c
= Name
.rfind('/', b
);
2370 if (c
== Name
.npos
|| c
== 0)
2372 V
= Name
.slice(c
+1, Name
.npos
);
2373 if (!V
.startswith("Versions/"))
2375 d
= Name
.rfind('/', c
);
2380 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2381 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2382 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2383 if (F
== Foo
&& DotFramework
== ".framework/") {
2389 // pull off the suffix after the "." and make a point to it
2390 a
= Name
.rfind('.');
2391 if (a
== Name
.npos
|| a
== 0)
2393 Dylib
= Name
.slice(a
, Name
.npos
);
2394 if (Dylib
!= ".dylib")
2397 // First pull off the version letter for the form Foo.A.dylib if any.
2399 Dot
= Name
.slice(a
-2, a
-1);
2404 b
= Name
.rfind('/', a
);
2409 // ignore any suffix after an underbar like Foo_profile.A.dylib
2410 Idx
= Name
.rfind('_');
2411 if (Idx
!= Name
.npos
&& Idx
!= b
) {
2412 Lib
= Name
.slice(b
, Idx
);
2413 Suffix
= Name
.slice(Idx
, a
);
2414 if (Suffix
!= "_debug" && Suffix
!= "_profile") {
2415 Suffix
= StringRef();
2416 Lib
= Name
.slice(b
, a
);
2420 Lib
= Name
.slice(b
, a
);
2421 // There are incorrect library names of the form:
2422 // libATS.A_profile.dylib so check for these.
2423 if (Lib
.size() >= 3) {
2424 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2426 Lib
= Lib
.slice(0, Lib
.size()-2);
2431 Qtx
= Name
.slice(a
, Name
.npos
);
2434 b
= Name
.rfind('/', a
);
2436 Lib
= Name
.slice(0, a
);
2438 Lib
= Name
.slice(b
+1, a
);
2439 // There are library names of the form: QT.A.qtx so check for these.
2440 if (Lib
.size() >= 3) {
2441 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2443 Lib
= Lib
.slice(0, Lib
.size()-2);
2448 // getLibraryShortNameByIndex() is used to get the short name of the library
2449 // for an undefined symbol in a linked Mach-O binary that was linked with the
2450 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
2451 // It is passed the index (0 - based) of the library as translated from
2452 // GET_LIBRARY_ORDINAL (1 - based).
2453 std::error_code
MachOObjectFile::getLibraryShortNameByIndex(unsigned Index
,
2454 StringRef
&Res
) const {
2455 if (Index
>= Libraries
.size())
2456 return object_error::parse_failed
;
2458 // If the cache of LibrariesShortNames is not built up do that first for
2459 // all the Libraries.
2460 if (LibrariesShortNames
.size() == 0) {
2461 for (unsigned i
= 0; i
< Libraries
.size(); i
++) {
2463 getStructOrErr
<MachO::dylib_command
>(*this, Libraries
[i
]);
2465 return object_error::parse_failed
;
2466 MachO::dylib_command D
= CommandOrErr
.get();
2467 if (D
.dylib
.name
>= D
.cmdsize
)
2468 return object_error::parse_failed
;
2469 const char *P
= (const char *)(Libraries
[i
]) + D
.dylib
.name
;
2470 StringRef Name
= StringRef(P
);
2471 if (D
.dylib
.name
+Name
.size() >= D
.cmdsize
)
2472 return object_error::parse_failed
;
2475 StringRef shortName
= guessLibraryShortName(Name
, isFramework
, Suffix
);
2476 if (shortName
.empty())
2477 LibrariesShortNames
.push_back(Name
);
2479 LibrariesShortNames
.push_back(shortName
);
2483 Res
= LibrariesShortNames
[Index
];
2484 return std::error_code();
2487 uint32_t MachOObjectFile::getLibraryCount() const {
2488 return Libraries
.size();
2492 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel
) const {
2494 Sec
.d
.a
= Rel
->getRawDataRefImpl().d
.a
;
2495 return section_iterator(SectionRef(Sec
, this));
2498 basic_symbol_iterator
MachOObjectFile::symbol_begin() const {
2500 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2501 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2502 return basic_symbol_iterator(SymbolRef(DRI
, this));
2504 return getSymbolByIndex(0);
2507 basic_symbol_iterator
MachOObjectFile::symbol_end() const {
2509 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2510 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2511 return basic_symbol_iterator(SymbolRef(DRI
, this));
2513 unsigned SymbolTableEntrySize
= is64Bit() ?
2514 sizeof(MachO::nlist_64
) :
2515 sizeof(MachO::nlist
);
2516 unsigned Offset
= Symtab
.symoff
+
2517 Symtab
.nsyms
* SymbolTableEntrySize
;
2518 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2519 return basic_symbol_iterator(SymbolRef(DRI
, this));
2522 symbol_iterator
MachOObjectFile::getSymbolByIndex(unsigned Index
) const {
2523 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2524 if (!SymtabLoadCmd
|| Index
>= Symtab
.nsyms
)
2525 report_fatal_error("Requested symbol index is out of range.");
2526 unsigned SymbolTableEntrySize
=
2527 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2529 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2530 DRI
.p
+= Index
* SymbolTableEntrySize
;
2531 return basic_symbol_iterator(SymbolRef(DRI
, this));
2534 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb
) const {
2535 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2537 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2538 unsigned SymbolTableEntrySize
=
2539 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2540 DataRefImpl DRIstart
;
2541 DRIstart
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2542 uint64_t Index
= (Symb
.p
- DRIstart
.p
) / SymbolTableEntrySize
;
2546 section_iterator
MachOObjectFile::section_begin() const {
2548 return section_iterator(SectionRef(DRI
, this));
2551 section_iterator
MachOObjectFile::section_end() const {
2553 DRI
.d
.a
= Sections
.size();
2554 return section_iterator(SectionRef(DRI
, this));
2557 uint8_t MachOObjectFile::getBytesInAddress() const {
2558 return is64Bit() ? 8 : 4;
2561 StringRef
MachOObjectFile::getFileFormatName() const {
2562 unsigned CPUType
= getCPUType(*this);
2565 case MachO::CPU_TYPE_I386
:
2566 return "Mach-O 32-bit i386";
2567 case MachO::CPU_TYPE_ARM
:
2568 return "Mach-O arm";
2569 case MachO::CPU_TYPE_ARM64_32
:
2570 return "Mach-O arm64 (ILP32)";
2571 case MachO::CPU_TYPE_POWERPC
:
2572 return "Mach-O 32-bit ppc";
2574 return "Mach-O 32-bit unknown";
2579 case MachO::CPU_TYPE_X86_64
:
2580 return "Mach-O 64-bit x86-64";
2581 case MachO::CPU_TYPE_ARM64
:
2582 return "Mach-O arm64";
2583 case MachO::CPU_TYPE_POWERPC64
:
2584 return "Mach-O 64-bit ppc64";
2586 return "Mach-O 64-bit unknown";
2590 Triple::ArchType
MachOObjectFile::getArch(uint32_t CPUType
, uint32_t CPUSubType
) {
2592 case MachO::CPU_TYPE_I386
:
2594 case MachO::CPU_TYPE_X86_64
:
2595 return Triple::x86_64
;
2596 case MachO::CPU_TYPE_ARM
:
2598 case MachO::CPU_TYPE_ARM64
:
2599 return Triple::aarch64
;
2600 case MachO::CPU_TYPE_ARM64_32
:
2601 return Triple::aarch64_32
;
2602 case MachO::CPU_TYPE_POWERPC
:
2604 case MachO::CPU_TYPE_POWERPC64
:
2605 return Triple::ppc64
;
2607 return Triple::UnknownArch
;
2611 Triple
MachOObjectFile::getArchTriple(uint32_t CPUType
, uint32_t CPUSubType
,
2612 const char **McpuDefault
,
2613 const char **ArchFlag
) {
2615 *McpuDefault
= nullptr;
2617 *ArchFlag
= nullptr;
2620 case MachO::CPU_TYPE_I386
:
2621 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2622 case MachO::CPU_SUBTYPE_I386_ALL
:
2625 return Triple("i386-apple-darwin");
2629 case MachO::CPU_TYPE_X86_64
:
2630 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2631 case MachO::CPU_SUBTYPE_X86_64_ALL
:
2633 *ArchFlag
= "x86_64";
2634 return Triple("x86_64-apple-darwin");
2635 case MachO::CPU_SUBTYPE_X86_64_H
:
2637 *ArchFlag
= "x86_64h";
2638 return Triple("x86_64h-apple-darwin");
2642 case MachO::CPU_TYPE_ARM
:
2643 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2644 case MachO::CPU_SUBTYPE_ARM_V4T
:
2646 *ArchFlag
= "armv4t";
2647 return Triple("armv4t-apple-darwin");
2648 case MachO::CPU_SUBTYPE_ARM_V5TEJ
:
2650 *ArchFlag
= "armv5e";
2651 return Triple("armv5e-apple-darwin");
2652 case MachO::CPU_SUBTYPE_ARM_XSCALE
:
2654 *ArchFlag
= "xscale";
2655 return Triple("xscale-apple-darwin");
2656 case MachO::CPU_SUBTYPE_ARM_V6
:
2658 *ArchFlag
= "armv6";
2659 return Triple("armv6-apple-darwin");
2660 case MachO::CPU_SUBTYPE_ARM_V6M
:
2662 *McpuDefault
= "cortex-m0";
2664 *ArchFlag
= "armv6m";
2665 return Triple("armv6m-apple-darwin");
2666 case MachO::CPU_SUBTYPE_ARM_V7
:
2668 *ArchFlag
= "armv7";
2669 return Triple("armv7-apple-darwin");
2670 case MachO::CPU_SUBTYPE_ARM_V7EM
:
2672 *McpuDefault
= "cortex-m4";
2674 *ArchFlag
= "armv7em";
2675 return Triple("thumbv7em-apple-darwin");
2676 case MachO::CPU_SUBTYPE_ARM_V7K
:
2678 *McpuDefault
= "cortex-a7";
2680 *ArchFlag
= "armv7k";
2681 return Triple("armv7k-apple-darwin");
2682 case MachO::CPU_SUBTYPE_ARM_V7M
:
2684 *McpuDefault
= "cortex-m3";
2686 *ArchFlag
= "armv7m";
2687 return Triple("thumbv7m-apple-darwin");
2688 case MachO::CPU_SUBTYPE_ARM_V7S
:
2690 *McpuDefault
= "cortex-a7";
2692 *ArchFlag
= "armv7s";
2693 return Triple("armv7s-apple-darwin");
2697 case MachO::CPU_TYPE_ARM64
:
2698 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2699 case MachO::CPU_SUBTYPE_ARM64_ALL
:
2701 *McpuDefault
= "cyclone";
2703 *ArchFlag
= "arm64";
2704 return Triple("arm64-apple-darwin");
2705 case MachO::CPU_SUBTYPE_ARM64E
:
2707 *McpuDefault
= "apple-a12";
2709 *ArchFlag
= "arm64e";
2710 return Triple("arm64e-apple-darwin");
2714 case MachO::CPU_TYPE_ARM64_32
:
2715 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2716 case MachO::CPU_SUBTYPE_ARM64_32_V8
:
2718 *McpuDefault
= "cyclone";
2720 *ArchFlag
= "arm64_32";
2721 return Triple("arm64_32-apple-darwin");
2725 case MachO::CPU_TYPE_POWERPC
:
2726 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2727 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2730 return Triple("ppc-apple-darwin");
2734 case MachO::CPU_TYPE_POWERPC64
:
2735 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2736 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2738 *ArchFlag
= "ppc64";
2739 return Triple("ppc64-apple-darwin");
2748 Triple
MachOObjectFile::getHostArch() {
2749 return Triple(sys::getDefaultTargetTriple());
2752 bool MachOObjectFile::isValidArch(StringRef ArchFlag
) {
2753 auto validArchs
= getValidArchs();
2754 return llvm::is_contained(validArchs
, ArchFlag
);
2757 ArrayRef
<StringRef
> MachOObjectFile::getValidArchs() {
2758 static const std::array
<StringRef
, 18> ValidArchs
= {{
2782 Triple::ArchType
MachOObjectFile::getArch() const {
2783 return getArch(getCPUType(*this), getCPUSubType(*this));
2786 Triple
MachOObjectFile::getArchTriple(const char **McpuDefault
) const {
2787 return getArchTriple(Header
.cputype
, Header
.cpusubtype
, McpuDefault
);
2790 relocation_iterator
MachOObjectFile::section_rel_begin(unsigned Index
) const {
2793 return section_rel_begin(DRI
);
2796 relocation_iterator
MachOObjectFile::section_rel_end(unsigned Index
) const {
2799 return section_rel_end(DRI
);
2802 dice_iterator
MachOObjectFile::begin_dices() const {
2804 if (!DataInCodeLoadCmd
)
2805 return dice_iterator(DiceRef(DRI
, this));
2807 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2808 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, DicLC
.dataoff
));
2809 return dice_iterator(DiceRef(DRI
, this));
2812 dice_iterator
MachOObjectFile::end_dices() const {
2814 if (!DataInCodeLoadCmd
)
2815 return dice_iterator(DiceRef(DRI
, this));
2817 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2818 unsigned Offset
= DicLC
.dataoff
+ DicLC
.datasize
;
2819 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2820 return dice_iterator(DiceRef(DRI
, this));
2823 ExportEntry::ExportEntry(Error
*E
, const MachOObjectFile
*O
,
2824 ArrayRef
<uint8_t> T
) : E(E
), O(O
), Trie(T
) {}
2826 void ExportEntry::moveToFirst() {
2827 ErrorAsOutParameter
ErrAsOutParam(E
);
2831 pushDownUntilBottom();
2834 void ExportEntry::moveToEnd() {
2839 bool ExportEntry::operator==(const ExportEntry
&Other
) const {
2840 // Common case, one at end, other iterating from begin.
2841 if (Done
|| Other
.Done
)
2842 return (Done
== Other
.Done
);
2843 // Not equal if different stack sizes.
2844 if (Stack
.size() != Other
.Stack
.size())
2846 // Not equal if different cumulative strings.
2847 if (!CumulativeString
.equals(Other
.CumulativeString
))
2849 // Equal if all nodes in both stacks match.
2850 for (unsigned i
=0; i
< Stack
.size(); ++i
) {
2851 if (Stack
[i
].Start
!= Other
.Stack
[i
].Start
)
2857 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr
, const char **error
) {
2859 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Trie
.end(), error
);
2861 if (Ptr
> Trie
.end())
2866 StringRef
ExportEntry::name() const {
2867 return CumulativeString
;
2870 uint64_t ExportEntry::flags() const {
2871 return Stack
.back().Flags
;
2874 uint64_t ExportEntry::address() const {
2875 return Stack
.back().Address
;
2878 uint64_t ExportEntry::other() const {
2879 return Stack
.back().Other
;
2882 StringRef
ExportEntry::otherName() const {
2883 const char* ImportName
= Stack
.back().ImportName
;
2885 return StringRef(ImportName
);
2889 uint32_t ExportEntry::nodeOffset() const {
2890 return Stack
.back().Start
- Trie
.begin();
2893 ExportEntry::NodeState::NodeState(const uint8_t *Ptr
)
2894 : Start(Ptr
), Current(Ptr
) {}
2896 void ExportEntry::pushNode(uint64_t offset
) {
2897 ErrorAsOutParameter
ErrAsOutParam(E
);
2898 const uint8_t *Ptr
= Trie
.begin() + offset
;
2899 NodeState
State(Ptr
);
2901 uint64_t ExportInfoSize
= readULEB128(State
.Current
, &error
);
2903 *E
= malformedError("export info size " + Twine(error
) +
2904 " in export trie data at node: 0x" +
2905 Twine::utohexstr(offset
));
2909 State
.IsExportNode
= (ExportInfoSize
!= 0);
2910 const uint8_t* Children
= State
.Current
+ ExportInfoSize
;
2911 if (Children
> Trie
.end()) {
2912 *E
= malformedError(
2913 "export info size: 0x" + Twine::utohexstr(ExportInfoSize
) +
2914 " in export trie data at node: 0x" + Twine::utohexstr(offset
) +
2915 " too big and extends past end of trie data");
2919 if (State
.IsExportNode
) {
2920 const uint8_t *ExportStart
= State
.Current
;
2921 State
.Flags
= readULEB128(State
.Current
, &error
);
2923 *E
= malformedError("flags " + Twine(error
) +
2924 " in export trie data at node: 0x" +
2925 Twine::utohexstr(offset
));
2929 uint64_t Kind
= State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK
;
2930 if (State
.Flags
!= 0 &&
2931 (Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR
&&
2932 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
&&
2933 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
)) {
2934 *E
= malformedError(
2935 "unsupported exported symbol kind: " + Twine((int)Kind
) +
2936 " in flags: 0x" + Twine::utohexstr(State
.Flags
) +
2937 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
2941 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_REEXPORT
) {
2943 State
.Other
= readULEB128(State
.Current
, &error
); // dylib ordinal
2945 *E
= malformedError("dylib ordinal of re-export " + Twine(error
) +
2946 " in export trie data at node: 0x" +
2947 Twine::utohexstr(offset
));
2952 if (State
.Other
> O
->getLibraryCount()) {
2953 *E
= malformedError(
2954 "bad library ordinal: " + Twine((int)State
.Other
) + " (max " +
2955 Twine((int)O
->getLibraryCount()) +
2956 ") in export trie data at node: 0x" + Twine::utohexstr(offset
));
2961 State
.ImportName
= reinterpret_cast<const char*>(State
.Current
);
2962 if (*State
.ImportName
== '\0') {
2965 const uint8_t *End
= State
.Current
+ 1;
2966 if (End
>= Trie
.end()) {
2967 *E
= malformedError("import name of re-export in export trie data at "
2969 Twine::utohexstr(offset
) +
2970 " starts past end of trie data");
2974 while(*End
!= '\0' && End
< Trie
.end())
2977 *E
= malformedError("import name of re-export in export trie data at "
2979 Twine::utohexstr(offset
) +
2980 " extends past end of trie data");
2984 State
.Current
= End
+ 1;
2987 State
.Address
= readULEB128(State
.Current
, &error
);
2989 *E
= malformedError("address " + Twine(error
) +
2990 " in export trie data at node: 0x" +
2991 Twine::utohexstr(offset
));
2995 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
) {
2996 State
.Other
= readULEB128(State
.Current
, &error
);
2998 *E
= malformedError("resolver of stub and resolver " + Twine(error
) +
2999 " in export trie data at node: 0x" +
3000 Twine::utohexstr(offset
));
3006 if(ExportStart
+ ExportInfoSize
!= State
.Current
) {
3007 *E
= malformedError(
3008 "inconsistant export info size: 0x" +
3009 Twine::utohexstr(ExportInfoSize
) + " where actual size was: 0x" +
3010 Twine::utohexstr(State
.Current
- ExportStart
) +
3011 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
3016 State
.ChildCount
= *Children
;
3017 if (State
.ChildCount
!= 0 && Children
+ 1 >= Trie
.end()) {
3018 *E
= malformedError("byte for count of childern in export trie data at "
3020 Twine::utohexstr(offset
) +
3021 " extends past end of trie data");
3025 State
.Current
= Children
+ 1;
3026 State
.NextChildIndex
= 0;
3027 State
.ParentStringLength
= CumulativeString
.size();
3028 Stack
.push_back(State
);
3031 void ExportEntry::pushDownUntilBottom() {
3032 ErrorAsOutParameter
ErrAsOutParam(E
);
3034 while (Stack
.back().NextChildIndex
< Stack
.back().ChildCount
) {
3035 NodeState
&Top
= Stack
.back();
3036 CumulativeString
.resize(Top
.ParentStringLength
);
3037 for (;*Top
.Current
!= 0 && Top
.Current
< Trie
.end(); Top
.Current
++) {
3038 char C
= *Top
.Current
;
3039 CumulativeString
.push_back(C
);
3041 if (Top
.Current
>= Trie
.end()) {
3042 *E
= malformedError("edge sub-string in export trie data at node: 0x" +
3043 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
3044 " for child #" + Twine((int)Top
.NextChildIndex
) +
3045 " extends past end of trie data");
3050 uint64_t childNodeIndex
= readULEB128(Top
.Current
, &error
);
3052 *E
= malformedError("child node offset " + Twine(error
) +
3053 " in export trie data at node: 0x" +
3054 Twine::utohexstr(Top
.Start
- Trie
.begin()));
3058 for (const NodeState
&node
: nodes()) {
3059 if (node
.Start
== Trie
.begin() + childNodeIndex
){
3060 *E
= malformedError("loop in childern in export trie data at node: 0x" +
3061 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
3062 " back to node: 0x" +
3063 Twine::utohexstr(childNodeIndex
));
3068 Top
.NextChildIndex
+= 1;
3069 pushNode(childNodeIndex
);
3073 if (!Stack
.back().IsExportNode
) {
3074 *E
= malformedError("node is not an export node in export trie data at "
3076 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3082 // We have a trie data structure and need a way to walk it that is compatible
3083 // with the C++ iterator model. The solution is a non-recursive depth first
3084 // traversal where the iterator contains a stack of parent nodes along with a
3085 // string that is the accumulation of all edge strings along the parent chain
3088 // There is one "export" node for each exported symbol. But because some
3089 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
3090 // node may have child nodes too.
3092 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
3093 // child until hitting a node with no children (which is an export node or
3094 // else the trie is malformed). On the way down, each node is pushed on the
3095 // stack ivar. If there is no more ways down, it pops up one and tries to go
3096 // down a sibling path until a childless node is reached.
3097 void ExportEntry::moveNext() {
3098 assert(!Stack
.empty() && "ExportEntry::moveNext() with empty node stack");
3099 if (!Stack
.back().IsExportNode
) {
3100 *E
= malformedError("node is not an export node in export trie data at "
3102 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3108 while (!Stack
.empty()) {
3109 NodeState
&Top
= Stack
.back();
3110 if (Top
.NextChildIndex
< Top
.ChildCount
) {
3111 pushDownUntilBottom();
3112 // Now at the next export node.
3115 if (Top
.IsExportNode
) {
3116 // This node has no children but is itself an export node.
3117 CumulativeString
.resize(Top
.ParentStringLength
);
3126 iterator_range
<export_iterator
>
3127 MachOObjectFile::exports(Error
&E
, ArrayRef
<uint8_t> Trie
,
3128 const MachOObjectFile
*O
) {
3129 ExportEntry
Start(&E
, O
, Trie
);
3133 Start
.moveToFirst();
3135 ExportEntry
Finish(&E
, O
, Trie
);
3138 return make_range(export_iterator(Start
), export_iterator(Finish
));
3141 iterator_range
<export_iterator
> MachOObjectFile::exports(Error
&Err
) const {
3142 return exports(Err
, getDyldInfoExportsTrie(), this);
3145 MachORebaseEntry::MachORebaseEntry(Error
*E
, const MachOObjectFile
*O
,
3146 ArrayRef
<uint8_t> Bytes
, bool is64Bit
)
3147 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3148 PointerSize(is64Bit
? 8 : 4) {}
3150 void MachORebaseEntry::moveToFirst() {
3151 Ptr
= Opcodes
.begin();
3155 void MachORebaseEntry::moveToEnd() {
3156 Ptr
= Opcodes
.end();
3157 RemainingLoopCount
= 0;
3161 void MachORebaseEntry::moveNext() {
3162 ErrorAsOutParameter
ErrAsOutParam(E
);
3163 // If in the middle of some loop, move to next rebasing in loop.
3164 SegmentOffset
+= AdvanceAmount
;
3165 if (RemainingLoopCount
) {
3166 --RemainingLoopCount
;
3169 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3170 // pointer size. Therefore it is possible to reach the end without ever having
3171 // seen REBASE_OPCODE_DONE.
3172 if (Ptr
== Opcodes
.end()) {
3178 // Parse next opcode and set up next loop.
3179 const uint8_t *OpcodeStart
= Ptr
;
3180 uint8_t Byte
= *Ptr
++;
3181 uint8_t ImmValue
= Byte
& MachO::REBASE_IMMEDIATE_MASK
;
3182 uint8_t Opcode
= Byte
& MachO::REBASE_OPCODE_MASK
;
3183 uint32_t Count
, Skip
;
3184 const char *error
= nullptr;
3186 case MachO::REBASE_OPCODE_DONE
:
3190 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
3192 case MachO::REBASE_OPCODE_SET_TYPE_IMM
:
3193 RebaseType
= ImmValue
;
3194 if (RebaseType
> MachO::REBASE_TYPE_TEXT_PCREL32
) {
3195 *E
= malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3196 Twine((int)RebaseType
) + " for opcode at: 0x" +
3197 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3203 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3204 << "RebaseType=" << (int) RebaseType
<< "\n");
3206 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3207 SegmentIndex
= ImmValue
;
3208 SegmentOffset
= readULEB128(&error
);
3210 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3211 Twine(error
) + " for opcode at: 0x" +
3212 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3216 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3219 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3220 Twine(error
) + " for opcode at: 0x" +
3221 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3227 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3228 << "SegmentIndex=" << SegmentIndex
<< ", "
3229 << format("SegmentOffset=0x%06X", SegmentOffset
)
3232 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB
:
3233 SegmentOffset
+= readULEB128(&error
);
3235 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3236 " for opcode at: 0x" +
3237 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3241 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3244 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3245 " for opcode at: 0x" +
3246 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3250 DEBUG_WITH_TYPE("mach-o-rebase",
3251 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3252 << format("SegmentOffset=0x%06X",
3253 SegmentOffset
) << "\n");
3255 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED
:
3256 SegmentOffset
+= ImmValue
* PointerSize
;
3257 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3260 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3261 Twine(error
) + " for opcode at: 0x" +
3262 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3266 DEBUG_WITH_TYPE("mach-o-rebase",
3267 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3268 << format("SegmentOffset=0x%06X",
3269 SegmentOffset
) << "\n");
3271 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES
:
3272 AdvanceAmount
= PointerSize
;
3276 RemainingLoopCount
= ImmValue
- 1;
3278 RemainingLoopCount
= 0;
3279 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3280 PointerSize
, Count
, Skip
);
3282 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3283 Twine(error
) + " for opcode at: 0x" +
3284 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3290 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3291 << format("SegmentOffset=0x%06X", SegmentOffset
)
3292 << ", AdvanceAmount=" << AdvanceAmount
3293 << ", RemainingLoopCount=" << RemainingLoopCount
3296 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES
:
3297 AdvanceAmount
= PointerSize
;
3299 Count
= readULEB128(&error
);
3301 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3302 Twine(error
) + " for opcode at: 0x" +
3303 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3308 RemainingLoopCount
= Count
- 1;
3310 RemainingLoopCount
= 0;
3311 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3312 PointerSize
, Count
, Skip
);
3314 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3315 Twine(error
) + " for opcode at: 0x" +
3316 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3322 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3323 << format("SegmentOffset=0x%06X", SegmentOffset
)
3324 << ", AdvanceAmount=" << AdvanceAmount
3325 << ", RemainingLoopCount=" << RemainingLoopCount
3328 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB
:
3329 Skip
= readULEB128(&error
);
3331 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3332 Twine(error
) + " for opcode at: 0x" +
3333 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3337 AdvanceAmount
= Skip
+ PointerSize
;
3339 RemainingLoopCount
= 0;
3340 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3341 PointerSize
, Count
, Skip
);
3343 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3344 Twine(error
) + " for opcode at: 0x" +
3345 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3351 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3352 << format("SegmentOffset=0x%06X", SegmentOffset
)
3353 << ", AdvanceAmount=" << AdvanceAmount
3354 << ", RemainingLoopCount=" << RemainingLoopCount
3357 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB
:
3358 Count
= readULEB128(&error
);
3360 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3362 Twine(error
) + " for opcode at: 0x" +
3363 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3368 RemainingLoopCount
= Count
- 1;
3370 RemainingLoopCount
= 0;
3371 Skip
= readULEB128(&error
);
3373 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3375 Twine(error
) + " for opcode at: 0x" +
3376 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3380 AdvanceAmount
= Skip
+ PointerSize
;
3382 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3383 PointerSize
, Count
, Skip
);
3385 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3387 Twine(error
) + " for opcode at: 0x" +
3388 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3394 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3395 << format("SegmentOffset=0x%06X", SegmentOffset
)
3396 << ", AdvanceAmount=" << AdvanceAmount
3397 << ", RemainingLoopCount=" << RemainingLoopCount
3401 *E
= malformedError("bad rebase info (bad opcode value 0x" +
3402 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3403 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3410 uint64_t MachORebaseEntry::readULEB128(const char **error
) {
3412 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3414 if (Ptr
> Opcodes
.end())
3415 Ptr
= Opcodes
.end();
3419 int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex
; }
3421 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset
; }
3423 StringRef
MachORebaseEntry::typeName() const {
3424 switch (RebaseType
) {
3425 case MachO::REBASE_TYPE_POINTER
:
3427 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32
:
3428 return "text abs32";
3429 case MachO::REBASE_TYPE_TEXT_PCREL32
:
3430 return "text rel32";
3435 // For use with the SegIndex of a checked Mach-O Rebase entry
3436 // to get the segment name.
3437 StringRef
MachORebaseEntry::segmentName() const {
3438 return O
->BindRebaseSegmentName(SegmentIndex
);
3441 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3442 // to get the section name.
3443 StringRef
MachORebaseEntry::sectionName() const {
3444 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3447 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3448 // to get the address.
3449 uint64_t MachORebaseEntry::address() const {
3450 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3453 bool MachORebaseEntry::operator==(const MachORebaseEntry
&Other
) const {
3454 #ifdef EXPENSIVE_CHECKS
3455 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
3457 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
3459 return (Ptr
== Other
.Ptr
) &&
3460 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
3461 (Done
== Other
.Done
);
3464 iterator_range
<rebase_iterator
>
3465 MachOObjectFile::rebaseTable(Error
&Err
, MachOObjectFile
*O
,
3466 ArrayRef
<uint8_t> Opcodes
, bool is64
) {
3467 if (O
->BindRebaseSectionTable
== nullptr)
3468 O
->BindRebaseSectionTable
= std::make_unique
<BindRebaseSegInfo
>(O
);
3469 MachORebaseEntry
Start(&Err
, O
, Opcodes
, is64
);
3470 Start
.moveToFirst();
3472 MachORebaseEntry
Finish(&Err
, O
, Opcodes
, is64
);
3475 return make_range(rebase_iterator(Start
), rebase_iterator(Finish
));
3478 iterator_range
<rebase_iterator
> MachOObjectFile::rebaseTable(Error
&Err
) {
3479 return rebaseTable(Err
, this, getDyldInfoRebaseOpcodes(), is64Bit());
3482 MachOBindEntry::MachOBindEntry(Error
*E
, const MachOObjectFile
*O
,
3483 ArrayRef
<uint8_t> Bytes
, bool is64Bit
, Kind BK
)
3484 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3485 PointerSize(is64Bit
? 8 : 4), TableKind(BK
) {}
3487 void MachOBindEntry::moveToFirst() {
3488 Ptr
= Opcodes
.begin();
3492 void MachOBindEntry::moveToEnd() {
3493 Ptr
= Opcodes
.end();
3494 RemainingLoopCount
= 0;
3498 void MachOBindEntry::moveNext() {
3499 ErrorAsOutParameter
ErrAsOutParam(E
);
3500 // If in the middle of some loop, move to next binding in loop.
3501 SegmentOffset
+= AdvanceAmount
;
3502 if (RemainingLoopCount
) {
3503 --RemainingLoopCount
;
3506 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3507 // pointer size. Therefore it is possible to reach the end without ever having
3508 // seen BIND_OPCODE_DONE.
3509 if (Ptr
== Opcodes
.end()) {
3515 // Parse next opcode and set up next loop.
3516 const uint8_t *OpcodeStart
= Ptr
;
3517 uint8_t Byte
= *Ptr
++;
3518 uint8_t ImmValue
= Byte
& MachO::BIND_IMMEDIATE_MASK
;
3519 uint8_t Opcode
= Byte
& MachO::BIND_OPCODE_MASK
;
3520 int8_t SignExtended
;
3521 const uint8_t *SymStart
;
3522 uint32_t Count
, Skip
;
3523 const char *error
= nullptr;
3525 case MachO::BIND_OPCODE_DONE
:
3526 if (TableKind
== Kind::Lazy
) {
3527 // Lazying bindings have a DONE opcode between entries. Need to ignore
3528 // it to advance to next entry. But need not if this is last entry.
3529 bool NotLastEntry
= false;
3530 for (const uint8_t *P
= Ptr
; P
< Opcodes
.end(); ++P
) {
3532 NotLastEntry
= true;
3540 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3542 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
:
3543 if (TableKind
== Kind::Weak
) {
3544 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3545 "weak bind table for opcode at: 0x" +
3546 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3551 LibraryOrdinalSet
= true;
3552 if (ImmValue
> O
->getLibraryCount()) {
3553 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3554 "library ordinal: " +
3555 Twine((int)ImmValue
) + " (max " +
3556 Twine((int)O
->getLibraryCount()) +
3557 ") for opcode at: 0x" +
3558 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3564 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3565 << "Ordinal=" << Ordinal
<< "\n");
3567 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
:
3568 if (TableKind
== Kind::Weak
) {
3569 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3570 "weak bind table for opcode at: 0x" +
3571 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3575 Ordinal
= readULEB128(&error
);
3576 LibraryOrdinalSet
= true;
3578 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3579 Twine(error
) + " for opcode at: 0x" +
3580 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3584 if (Ordinal
> (int)O
->getLibraryCount()) {
3585 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3586 "library ordinal: " +
3587 Twine((int)Ordinal
) + " (max " +
3588 Twine((int)O
->getLibraryCount()) +
3589 ") for opcode at: 0x" +
3590 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3596 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3597 << "Ordinal=" << Ordinal
<< "\n");
3599 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
:
3600 if (TableKind
== Kind::Weak
) {
3601 *E
= malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3602 "weak bind table for opcode at: 0x" +
3603 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3608 SignExtended
= MachO::BIND_OPCODE_MASK
| ImmValue
;
3609 Ordinal
= SignExtended
;
3610 if (Ordinal
< MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP
) {
3611 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3612 "special ordinal: " +
3613 Twine((int)Ordinal
) + " for opcode at: 0x" +
3614 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3620 LibraryOrdinalSet
= true;
3623 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3624 << "Ordinal=" << Ordinal
<< "\n");
3626 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
:
3629 while (*Ptr
&& (Ptr
< Opcodes
.end())) {
3632 if (Ptr
== Opcodes
.end()) {
3633 *E
= malformedError(
3634 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3635 "symbol name extends past opcodes for opcode at: 0x" +
3636 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3640 SymbolName
= StringRef(reinterpret_cast<const char*>(SymStart
),
3645 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3646 << "SymbolName=" << SymbolName
<< "\n");
3647 if (TableKind
== Kind::Weak
) {
3648 if (ImmValue
& MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
)
3652 case MachO::BIND_OPCODE_SET_TYPE_IMM
:
3653 BindType
= ImmValue
;
3654 if (ImmValue
> MachO::BIND_TYPE_TEXT_PCREL32
) {
3655 *E
= malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3656 Twine((int)ImmValue
) + " for opcode at: 0x" +
3657 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3663 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3664 << "BindType=" << (int)BindType
<< "\n");
3666 case MachO::BIND_OPCODE_SET_ADDEND_SLEB
:
3667 Addend
= readSLEB128(&error
);
3669 *E
= malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error
) +
3670 " for opcode at: 0x" +
3671 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3677 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3678 << "Addend=" << Addend
<< "\n");
3680 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3681 SegmentIndex
= ImmValue
;
3682 SegmentOffset
= readULEB128(&error
);
3684 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3685 Twine(error
) + " for opcode at: 0x" +
3686 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3690 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3693 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3694 Twine(error
) + " for opcode at: 0x" +
3695 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3701 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3702 << "SegmentIndex=" << SegmentIndex
<< ", "
3703 << format("SegmentOffset=0x%06X", SegmentOffset
)
3706 case MachO::BIND_OPCODE_ADD_ADDR_ULEB
:
3707 SegmentOffset
+= readULEB128(&error
);
3709 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3710 " for opcode at: 0x" +
3711 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3715 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3718 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3719 " for opcode at: 0x" +
3720 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3724 DEBUG_WITH_TYPE("mach-o-bind",
3725 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3726 << format("SegmentOffset=0x%06X",
3727 SegmentOffset
) << "\n");
3729 case MachO::BIND_OPCODE_DO_BIND
:
3730 AdvanceAmount
= PointerSize
;
3731 RemainingLoopCount
= 0;
3732 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3735 *E
= malformedError("for BIND_OPCODE_DO_BIND " + Twine(error
) +
3736 " for opcode at: 0x" +
3737 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3741 if (SymbolName
== StringRef()) {
3742 *E
= malformedError(
3743 "for BIND_OPCODE_DO_BIND missing preceding "
3744 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3745 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3749 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3751 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3752 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3753 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3757 DEBUG_WITH_TYPE("mach-o-bind",
3758 dbgs() << "BIND_OPCODE_DO_BIND: "
3759 << format("SegmentOffset=0x%06X",
3760 SegmentOffset
) << "\n");
3762 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
:
3763 if (TableKind
== Kind::Lazy
) {
3764 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3765 "lazy bind table for opcode at: 0x" +
3766 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3770 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3773 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3774 Twine(error
) + " for opcode at: 0x" +
3775 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3779 if (SymbolName
== StringRef()) {
3780 *E
= malformedError(
3781 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3782 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3784 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3788 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3789 *E
= malformedError(
3790 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3791 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3792 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3796 AdvanceAmount
= readULEB128(&error
) + PointerSize
;
3798 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3799 Twine(error
) + " for opcode at: 0x" +
3800 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3804 // Note, this is not really an error until the next bind but make no sense
3805 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3807 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
+
3808 AdvanceAmount
, PointerSize
);
3810 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3812 Twine(error
) + " for opcode at: 0x" +
3813 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3817 RemainingLoopCount
= 0;
3820 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3821 << format("SegmentOffset=0x%06X", SegmentOffset
)
3822 << ", AdvanceAmount=" << AdvanceAmount
3823 << ", RemainingLoopCount=" << RemainingLoopCount
3826 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
:
3827 if (TableKind
== Kind::Lazy
) {
3828 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3829 "allowed in lazy bind table for opcode at: 0x" +
3830 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3834 if (SymbolName
== StringRef()) {
3835 *E
= malformedError(
3836 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3837 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3839 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3843 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3844 *E
= malformedError(
3845 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3846 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3848 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3852 AdvanceAmount
= ImmValue
* PointerSize
+ PointerSize
;
3853 RemainingLoopCount
= 0;
3854 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
+
3855 AdvanceAmount
, PointerSize
);
3857 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3858 Twine(error
) + " for opcode at: 0x" +
3859 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3863 DEBUG_WITH_TYPE("mach-o-bind",
3865 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3866 << format("SegmentOffset=0x%06X", SegmentOffset
) << "\n");
3868 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
:
3869 if (TableKind
== Kind::Lazy
) {
3870 *E
= malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3871 "allowed in lazy bind table for opcode at: 0x" +
3872 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3876 Count
= readULEB128(&error
);
3878 RemainingLoopCount
= Count
- 1;
3880 RemainingLoopCount
= 0;
3882 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3884 Twine(error
) + " for opcode at: 0x" +
3885 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3889 Skip
= readULEB128(&error
);
3890 AdvanceAmount
= Skip
+ PointerSize
;
3892 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3894 Twine(error
) + " for opcode at: 0x" +
3895 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3899 if (SymbolName
== StringRef()) {
3900 *E
= malformedError(
3901 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3902 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3904 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3908 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3909 *E
= malformedError(
3910 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3911 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3913 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3917 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3918 PointerSize
, Count
, Skip
);
3921 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3922 Twine(error
) + " for opcode at: 0x" +
3923 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3929 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3930 << format("SegmentOffset=0x%06X", SegmentOffset
)
3931 << ", AdvanceAmount=" << AdvanceAmount
3932 << ", RemainingLoopCount=" << RemainingLoopCount
3936 *E
= malformedError("bad bind info (bad opcode value 0x" +
3937 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3938 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3945 uint64_t MachOBindEntry::readULEB128(const char **error
) {
3947 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3949 if (Ptr
> Opcodes
.end())
3950 Ptr
= Opcodes
.end();
3954 int64_t MachOBindEntry::readSLEB128(const char **error
) {
3956 int64_t Result
= decodeSLEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3958 if (Ptr
> Opcodes
.end())
3959 Ptr
= Opcodes
.end();
3963 int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex
; }
3965 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset
; }
3967 StringRef
MachOBindEntry::typeName() const {
3969 case MachO::BIND_TYPE_POINTER
:
3971 case MachO::BIND_TYPE_TEXT_ABSOLUTE32
:
3972 return "text abs32";
3973 case MachO::BIND_TYPE_TEXT_PCREL32
:
3974 return "text rel32";
3979 StringRef
MachOBindEntry::symbolName() const { return SymbolName
; }
3981 int64_t MachOBindEntry::addend() const { return Addend
; }
3983 uint32_t MachOBindEntry::flags() const { return Flags
; }
3985 int MachOBindEntry::ordinal() const { return Ordinal
; }
3987 // For use with the SegIndex of a checked Mach-O Bind entry
3988 // to get the segment name.
3989 StringRef
MachOBindEntry::segmentName() const {
3990 return O
->BindRebaseSegmentName(SegmentIndex
);
3993 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3994 // to get the section name.
3995 StringRef
MachOBindEntry::sectionName() const {
3996 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3999 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
4000 // to get the address.
4001 uint64_t MachOBindEntry::address() const {
4002 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
4005 bool MachOBindEntry::operator==(const MachOBindEntry
&Other
) const {
4006 #ifdef EXPENSIVE_CHECKS
4007 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
4009 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
4011 return (Ptr
== Other
.Ptr
) &&
4012 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
4013 (Done
== Other
.Done
);
4016 // Build table of sections so SegIndex/SegOffset pairs can be translated.
4017 BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile
*Obj
) {
4018 uint32_t CurSegIndex
= Obj
->hasPageZeroSegment() ? 1 : 0;
4019 StringRef CurSegName
;
4020 uint64_t CurSegAddress
;
4021 for (const SectionRef
&Section
: Obj
->sections()) {
4023 Expected
<StringRef
> NameOrErr
= Section
.getName();
4025 consumeError(NameOrErr
.takeError());
4027 Info
.SectionName
= *NameOrErr
;
4028 Info
.Address
= Section
.getAddress();
4029 Info
.Size
= Section
.getSize();
4031 Obj
->getSectionFinalSegmentName(Section
.getRawDataRefImpl());
4032 if (!Info
.SegmentName
.equals(CurSegName
)) {
4034 CurSegName
= Info
.SegmentName
;
4035 CurSegAddress
= Info
.Address
;
4037 Info
.SegmentIndex
= CurSegIndex
- 1;
4038 Info
.OffsetInSegment
= Info
.Address
- CurSegAddress
;
4039 Info
.SegmentStartAddress
= CurSegAddress
;
4040 Sections
.push_back(Info
);
4042 MaxSegIndex
= CurSegIndex
;
4045 // For use with a SegIndex, SegOffset, and PointerSize triple in
4046 // MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
4048 // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
4049 // that fully contains a pointer at that location. Multiple fixups in a bind
4050 // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
4051 // be tested via the Count and Skip parameters.
4052 const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex
,
4054 uint8_t PointerSize
,
4058 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4059 if (SegIndex
>= MaxSegIndex
)
4060 return "bad segIndex (too large)";
4061 for (uint32_t i
= 0; i
< Count
; ++i
) {
4062 uint32_t Start
= SegOffset
+ i
* (PointerSize
+ Skip
);
4063 uint32_t End
= Start
+ PointerSize
;
4065 for (const SectionInfo
&SI
: Sections
) {
4066 if (SI
.SegmentIndex
!= SegIndex
)
4068 if ((SI
.OffsetInSegment
<=Start
) && (Start
<(SI
.OffsetInSegment
+SI
.Size
))) {
4069 if (End
<= SI
.OffsetInSegment
+ SI
.Size
) {
4074 return "bad offset, extends beyond section boundary";
4078 return "bad offset, not in section";
4083 // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4084 // to get the segment name.
4085 StringRef
BindRebaseSegInfo::segmentName(int32_t SegIndex
) {
4086 for (const SectionInfo
&SI
: Sections
) {
4087 if (SI
.SegmentIndex
== SegIndex
)
4088 return SI
.SegmentName
;
4090 llvm_unreachable("invalid SegIndex");
4093 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4094 // to get the SectionInfo.
4095 const BindRebaseSegInfo::SectionInfo
&BindRebaseSegInfo::findSection(
4096 int32_t SegIndex
, uint64_t SegOffset
) {
4097 for (const SectionInfo
&SI
: Sections
) {
4098 if (SI
.SegmentIndex
!= SegIndex
)
4100 if (SI
.OffsetInSegment
> SegOffset
)
4102 if (SegOffset
>= (SI
.OffsetInSegment
+ SI
.Size
))
4106 llvm_unreachable("SegIndex and SegOffset not in any section");
4109 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4110 // entry to get the section name.
4111 StringRef
BindRebaseSegInfo::sectionName(int32_t SegIndex
,
4112 uint64_t SegOffset
) {
4113 return findSection(SegIndex
, SegOffset
).SectionName
;
4116 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4117 // entry to get the address.
4118 uint64_t BindRebaseSegInfo::address(uint32_t SegIndex
, uint64_t OffsetInSeg
) {
4119 const SectionInfo
&SI
= findSection(SegIndex
, OffsetInSeg
);
4120 return SI
.SegmentStartAddress
+ OffsetInSeg
;
4123 iterator_range
<bind_iterator
>
4124 MachOObjectFile::bindTable(Error
&Err
, MachOObjectFile
*O
,
4125 ArrayRef
<uint8_t> Opcodes
, bool is64
,
4126 MachOBindEntry::Kind BKind
) {
4127 if (O
->BindRebaseSectionTable
== nullptr)
4128 O
->BindRebaseSectionTable
= std::make_unique
<BindRebaseSegInfo
>(O
);
4129 MachOBindEntry
Start(&Err
, O
, Opcodes
, is64
, BKind
);
4130 Start
.moveToFirst();
4132 MachOBindEntry
Finish(&Err
, O
, Opcodes
, is64
, BKind
);
4135 return make_range(bind_iterator(Start
), bind_iterator(Finish
));
4138 iterator_range
<bind_iterator
> MachOObjectFile::bindTable(Error
&Err
) {
4139 return bindTable(Err
, this, getDyldInfoBindOpcodes(), is64Bit(),
4140 MachOBindEntry::Kind::Regular
);
4143 iterator_range
<bind_iterator
> MachOObjectFile::lazyBindTable(Error
&Err
) {
4144 return bindTable(Err
, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4145 MachOBindEntry::Kind::Lazy
);
4148 iterator_range
<bind_iterator
> MachOObjectFile::weakBindTable(Error
&Err
) {
4149 return bindTable(Err
, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
4150 MachOBindEntry::Kind::Weak
);
4153 MachOObjectFile::load_command_iterator
4154 MachOObjectFile::begin_load_commands() const {
4155 return LoadCommands
.begin();
4158 MachOObjectFile::load_command_iterator
4159 MachOObjectFile::end_load_commands() const {
4160 return LoadCommands
.end();
4163 iterator_range
<MachOObjectFile::load_command_iterator
>
4164 MachOObjectFile::load_commands() const {
4165 return make_range(begin_load_commands(), end_load_commands());
4169 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec
) const {
4170 ArrayRef
<char> Raw
= getSectionRawFinalSegmentName(Sec
);
4171 return parseSegmentOrSectionName(Raw
.data());
4175 MachOObjectFile::getSectionRawName(DataRefImpl Sec
) const {
4176 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4177 const section_base
*Base
=
4178 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4179 return makeArrayRef(Base
->sectname
);
4183 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec
) const {
4184 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4185 const section_base
*Base
=
4186 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4187 return makeArrayRef(Base
->segname
);
4191 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info
&RE
)
4193 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64
)
4195 return getPlainRelocationAddress(RE
) & MachO::R_SCATTERED
;
4198 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4199 const MachO::any_relocation_info
&RE
) const {
4200 if (isLittleEndian())
4201 return RE
.r_word1
& 0xffffff;
4202 return RE
.r_word1
>> 8;
4205 bool MachOObjectFile::getPlainRelocationExternal(
4206 const MachO::any_relocation_info
&RE
) const {
4207 if (isLittleEndian())
4208 return (RE
.r_word1
>> 27) & 1;
4209 return (RE
.r_word1
>> 4) & 1;
4212 bool MachOObjectFile::getScatteredRelocationScattered(
4213 const MachO::any_relocation_info
&RE
) const {
4214 return RE
.r_word0
>> 31;
4217 uint32_t MachOObjectFile::getScatteredRelocationValue(
4218 const MachO::any_relocation_info
&RE
) const {
4222 uint32_t MachOObjectFile::getScatteredRelocationType(
4223 const MachO::any_relocation_info
&RE
) const {
4224 return (RE
.r_word0
>> 24) & 0xf;
4227 unsigned MachOObjectFile::getAnyRelocationAddress(
4228 const MachO::any_relocation_info
&RE
) const {
4229 if (isRelocationScattered(RE
))
4230 return getScatteredRelocationAddress(RE
);
4231 return getPlainRelocationAddress(RE
);
4234 unsigned MachOObjectFile::getAnyRelocationPCRel(
4235 const MachO::any_relocation_info
&RE
) const {
4236 if (isRelocationScattered(RE
))
4237 return getScatteredRelocationPCRel(RE
);
4238 return getPlainRelocationPCRel(*this, RE
);
4241 unsigned MachOObjectFile::getAnyRelocationLength(
4242 const MachO::any_relocation_info
&RE
) const {
4243 if (isRelocationScattered(RE
))
4244 return getScatteredRelocationLength(RE
);
4245 return getPlainRelocationLength(*this, RE
);
4249 MachOObjectFile::getAnyRelocationType(
4250 const MachO::any_relocation_info
&RE
) const {
4251 if (isRelocationScattered(RE
))
4252 return getScatteredRelocationType(RE
);
4253 return getPlainRelocationType(*this, RE
);
4257 MachOObjectFile::getAnyRelocationSection(
4258 const MachO::any_relocation_info
&RE
) const {
4259 if (isRelocationScattered(RE
) || getPlainRelocationExternal(RE
))
4260 return *section_end();
4261 unsigned SecNum
= getPlainRelocationSymbolNum(RE
);
4262 if (SecNum
== MachO::R_ABS
|| SecNum
> Sections
.size())
4263 return *section_end();
4265 DRI
.d
.a
= SecNum
- 1;
4266 return SectionRef(DRI
, this);
4269 MachO::section
MachOObjectFile::getSection(DataRefImpl DRI
) const {
4270 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4271 return getStruct
<MachO::section
>(*this, Sections
[DRI
.d
.a
]);
4274 MachO::section_64
MachOObjectFile::getSection64(DataRefImpl DRI
) const {
4275 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4276 return getStruct
<MachO::section_64
>(*this, Sections
[DRI
.d
.a
]);
4279 MachO::section
MachOObjectFile::getSection(const LoadCommandInfo
&L
,
4280 unsigned Index
) const {
4281 const char *Sec
= getSectionPtr(*this, L
, Index
);
4282 return getStruct
<MachO::section
>(*this, Sec
);
4285 MachO::section_64
MachOObjectFile::getSection64(const LoadCommandInfo
&L
,
4286 unsigned Index
) const {
4287 const char *Sec
= getSectionPtr(*this, L
, Index
);
4288 return getStruct
<MachO::section_64
>(*this, Sec
);
4292 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI
) const {
4293 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4294 return getStruct
<MachO::nlist
>(*this, P
);
4298 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI
) const {
4299 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4300 return getStruct
<MachO::nlist_64
>(*this, P
);
4303 MachO::linkedit_data_command
4304 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo
&L
) const {
4305 return getStruct
<MachO::linkedit_data_command
>(*this, L
.Ptr
);
4308 MachO::segment_command
4309 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo
&L
) const {
4310 return getStruct
<MachO::segment_command
>(*this, L
.Ptr
);
4313 MachO::segment_command_64
4314 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo
&L
) const {
4315 return getStruct
<MachO::segment_command_64
>(*this, L
.Ptr
);
4318 MachO::linker_option_command
4319 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo
&L
) const {
4320 return getStruct
<MachO::linker_option_command
>(*this, L
.Ptr
);
4323 MachO::version_min_command
4324 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo
&L
) const {
4325 return getStruct
<MachO::version_min_command
>(*this, L
.Ptr
);
4329 MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo
&L
) const {
4330 return getStruct
<MachO::note_command
>(*this, L
.Ptr
);
4333 MachO::build_version_command
4334 MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo
&L
) const {
4335 return getStruct
<MachO::build_version_command
>(*this, L
.Ptr
);
4338 MachO::build_tool_version
4339 MachOObjectFile::getBuildToolVersion(unsigned index
) const {
4340 return getStruct
<MachO::build_tool_version
>(*this, BuildTools
[index
]);
4343 MachO::dylib_command
4344 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo
&L
) const {
4345 return getStruct
<MachO::dylib_command
>(*this, L
.Ptr
);
4348 MachO::dyld_info_command
4349 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo
&L
) const {
4350 return getStruct
<MachO::dyld_info_command
>(*this, L
.Ptr
);
4353 MachO::dylinker_command
4354 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo
&L
) const {
4355 return getStruct
<MachO::dylinker_command
>(*this, L
.Ptr
);
4359 MachOObjectFile::getUuidCommand(const LoadCommandInfo
&L
) const {
4360 return getStruct
<MachO::uuid_command
>(*this, L
.Ptr
);
4363 MachO::rpath_command
4364 MachOObjectFile::getRpathCommand(const LoadCommandInfo
&L
) const {
4365 return getStruct
<MachO::rpath_command
>(*this, L
.Ptr
);
4368 MachO::source_version_command
4369 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo
&L
) const {
4370 return getStruct
<MachO::source_version_command
>(*this, L
.Ptr
);
4373 MachO::entry_point_command
4374 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo
&L
) const {
4375 return getStruct
<MachO::entry_point_command
>(*this, L
.Ptr
);
4378 MachO::encryption_info_command
4379 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo
&L
) const {
4380 return getStruct
<MachO::encryption_info_command
>(*this, L
.Ptr
);
4383 MachO::encryption_info_command_64
4384 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo
&L
) const {
4385 return getStruct
<MachO::encryption_info_command_64
>(*this, L
.Ptr
);
4388 MachO::sub_framework_command
4389 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo
&L
) const {
4390 return getStruct
<MachO::sub_framework_command
>(*this, L
.Ptr
);
4393 MachO::sub_umbrella_command
4394 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo
&L
) const {
4395 return getStruct
<MachO::sub_umbrella_command
>(*this, L
.Ptr
);
4398 MachO::sub_library_command
4399 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo
&L
) const {
4400 return getStruct
<MachO::sub_library_command
>(*this, L
.Ptr
);
4403 MachO::sub_client_command
4404 MachOObjectFile::getSubClientCommand(const LoadCommandInfo
&L
) const {
4405 return getStruct
<MachO::sub_client_command
>(*this, L
.Ptr
);
4408 MachO::routines_command
4409 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo
&L
) const {
4410 return getStruct
<MachO::routines_command
>(*this, L
.Ptr
);
4413 MachO::routines_command_64
4414 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo
&L
) const {
4415 return getStruct
<MachO::routines_command_64
>(*this, L
.Ptr
);
4418 MachO::thread_command
4419 MachOObjectFile::getThreadCommand(const LoadCommandInfo
&L
) const {
4420 return getStruct
<MachO::thread_command
>(*this, L
.Ptr
);
4423 MachO::any_relocation_info
4424 MachOObjectFile::getRelocation(DataRefImpl Rel
) const {
4426 if (getHeader().filetype
== MachO::MH_OBJECT
) {
4430 MachO::section_64 Sect
= getSection64(Sec
);
4431 Offset
= Sect
.reloff
;
4433 MachO::section Sect
= getSection(Sec
);
4434 Offset
= Sect
.reloff
;
4437 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
4439 Offset
= DysymtabLoadCmd
.extreloff
; // Offset to the external relocations
4441 Offset
= DysymtabLoadCmd
.locreloff
; // Offset to the local relocations
4444 auto P
= reinterpret_cast<const MachO::any_relocation_info
*>(
4445 getPtr(*this, Offset
)) + Rel
.d
.b
;
4446 return getStruct
<MachO::any_relocation_info
>(
4447 *this, reinterpret_cast<const char *>(P
));
4450 MachO::data_in_code_entry
4451 MachOObjectFile::getDice(DataRefImpl Rel
) const {
4452 const char *P
= reinterpret_cast<const char *>(Rel
.p
);
4453 return getStruct
<MachO::data_in_code_entry
>(*this, P
);
4456 const MachO::mach_header
&MachOObjectFile::getHeader() const {
4460 const MachO::mach_header_64
&MachOObjectFile::getHeader64() const {
4465 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4466 const MachO::dysymtab_command
&DLC
,
4467 unsigned Index
) const {
4468 uint64_t Offset
= DLC
.indirectsymoff
+ Index
* sizeof(uint32_t);
4469 return getStruct
<uint32_t>(*this, getPtr(*this, Offset
));
4472 MachO::data_in_code_entry
4473 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset
,
4474 unsigned Index
) const {
4475 uint64_t Offset
= DataOffset
+ Index
* sizeof(MachO::data_in_code_entry
);
4476 return getStruct
<MachO::data_in_code_entry
>(*this, getPtr(*this, Offset
));
4479 MachO::symtab_command
MachOObjectFile::getSymtabLoadCommand() const {
4481 return getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
4483 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4484 MachO::symtab_command Cmd
;
4485 Cmd
.cmd
= MachO::LC_SYMTAB
;
4486 Cmd
.cmdsize
= sizeof(MachO::symtab_command
);
4494 MachO::dysymtab_command
MachOObjectFile::getDysymtabLoadCommand() const {
4495 if (DysymtabLoadCmd
)
4496 return getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
4498 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4499 MachO::dysymtab_command Cmd
;
4500 Cmd
.cmd
= MachO::LC_DYSYMTAB
;
4501 Cmd
.cmdsize
= sizeof(MachO::dysymtab_command
);
4512 Cmd
.extrefsymoff
= 0;
4513 Cmd
.nextrefsyms
= 0;
4514 Cmd
.indirectsymoff
= 0;
4515 Cmd
.nindirectsyms
= 0;
4523 MachO::linkedit_data_command
4524 MachOObjectFile::getDataInCodeLoadCommand() const {
4525 if (DataInCodeLoadCmd
)
4526 return getStruct
<MachO::linkedit_data_command
>(*this, DataInCodeLoadCmd
);
4528 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4529 MachO::linkedit_data_command Cmd
;
4530 Cmd
.cmd
= MachO::LC_DATA_IN_CODE
;
4531 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4537 MachO::linkedit_data_command
4538 MachOObjectFile::getLinkOptHintsLoadCommand() const {
4539 if (LinkOptHintsLoadCmd
)
4540 return getStruct
<MachO::linkedit_data_command
>(*this, LinkOptHintsLoadCmd
);
4542 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4544 MachO::linkedit_data_command Cmd
;
4545 Cmd
.cmd
= MachO::LC_LINKER_OPTIMIZATION_HINT
;
4546 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4552 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4553 if (!DyldInfoLoadCmd
)
4556 auto DyldInfoOrErr
=
4557 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4560 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4561 const uint8_t *Ptr
=
4562 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.rebase_off
));
4563 return makeArrayRef(Ptr
, DyldInfo
.rebase_size
);
4566 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4567 if (!DyldInfoLoadCmd
)
4570 auto DyldInfoOrErr
=
4571 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4574 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4575 const uint8_t *Ptr
=
4576 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.bind_off
));
4577 return makeArrayRef(Ptr
, DyldInfo
.bind_size
);
4580 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4581 if (!DyldInfoLoadCmd
)
4584 auto DyldInfoOrErr
=
4585 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4588 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4589 const uint8_t *Ptr
=
4590 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.weak_bind_off
));
4591 return makeArrayRef(Ptr
, DyldInfo
.weak_bind_size
);
4594 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4595 if (!DyldInfoLoadCmd
)
4598 auto DyldInfoOrErr
=
4599 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4602 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4603 const uint8_t *Ptr
=
4604 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.lazy_bind_off
));
4605 return makeArrayRef(Ptr
, DyldInfo
.lazy_bind_size
);
4608 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4609 if (!DyldInfoLoadCmd
)
4612 auto DyldInfoOrErr
=
4613 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4616 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4617 const uint8_t *Ptr
=
4618 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.export_off
));
4619 return makeArrayRef(Ptr
, DyldInfo
.export_size
);
4622 ArrayRef
<uint8_t> MachOObjectFile::getUuid() const {
4625 // Returning a pointer is fine as uuid doesn't need endian swapping.
4626 const char *Ptr
= UuidLoadCmd
+ offsetof(MachO::uuid_command
, uuid
);
4627 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr
), 16);
4630 StringRef
MachOObjectFile::getStringTableData() const {
4631 MachO::symtab_command S
= getSymtabLoadCommand();
4632 return getData().substr(S
.stroff
, S
.strsize
);
4635 bool MachOObjectFile::is64Bit() const {
4636 return getType() == getMachOType(false, true) ||
4637 getType() == getMachOType(true, true);
4640 void MachOObjectFile::ReadULEB128s(uint64_t Index
,
4641 SmallVectorImpl
<uint64_t> &Out
) const {
4642 DataExtractor
extractor(ObjectFile::getData(), true, 0);
4644 uint64_t offset
= Index
;
4646 while (uint64_t delta
= extractor
.getULEB128(&offset
)) {
4648 Out
.push_back(data
);
4652 bool MachOObjectFile::isRelocatableObject() const {
4653 return getHeader().filetype
== MachO::MH_OBJECT
;
4656 Expected
<std::unique_ptr
<MachOObjectFile
>>
4657 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer
,
4658 uint32_t UniversalCputype
,
4659 uint32_t UniversalIndex
) {
4660 StringRef Magic
= Buffer
.getBuffer().slice(0, 4);
4661 if (Magic
== "\xFE\xED\xFA\xCE")
4662 return MachOObjectFile::create(Buffer
, false, false,
4663 UniversalCputype
, UniversalIndex
);
4664 if (Magic
== "\xCE\xFA\xED\xFE")
4665 return MachOObjectFile::create(Buffer
, true, false,
4666 UniversalCputype
, UniversalIndex
);
4667 if (Magic
== "\xFE\xED\xFA\xCF")
4668 return MachOObjectFile::create(Buffer
, false, true,
4669 UniversalCputype
, UniversalIndex
);
4670 if (Magic
== "\xCF\xFA\xED\xFE")
4671 return MachOObjectFile::create(Buffer
, true, true,
4672 UniversalCputype
, UniversalIndex
);
4673 return make_error
<GenericBinaryError
>("Unrecognized MachO magic number",
4674 object_error::invalid_file_type
);
4677 StringRef
MachOObjectFile::mapDebugSectionName(StringRef Name
) const {
4678 return StringSwitch
<StringRef
>(Name
)
4679 .Case("debug_str_offs", "debug_str_offsets")