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/STLExtras.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/ADT/bit.h"
21 #include "llvm/BinaryFormat/MachO.h"
22 #include "llvm/BinaryFormat/Swift.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/Errc.h"
30 #include "llvm/Support/Error.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/FileSystem.h"
33 #include "llvm/Support/Format.h"
34 #include "llvm/Support/LEB128.h"
35 #include "llvm/Support/MemoryBufferRef.h"
36 #include "llvm/Support/Path.h"
37 #include "llvm/Support/SwapByteOrder.h"
38 #include "llvm/Support/raw_ostream.h"
39 #include "llvm/TargetParser/Host.h"
40 #include "llvm/TargetParser/Triple.h"
49 #include <system_error>
52 using namespace object
;
61 } // end anonymous namespace
63 static Error
malformedError(const Twine
&Msg
) {
64 return make_error
<GenericBinaryError
>("truncated or malformed object (" +
66 object_error::parse_failed
);
69 // FIXME: Replace all uses of this function with getStructOrErr.
71 static T
getStruct(const MachOObjectFile
&O
, const char *P
) {
72 // Don't read before the beginning or past the end of the file
73 if (P
< O
.getData().begin() || P
+ sizeof(T
) > O
.getData().end())
74 report_fatal_error("Malformed MachO file.");
77 memcpy(&Cmd
, P
, sizeof(T
));
78 if (O
.isLittleEndian() != sys::IsLittleEndianHost
)
79 MachO::swapStruct(Cmd
);
84 static Expected
<T
> getStructOrErr(const MachOObjectFile
&O
, const char *P
) {
85 // Don't read before the beginning or past the end of the file
86 if (P
< O
.getData().begin() || P
+ sizeof(T
) > O
.getData().end())
87 return malformedError("Structure read out-of-range");
90 memcpy(&Cmd
, P
, sizeof(T
));
91 if (O
.isLittleEndian() != sys::IsLittleEndianHost
)
92 MachO::swapStruct(Cmd
);
97 getSectionPtr(const MachOObjectFile
&O
, MachOObjectFile::LoadCommandInfo L
,
99 uintptr_t CommandAddr
= reinterpret_cast<uintptr_t>(L
.Ptr
);
101 bool Is64
= O
.is64Bit();
102 unsigned SegmentLoadSize
= Is64
? sizeof(MachO::segment_command_64
) :
103 sizeof(MachO::segment_command
);
104 unsigned SectionSize
= Is64
? sizeof(MachO::section_64
) :
105 sizeof(MachO::section
);
107 uintptr_t SectionAddr
= CommandAddr
+ SegmentLoadSize
+ Sec
* SectionSize
;
108 return reinterpret_cast<const char*>(SectionAddr
);
111 static const char *getPtr(const MachOObjectFile
&O
, size_t Offset
,
112 size_t MachOFilesetEntryOffset
= 0) {
113 assert(Offset
<= O
.getData().size() &&
114 MachOFilesetEntryOffset
<= O
.getData().size());
115 return O
.getData().data() + Offset
+ MachOFilesetEntryOffset
;
118 static MachO::nlist_base
119 getSymbolTableEntryBase(const MachOObjectFile
&O
, DataRefImpl DRI
) {
120 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
121 return getStruct
<MachO::nlist_base
>(O
, P
);
124 static StringRef
parseSegmentOrSectionName(const char *P
) {
128 // Not null terminated, so this is a 16 char string.
129 return StringRef(P
, 16);
132 static unsigned getCPUType(const MachOObjectFile
&O
) {
133 return O
.getHeader().cputype
;
136 static unsigned getCPUSubType(const MachOObjectFile
&O
) {
137 return O
.getHeader().cpusubtype
;
141 getPlainRelocationAddress(const MachO::any_relocation_info
&RE
) {
146 getScatteredRelocationAddress(const MachO::any_relocation_info
&RE
) {
147 return RE
.r_word0
& 0xffffff;
150 static bool getPlainRelocationPCRel(const MachOObjectFile
&O
,
151 const MachO::any_relocation_info
&RE
) {
152 if (O
.isLittleEndian())
153 return (RE
.r_word1
>> 24) & 1;
154 return (RE
.r_word1
>> 7) & 1;
158 getScatteredRelocationPCRel(const MachO::any_relocation_info
&RE
) {
159 return (RE
.r_word0
>> 30) & 1;
162 static unsigned getPlainRelocationLength(const MachOObjectFile
&O
,
163 const MachO::any_relocation_info
&RE
) {
164 if (O
.isLittleEndian())
165 return (RE
.r_word1
>> 25) & 3;
166 return (RE
.r_word1
>> 5) & 3;
170 getScatteredRelocationLength(const MachO::any_relocation_info
&RE
) {
171 return (RE
.r_word0
>> 28) & 3;
174 static unsigned getPlainRelocationType(const MachOObjectFile
&O
,
175 const MachO::any_relocation_info
&RE
) {
176 if (O
.isLittleEndian())
177 return RE
.r_word1
>> 28;
178 return RE
.r_word1
& 0xf;
181 static uint32_t getSectionFlags(const MachOObjectFile
&O
,
184 MachO::section_64 Sect
= O
.getSection64(Sec
);
187 MachO::section Sect
= O
.getSection(Sec
);
191 static Expected
<MachOObjectFile::LoadCommandInfo
>
192 getLoadCommandInfo(const MachOObjectFile
&Obj
, const char *Ptr
,
193 uint32_t LoadCommandIndex
) {
194 if (auto CmdOrErr
= getStructOrErr
<MachO::load_command
>(Obj
, Ptr
)) {
195 if (CmdOrErr
->cmdsize
+ Ptr
> Obj
.getData().end())
196 return malformedError("load command " + Twine(LoadCommandIndex
) +
197 " extends past end of file");
198 if (CmdOrErr
->cmdsize
< 8)
199 return malformedError("load command " + Twine(LoadCommandIndex
) +
200 " with size less than 8 bytes");
201 return MachOObjectFile::LoadCommandInfo({Ptr
, *CmdOrErr
});
203 return CmdOrErr
.takeError();
206 static Expected
<MachOObjectFile::LoadCommandInfo
>
207 getFirstLoadCommandInfo(const MachOObjectFile
&Obj
) {
208 unsigned HeaderSize
= Obj
.is64Bit() ? sizeof(MachO::mach_header_64
)
209 : sizeof(MachO::mach_header
);
210 if (sizeof(MachO::load_command
) > Obj
.getHeader().sizeofcmds
)
211 return malformedError("load command 0 extends past the end all load "
212 "commands in the file");
213 return getLoadCommandInfo(
214 Obj
, getPtr(Obj
, HeaderSize
, Obj
.getMachOFilesetEntryOffset()), 0);
217 static Expected
<MachOObjectFile::LoadCommandInfo
>
218 getNextLoadCommandInfo(const MachOObjectFile
&Obj
, uint32_t LoadCommandIndex
,
219 const MachOObjectFile::LoadCommandInfo
&L
) {
220 unsigned HeaderSize
= Obj
.is64Bit() ? sizeof(MachO::mach_header_64
)
221 : sizeof(MachO::mach_header
);
222 if (L
.Ptr
+ L
.C
.cmdsize
+ sizeof(MachO::load_command
) >
223 Obj
.getData().data() + Obj
.getMachOFilesetEntryOffset() + HeaderSize
+
224 Obj
.getHeader().sizeofcmds
)
225 return malformedError("load command " + Twine(LoadCommandIndex
+ 1) +
226 " extends past the end all load commands in the file");
227 return getLoadCommandInfo(Obj
, L
.Ptr
+ L
.C
.cmdsize
, LoadCommandIndex
+ 1);
230 template <typename T
>
231 static void parseHeader(const MachOObjectFile
&Obj
, T
&Header
,
233 if (sizeof(T
) > Obj
.getData().size()) {
234 Err
= malformedError("the mach header extends past the end of the "
238 if (auto HeaderOrErr
= getStructOrErr
<T
>(
239 Obj
, getPtr(Obj
, 0, Obj
.getMachOFilesetEntryOffset())))
240 Header
= *HeaderOrErr
;
242 Err
= HeaderOrErr
.takeError();
245 // This is used to check for overlapping of Mach-O elements.
246 struct MachOElement
{
252 static Error
checkOverlappingElement(std::list
<MachOElement
> &Elements
,
253 uint64_t Offset
, uint64_t Size
,
256 return Error::success();
258 for (auto it
= Elements
.begin(); it
!= Elements
.end(); ++it
) {
260 if ((Offset
>= E
.Offset
&& Offset
< E
.Offset
+ E
.Size
) ||
261 (Offset
+ Size
> E
.Offset
&& Offset
+ Size
< E
.Offset
+ E
.Size
) ||
262 (Offset
<= E
.Offset
&& Offset
+ Size
>= E
.Offset
+ E
.Size
))
263 return malformedError(Twine(Name
) + " at offset " + Twine(Offset
) +
264 " with a size of " + Twine(Size
) + ", overlaps " +
265 E
.Name
+ " at offset " + Twine(E
.Offset
) + " with "
266 "a size of " + Twine(E
.Size
));
269 if (nt
!= Elements
.end()) {
271 if (Offset
+ Size
<= N
.Offset
) {
272 Elements
.insert(nt
, {Offset
, Size
, Name
});
273 return Error::success();
277 Elements
.push_back({Offset
, Size
, Name
});
278 return Error::success();
281 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
282 // sections to \param Sections, and optionally sets
283 // \param IsPageZeroSegment to true.
284 template <typename Segment
, typename Section
>
285 static Error
parseSegmentLoadCommand(
286 const MachOObjectFile
&Obj
, const MachOObjectFile::LoadCommandInfo
&Load
,
287 SmallVectorImpl
<const char *> &Sections
, bool &IsPageZeroSegment
,
288 uint32_t LoadCommandIndex
, const char *CmdName
, uint64_t SizeOfHeaders
,
289 std::list
<MachOElement
> &Elements
) {
290 const unsigned SegmentLoadSize
= sizeof(Segment
);
291 if (Load
.C
.cmdsize
< SegmentLoadSize
)
292 return malformedError("load command " + Twine(LoadCommandIndex
) +
293 " " + CmdName
+ " cmdsize too small");
294 if (auto SegOrErr
= getStructOrErr
<Segment
>(Obj
, Load
.Ptr
)) {
295 Segment S
= SegOrErr
.get();
296 const unsigned SectionSize
= sizeof(Section
);
297 uint64_t FileSize
= Obj
.getData().size();
298 if (S
.nsects
> std::numeric_limits
<uint32_t>::max() / SectionSize
||
299 S
.nsects
* SectionSize
> Load
.C
.cmdsize
- SegmentLoadSize
)
300 return malformedError("load command " + Twine(LoadCommandIndex
) +
301 " inconsistent cmdsize in " + CmdName
+
302 " for the number of sections");
303 for (unsigned J
= 0; J
< S
.nsects
; ++J
) {
304 const char *Sec
= getSectionPtr(Obj
, Load
, J
);
305 Sections
.push_back(Sec
);
306 auto SectionOrErr
= getStructOrErr
<Section
>(Obj
, Sec
);
308 return SectionOrErr
.takeError();
309 Section s
= SectionOrErr
.get();
310 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
311 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
312 s
.flags
!= MachO::S_ZEROFILL
&&
313 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
315 return malformedError("offset field of section " + Twine(J
) + " in " +
316 CmdName
+ " command " + Twine(LoadCommandIndex
) +
317 " extends past the end of the file");
318 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
319 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
320 s
.flags
!= MachO::S_ZEROFILL
&&
321 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&& S
.fileoff
== 0 &&
322 s
.offset
< SizeOfHeaders
&& s
.size
!= 0)
323 return malformedError("offset field of section " + Twine(J
) + " in " +
324 CmdName
+ " command " + Twine(LoadCommandIndex
) +
325 " not past the headers of the file");
326 uint64_t BigSize
= s
.offset
;
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("offset field plus size field of section " +
334 Twine(J
) + " in " + CmdName
+ " command " +
335 Twine(LoadCommandIndex
) +
336 " extends past the end of the file");
337 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
338 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
339 s
.flags
!= MachO::S_ZEROFILL
&&
340 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
342 return malformedError("size field of section " +
343 Twine(J
) + " in " + CmdName
+ " command " +
344 Twine(LoadCommandIndex
) +
345 " greater than the segment");
346 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
347 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&& s
.size
!= 0 &&
349 return malformedError("addr field of section " + Twine(J
) + " in " +
350 CmdName
+ " command " + Twine(LoadCommandIndex
) +
351 " less than the segment's vmaddr");
354 uint64_t BigEnd
= S
.vmaddr
;
356 if (S
.vmsize
!= 0 && s
.size
!= 0 && BigSize
> BigEnd
)
357 return malformedError("addr field plus size of section " + Twine(J
) +
358 " in " + CmdName
+ " command " +
359 Twine(LoadCommandIndex
) +
360 " greater than than "
361 "the segment's vmaddr plus vmsize");
362 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
363 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
364 s
.flags
!= MachO::S_ZEROFILL
&&
365 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
)
366 if (Error Err
= checkOverlappingElement(Elements
, s
.offset
, s
.size
,
369 if (s
.reloff
> FileSize
)
370 return malformedError("reloff field of section " + Twine(J
) + " in " +
371 CmdName
+ " command " + Twine(LoadCommandIndex
) +
372 " extends past the end of the file");
374 BigSize
*= sizeof(struct MachO::relocation_info
);
376 if (BigSize
> FileSize
)
377 return malformedError("reloff field plus nreloc field times sizeof("
378 "struct relocation_info) of section " +
379 Twine(J
) + " in " + CmdName
+ " command " +
380 Twine(LoadCommandIndex
) +
381 " extends past the end of the file");
382 if (Error Err
= checkOverlappingElement(Elements
, s
.reloff
, s
.nreloc
*
384 MachO::relocation_info
),
385 "section relocation entries"))
388 if (S
.fileoff
> FileSize
)
389 return malformedError("load command " + Twine(LoadCommandIndex
) +
390 " fileoff field in " + CmdName
+
391 " extends past the end of the file");
392 uint64_t BigSize
= S
.fileoff
;
393 BigSize
+= S
.filesize
;
394 if (BigSize
> FileSize
)
395 return malformedError("load command " + Twine(LoadCommandIndex
) +
396 " fileoff field plus filesize field in " +
397 CmdName
+ " extends past the end of the file");
398 if (S
.vmsize
!= 0 && S
.filesize
> S
.vmsize
)
399 return malformedError("load command " + Twine(LoadCommandIndex
) +
400 " filesize field in " + CmdName
+
401 " greater than vmsize field");
402 IsPageZeroSegment
|= StringRef("__PAGEZERO").equals(S
.segname
);
404 return SegOrErr
.takeError();
406 return Error::success();
409 static Error
checkSymtabCommand(const MachOObjectFile
&Obj
,
410 const MachOObjectFile::LoadCommandInfo
&Load
,
411 uint32_t LoadCommandIndex
,
412 const char **SymtabLoadCmd
,
413 std::list
<MachOElement
> &Elements
) {
414 if (Load
.C
.cmdsize
< sizeof(MachO::symtab_command
))
415 return malformedError("load command " + Twine(LoadCommandIndex
) +
416 " LC_SYMTAB cmdsize too small");
417 if (*SymtabLoadCmd
!= nullptr)
418 return malformedError("more than one LC_SYMTAB command");
419 auto SymtabOrErr
= getStructOrErr
<MachO::symtab_command
>(Obj
, Load
.Ptr
);
421 return SymtabOrErr
.takeError();
422 MachO::symtab_command Symtab
= SymtabOrErr
.get();
423 if (Symtab
.cmdsize
!= sizeof(MachO::symtab_command
))
424 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex
) +
425 " has incorrect cmdsize");
426 uint64_t FileSize
= Obj
.getData().size();
427 if (Symtab
.symoff
> FileSize
)
428 return malformedError("symoff field of LC_SYMTAB command " +
429 Twine(LoadCommandIndex
) + " extends past the end "
431 uint64_t SymtabSize
= Symtab
.nsyms
;
432 const char *struct_nlist_name
;
434 SymtabSize
*= sizeof(MachO::nlist_64
);
435 struct_nlist_name
= "struct nlist_64";
437 SymtabSize
*= sizeof(MachO::nlist
);
438 struct_nlist_name
= "struct nlist";
440 uint64_t BigSize
= SymtabSize
;
441 BigSize
+= Symtab
.symoff
;
442 if (BigSize
> FileSize
)
443 return malformedError("symoff field plus nsyms field times sizeof(" +
444 Twine(struct_nlist_name
) + ") of LC_SYMTAB command " +
445 Twine(LoadCommandIndex
) + " extends past the end "
447 if (Error Err
= checkOverlappingElement(Elements
, Symtab
.symoff
, SymtabSize
,
450 if (Symtab
.stroff
> FileSize
)
451 return malformedError("stroff field of LC_SYMTAB command " +
452 Twine(LoadCommandIndex
) + " extends past the end "
454 BigSize
= Symtab
.stroff
;
455 BigSize
+= Symtab
.strsize
;
456 if (BigSize
> FileSize
)
457 return malformedError("stroff field plus strsize field of LC_SYMTAB "
458 "command " + Twine(LoadCommandIndex
) + " extends "
459 "past the end of the file");
460 if (Error Err
= checkOverlappingElement(Elements
, Symtab
.stroff
,
461 Symtab
.strsize
, "string table"))
463 *SymtabLoadCmd
= Load
.Ptr
;
464 return Error::success();
467 static Error
checkDysymtabCommand(const MachOObjectFile
&Obj
,
468 const MachOObjectFile::LoadCommandInfo
&Load
,
469 uint32_t LoadCommandIndex
,
470 const char **DysymtabLoadCmd
,
471 std::list
<MachOElement
> &Elements
) {
472 if (Load
.C
.cmdsize
< sizeof(MachO::dysymtab_command
))
473 return malformedError("load command " + Twine(LoadCommandIndex
) +
474 " LC_DYSYMTAB cmdsize too small");
475 if (*DysymtabLoadCmd
!= nullptr)
476 return malformedError("more than one LC_DYSYMTAB command");
478 getStructOrErr
<MachO::dysymtab_command
>(Obj
, Load
.Ptr
);
480 return DysymtabOrErr
.takeError();
481 MachO::dysymtab_command Dysymtab
= DysymtabOrErr
.get();
482 if (Dysymtab
.cmdsize
!= sizeof(MachO::dysymtab_command
))
483 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex
) +
484 " has incorrect cmdsize");
485 uint64_t FileSize
= Obj
.getData().size();
486 if (Dysymtab
.tocoff
> FileSize
)
487 return malformedError("tocoff field of LC_DYSYMTAB command " +
488 Twine(LoadCommandIndex
) + " extends past the end of "
490 uint64_t BigSize
= Dysymtab
.ntoc
;
491 BigSize
*= sizeof(MachO::dylib_table_of_contents
);
492 BigSize
+= Dysymtab
.tocoff
;
493 if (BigSize
> FileSize
)
494 return malformedError("tocoff field plus ntoc field times sizeof(struct "
495 "dylib_table_of_contents) of LC_DYSYMTAB command " +
496 Twine(LoadCommandIndex
) + " extends past the end of "
498 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.tocoff
,
499 Dysymtab
.ntoc
* sizeof(struct
500 MachO::dylib_table_of_contents
),
501 "table of contents"))
503 if (Dysymtab
.modtaboff
> FileSize
)
504 return malformedError("modtaboff field of LC_DYSYMTAB command " +
505 Twine(LoadCommandIndex
) + " extends past the end of "
507 BigSize
= Dysymtab
.nmodtab
;
508 const char *struct_dylib_module_name
;
509 uint64_t sizeof_modtab
;
511 sizeof_modtab
= sizeof(MachO::dylib_module_64
);
512 struct_dylib_module_name
= "struct dylib_module_64";
514 sizeof_modtab
= sizeof(MachO::dylib_module
);
515 struct_dylib_module_name
= "struct dylib_module";
517 BigSize
*= sizeof_modtab
;
518 BigSize
+= Dysymtab
.modtaboff
;
519 if (BigSize
> FileSize
)
520 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
521 Twine(struct_dylib_module_name
) + ") of LC_DYSYMTAB "
522 "command " + Twine(LoadCommandIndex
) + " extends "
523 "past the end of the file");
524 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.modtaboff
,
525 Dysymtab
.nmodtab
* sizeof_modtab
,
528 if (Dysymtab
.extrefsymoff
> FileSize
)
529 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
530 Twine(LoadCommandIndex
) + " extends past the end of "
532 BigSize
= Dysymtab
.nextrefsyms
;
533 BigSize
*= sizeof(MachO::dylib_reference
);
534 BigSize
+= Dysymtab
.extrefsymoff
;
535 if (BigSize
> FileSize
)
536 return malformedError("extrefsymoff field plus nextrefsyms field times "
537 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
538 "command " + Twine(LoadCommandIndex
) + " extends "
539 "past the end of the file");
540 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.extrefsymoff
,
541 Dysymtab
.nextrefsyms
*
542 sizeof(MachO::dylib_reference
),
545 if (Dysymtab
.indirectsymoff
> FileSize
)
546 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
547 Twine(LoadCommandIndex
) + " extends past the end of "
549 BigSize
= Dysymtab
.nindirectsyms
;
550 BigSize
*= sizeof(uint32_t);
551 BigSize
+= Dysymtab
.indirectsymoff
;
552 if (BigSize
> FileSize
)
553 return malformedError("indirectsymoff field plus nindirectsyms field times "
554 "sizeof(uint32_t) of LC_DYSYMTAB command " +
555 Twine(LoadCommandIndex
) + " extends past the end of "
557 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.indirectsymoff
,
558 Dysymtab
.nindirectsyms
*
562 if (Dysymtab
.extreloff
> FileSize
)
563 return malformedError("extreloff field of LC_DYSYMTAB command " +
564 Twine(LoadCommandIndex
) + " extends past the end of "
566 BigSize
= Dysymtab
.nextrel
;
567 BigSize
*= sizeof(MachO::relocation_info
);
568 BigSize
+= Dysymtab
.extreloff
;
569 if (BigSize
> FileSize
)
570 return malformedError("extreloff field plus nextrel field times sizeof"
571 "(struct relocation_info) of LC_DYSYMTAB command " +
572 Twine(LoadCommandIndex
) + " extends past the end of "
574 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.extreloff
,
576 sizeof(MachO::relocation_info
),
577 "external relocation table"))
579 if (Dysymtab
.locreloff
> FileSize
)
580 return malformedError("locreloff field of LC_DYSYMTAB command " +
581 Twine(LoadCommandIndex
) + " extends past the end of "
583 BigSize
= Dysymtab
.nlocrel
;
584 BigSize
*= sizeof(MachO::relocation_info
);
585 BigSize
+= Dysymtab
.locreloff
;
586 if (BigSize
> FileSize
)
587 return malformedError("locreloff field plus nlocrel field times sizeof"
588 "(struct relocation_info) of LC_DYSYMTAB command " +
589 Twine(LoadCommandIndex
) + " extends past the end of "
591 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.locreloff
,
593 sizeof(MachO::relocation_info
),
594 "local relocation table"))
596 *DysymtabLoadCmd
= Load
.Ptr
;
597 return Error::success();
600 static Error
checkLinkeditDataCommand(const MachOObjectFile
&Obj
,
601 const MachOObjectFile::LoadCommandInfo
&Load
,
602 uint32_t LoadCommandIndex
,
603 const char **LoadCmd
, const char *CmdName
,
604 std::list
<MachOElement
> &Elements
,
605 const char *ElementName
) {
606 if (Load
.C
.cmdsize
< sizeof(MachO::linkedit_data_command
))
607 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
608 CmdName
+ " cmdsize too small");
609 if (*LoadCmd
!= nullptr)
610 return malformedError("more than one " + Twine(CmdName
) + " command");
611 auto LinkDataOrError
=
612 getStructOrErr
<MachO::linkedit_data_command
>(Obj
, Load
.Ptr
);
613 if (!LinkDataOrError
)
614 return LinkDataOrError
.takeError();
615 MachO::linkedit_data_command LinkData
= LinkDataOrError
.get();
616 if (LinkData
.cmdsize
!= sizeof(MachO::linkedit_data_command
))
617 return malformedError(Twine(CmdName
) + " command " +
618 Twine(LoadCommandIndex
) + " has incorrect cmdsize");
619 uint64_t FileSize
= Obj
.getData().size();
620 if (LinkData
.dataoff
> FileSize
)
621 return malformedError("dataoff field of " + Twine(CmdName
) + " command " +
622 Twine(LoadCommandIndex
) + " extends past the end of "
624 uint64_t BigSize
= LinkData
.dataoff
;
625 BigSize
+= LinkData
.datasize
;
626 if (BigSize
> FileSize
)
627 return malformedError("dataoff field plus datasize field of " +
628 Twine(CmdName
) + " command " +
629 Twine(LoadCommandIndex
) + " extends past the end of "
631 if (Error Err
= checkOverlappingElement(Elements
, LinkData
.dataoff
,
632 LinkData
.datasize
, ElementName
))
635 return Error::success();
638 static Error
checkDyldInfoCommand(const MachOObjectFile
&Obj
,
639 const MachOObjectFile::LoadCommandInfo
&Load
,
640 uint32_t LoadCommandIndex
,
641 const char **LoadCmd
, const char *CmdName
,
642 std::list
<MachOElement
> &Elements
) {
643 if (Load
.C
.cmdsize
< sizeof(MachO::dyld_info_command
))
644 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
645 CmdName
+ " cmdsize too small");
646 if (*LoadCmd
!= nullptr)
647 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
650 getStructOrErr
<MachO::dyld_info_command
>(Obj
, Load
.Ptr
);
652 return DyldInfoOrErr
.takeError();
653 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
654 if (DyldInfo
.cmdsize
!= sizeof(MachO::dyld_info_command
))
655 return malformedError(Twine(CmdName
) + " command " +
656 Twine(LoadCommandIndex
) + " has incorrect cmdsize");
657 uint64_t FileSize
= Obj
.getData().size();
658 if (DyldInfo
.rebase_off
> FileSize
)
659 return malformedError("rebase_off field of " + Twine(CmdName
) +
660 " command " + Twine(LoadCommandIndex
) + " extends "
661 "past the end of the file");
662 uint64_t BigSize
= DyldInfo
.rebase_off
;
663 BigSize
+= DyldInfo
.rebase_size
;
664 if (BigSize
> FileSize
)
665 return malformedError("rebase_off field plus rebase_size field of " +
666 Twine(CmdName
) + " command " +
667 Twine(LoadCommandIndex
) + " extends past the end of "
669 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.rebase_off
,
670 DyldInfo
.rebase_size
,
673 if (DyldInfo
.bind_off
> FileSize
)
674 return malformedError("bind_off field of " + Twine(CmdName
) +
675 " command " + Twine(LoadCommandIndex
) + " extends "
676 "past the end of the file");
677 BigSize
= DyldInfo
.bind_off
;
678 BigSize
+= DyldInfo
.bind_size
;
679 if (BigSize
> FileSize
)
680 return malformedError("bind_off field plus bind_size field of " +
681 Twine(CmdName
) + " command " +
682 Twine(LoadCommandIndex
) + " extends past the end of "
684 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.bind_off
,
688 if (DyldInfo
.weak_bind_off
> FileSize
)
689 return malformedError("weak_bind_off field of " + Twine(CmdName
) +
690 " command " + Twine(LoadCommandIndex
) + " extends "
691 "past the end of the file");
692 BigSize
= DyldInfo
.weak_bind_off
;
693 BigSize
+= DyldInfo
.weak_bind_size
;
694 if (BigSize
> FileSize
)
695 return malformedError("weak_bind_off field plus weak_bind_size field of " +
696 Twine(CmdName
) + " command " +
697 Twine(LoadCommandIndex
) + " extends past the end of "
699 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.weak_bind_off
,
700 DyldInfo
.weak_bind_size
,
701 "dyld weak bind info"))
703 if (DyldInfo
.lazy_bind_off
> FileSize
)
704 return malformedError("lazy_bind_off field of " + Twine(CmdName
) +
705 " command " + Twine(LoadCommandIndex
) + " extends "
706 "past the end of the file");
707 BigSize
= DyldInfo
.lazy_bind_off
;
708 BigSize
+= DyldInfo
.lazy_bind_size
;
709 if (BigSize
> FileSize
)
710 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
711 Twine(CmdName
) + " command " +
712 Twine(LoadCommandIndex
) + " extends past the end of "
714 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.lazy_bind_off
,
715 DyldInfo
.lazy_bind_size
,
716 "dyld lazy bind info"))
718 if (DyldInfo
.export_off
> FileSize
)
719 return malformedError("export_off field of " + Twine(CmdName
) +
720 " command " + Twine(LoadCommandIndex
) + " extends "
721 "past the end of the file");
722 BigSize
= DyldInfo
.export_off
;
723 BigSize
+= DyldInfo
.export_size
;
724 if (BigSize
> FileSize
)
725 return malformedError("export_off field plus export_size field of " +
726 Twine(CmdName
) + " command " +
727 Twine(LoadCommandIndex
) + " extends past the end of "
729 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.export_off
,
730 DyldInfo
.export_size
,
734 return Error::success();
737 static Error
checkDylibCommand(const MachOObjectFile
&Obj
,
738 const MachOObjectFile::LoadCommandInfo
&Load
,
739 uint32_t LoadCommandIndex
, const char *CmdName
) {
740 if (Load
.C
.cmdsize
< sizeof(MachO::dylib_command
))
741 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
742 CmdName
+ " cmdsize too small");
743 auto CommandOrErr
= getStructOrErr
<MachO::dylib_command
>(Obj
, Load
.Ptr
);
745 return CommandOrErr
.takeError();
746 MachO::dylib_command D
= CommandOrErr
.get();
747 if (D
.dylib
.name
< sizeof(MachO::dylib_command
))
748 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
749 CmdName
+ " name.offset field too small, not past "
750 "the end of the dylib_command struct");
751 if (D
.dylib
.name
>= D
.cmdsize
)
752 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
753 CmdName
+ " name.offset field extends past the end "
754 "of the load command");
755 // Make sure there is a null between the starting offset of the name and
756 // the end of the load command.
758 const char *P
= (const char *)Load
.Ptr
;
759 for (i
= D
.dylib
.name
; i
< D
.cmdsize
; i
++)
763 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
764 CmdName
+ " library name extends past the end of the "
766 return Error::success();
769 static Error
checkDylibIdCommand(const MachOObjectFile
&Obj
,
770 const MachOObjectFile::LoadCommandInfo
&Load
,
771 uint32_t LoadCommandIndex
,
772 const char **LoadCmd
) {
773 if (Error Err
= checkDylibCommand(Obj
, Load
, LoadCommandIndex
,
776 if (*LoadCmd
!= nullptr)
777 return malformedError("more than one LC_ID_DYLIB command");
778 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB
&&
779 Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
)
780 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
783 return Error::success();
786 static Error
checkDyldCommand(const MachOObjectFile
&Obj
,
787 const MachOObjectFile::LoadCommandInfo
&Load
,
788 uint32_t LoadCommandIndex
, const char *CmdName
) {
789 if (Load
.C
.cmdsize
< sizeof(MachO::dylinker_command
))
790 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
791 CmdName
+ " cmdsize too small");
792 auto CommandOrErr
= getStructOrErr
<MachO::dylinker_command
>(Obj
, Load
.Ptr
);
794 return CommandOrErr
.takeError();
795 MachO::dylinker_command D
= CommandOrErr
.get();
796 if (D
.name
< sizeof(MachO::dylinker_command
))
797 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
798 CmdName
+ " name.offset field too small, not past "
799 "the end of the dylinker_command struct");
800 if (D
.name
>= D
.cmdsize
)
801 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
802 CmdName
+ " name.offset field extends past the end "
803 "of the load command");
804 // Make sure there is a null between the starting offset of the name and
805 // the end of the load command.
807 const char *P
= (const char *)Load
.Ptr
;
808 for (i
= D
.name
; i
< D
.cmdsize
; i
++)
812 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
813 CmdName
+ " dyld name extends past the end of the "
815 return Error::success();
818 static Error
checkVersCommand(const MachOObjectFile
&Obj
,
819 const MachOObjectFile::LoadCommandInfo
&Load
,
820 uint32_t LoadCommandIndex
,
821 const char **LoadCmd
, const char *CmdName
) {
822 if (Load
.C
.cmdsize
!= sizeof(MachO::version_min_command
))
823 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
824 CmdName
+ " has incorrect cmdsize");
825 if (*LoadCmd
!= nullptr)
826 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
827 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
828 "LC_VERSION_MIN_WATCHOS command");
830 return Error::success();
833 static Error
checkNoteCommand(const MachOObjectFile
&Obj
,
834 const MachOObjectFile::LoadCommandInfo
&Load
,
835 uint32_t LoadCommandIndex
,
836 std::list
<MachOElement
> &Elements
) {
837 if (Load
.C
.cmdsize
!= sizeof(MachO::note_command
))
838 return malformedError("load command " + Twine(LoadCommandIndex
) +
839 " LC_NOTE has incorrect cmdsize");
840 auto NoteCmdOrErr
= getStructOrErr
<MachO::note_command
>(Obj
, Load
.Ptr
);
842 return NoteCmdOrErr
.takeError();
843 MachO::note_command Nt
= NoteCmdOrErr
.get();
844 uint64_t FileSize
= Obj
.getData().size();
845 if (Nt
.offset
> FileSize
)
846 return malformedError("offset field of LC_NOTE command " +
847 Twine(LoadCommandIndex
) + " extends "
848 "past the end of the file");
849 uint64_t BigSize
= Nt
.offset
;
851 if (BigSize
> FileSize
)
852 return malformedError("size field plus offset field of LC_NOTE command " +
853 Twine(LoadCommandIndex
) + " extends past the end of "
855 if (Error Err
= checkOverlappingElement(Elements
, Nt
.offset
, Nt
.size
,
858 return Error::success();
862 parseBuildVersionCommand(const MachOObjectFile
&Obj
,
863 const MachOObjectFile::LoadCommandInfo
&Load
,
864 SmallVectorImpl
<const char*> &BuildTools
,
865 uint32_t LoadCommandIndex
) {
867 getStructOrErr
<MachO::build_version_command
>(Obj
, Load
.Ptr
);
869 return BVCOrErr
.takeError();
870 MachO::build_version_command BVC
= BVCOrErr
.get();
871 if (Load
.C
.cmdsize
!=
872 sizeof(MachO::build_version_command
) +
873 BVC
.ntools
* sizeof(MachO::build_tool_version
))
874 return malformedError("load command " + Twine(LoadCommandIndex
) +
875 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
877 auto Start
= Load
.Ptr
+ sizeof(MachO::build_version_command
);
878 BuildTools
.resize(BVC
.ntools
);
879 for (unsigned i
= 0; i
< BVC
.ntools
; ++i
)
880 BuildTools
[i
] = Start
+ i
* sizeof(MachO::build_tool_version
);
882 return Error::success();
885 static Error
checkRpathCommand(const MachOObjectFile
&Obj
,
886 const MachOObjectFile::LoadCommandInfo
&Load
,
887 uint32_t LoadCommandIndex
) {
888 if (Load
.C
.cmdsize
< sizeof(MachO::rpath_command
))
889 return malformedError("load command " + Twine(LoadCommandIndex
) +
890 " LC_RPATH cmdsize too small");
891 auto ROrErr
= getStructOrErr
<MachO::rpath_command
>(Obj
, Load
.Ptr
);
893 return ROrErr
.takeError();
894 MachO::rpath_command R
= ROrErr
.get();
895 if (R
.path
< sizeof(MachO::rpath_command
))
896 return malformedError("load command " + Twine(LoadCommandIndex
) +
897 " LC_RPATH path.offset field too small, not past "
898 "the end of the rpath_command struct");
899 if (R
.path
>= R
.cmdsize
)
900 return malformedError("load command " + Twine(LoadCommandIndex
) +
901 " LC_RPATH path.offset field extends past the end "
902 "of the load command");
903 // Make sure there is a null between the starting offset of the path and
904 // the end of the load command.
906 const char *P
= (const char *)Load
.Ptr
;
907 for (i
= R
.path
; i
< R
.cmdsize
; i
++)
911 return malformedError("load command " + Twine(LoadCommandIndex
) +
912 " LC_RPATH library name extends past the end of the "
914 return Error::success();
917 static Error
checkEncryptCommand(const MachOObjectFile
&Obj
,
918 const MachOObjectFile::LoadCommandInfo
&Load
,
919 uint32_t LoadCommandIndex
,
920 uint64_t cryptoff
, uint64_t cryptsize
,
921 const char **LoadCmd
, const char *CmdName
) {
922 if (*LoadCmd
!= nullptr)
923 return malformedError("more than one LC_ENCRYPTION_INFO and or "
924 "LC_ENCRYPTION_INFO_64 command");
925 uint64_t FileSize
= Obj
.getData().size();
926 if (cryptoff
> FileSize
)
927 return malformedError("cryptoff field of " + Twine(CmdName
) +
928 " command " + Twine(LoadCommandIndex
) + " extends "
929 "past the end of the file");
930 uint64_t BigSize
= cryptoff
;
931 BigSize
+= cryptsize
;
932 if (BigSize
> FileSize
)
933 return malformedError("cryptoff field plus cryptsize field of " +
934 Twine(CmdName
) + " command " +
935 Twine(LoadCommandIndex
) + " extends past the end of "
938 return Error::success();
941 static Error
checkLinkerOptCommand(const MachOObjectFile
&Obj
,
942 const MachOObjectFile::LoadCommandInfo
&Load
,
943 uint32_t LoadCommandIndex
) {
944 if (Load
.C
.cmdsize
< sizeof(MachO::linker_option_command
))
945 return malformedError("load command " + Twine(LoadCommandIndex
) +
946 " LC_LINKER_OPTION cmdsize too small");
947 auto LinkOptionOrErr
=
948 getStructOrErr
<MachO::linker_option_command
>(Obj
, Load
.Ptr
);
949 if (!LinkOptionOrErr
)
950 return LinkOptionOrErr
.takeError();
951 MachO::linker_option_command L
= LinkOptionOrErr
.get();
952 // Make sure the count of strings is correct.
953 const char *string
= (const char *)Load
.Ptr
+
954 sizeof(struct MachO::linker_option_command
);
955 uint32_t left
= L
.cmdsize
- sizeof(struct MachO::linker_option_command
);
958 while (*string
== '\0' && left
> 0) {
964 uint32_t NullPos
= StringRef(string
, left
).find('\0');
965 if (0xffffffff == NullPos
)
966 return malformedError("load command " + Twine(LoadCommandIndex
) +
967 " LC_LINKER_OPTION string #" + Twine(i
) +
968 " is not NULL terminated");
969 uint32_t len
= std::min(NullPos
, left
) + 1;
975 return malformedError("load command " + Twine(LoadCommandIndex
) +
976 " LC_LINKER_OPTION string count " + Twine(L
.count
) +
977 " does not match number of strings");
978 return Error::success();
981 static Error
checkSubCommand(const MachOObjectFile
&Obj
,
982 const MachOObjectFile::LoadCommandInfo
&Load
,
983 uint32_t LoadCommandIndex
, const char *CmdName
,
984 size_t SizeOfCmd
, const char *CmdStructName
,
985 uint32_t PathOffset
, const char *PathFieldName
) {
986 if (PathOffset
< SizeOfCmd
)
987 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
988 CmdName
+ " " + PathFieldName
+ ".offset field too "
989 "small, not past the end of the " + CmdStructName
);
990 if (PathOffset
>= Load
.C
.cmdsize
)
991 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
992 CmdName
+ " " + PathFieldName
+ ".offset field "
993 "extends past the end of the load command");
994 // Make sure there is a null between the starting offset of the path and
995 // the end of the load command.
997 const char *P
= (const char *)Load
.Ptr
;
998 for (i
= PathOffset
; i
< Load
.C
.cmdsize
; i
++)
1001 if (i
>= Load
.C
.cmdsize
)
1002 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
1003 CmdName
+ " " + PathFieldName
+ " name extends past "
1004 "the end of the load command");
1005 return Error::success();
1008 static Error
checkThreadCommand(const MachOObjectFile
&Obj
,
1009 const MachOObjectFile::LoadCommandInfo
&Load
,
1010 uint32_t LoadCommandIndex
,
1011 const char *CmdName
) {
1012 if (Load
.C
.cmdsize
< sizeof(MachO::thread_command
))
1013 return malformedError("load command " + Twine(LoadCommandIndex
) +
1014 CmdName
+ " cmdsize too small");
1015 auto ThreadCommandOrErr
=
1016 getStructOrErr
<MachO::thread_command
>(Obj
, Load
.Ptr
);
1017 if (!ThreadCommandOrErr
)
1018 return ThreadCommandOrErr
.takeError();
1019 MachO::thread_command T
= ThreadCommandOrErr
.get();
1020 const char *state
= Load
.Ptr
+ sizeof(MachO::thread_command
);
1021 const char *end
= Load
.Ptr
+ T
.cmdsize
;
1022 uint32_t nflavor
= 0;
1023 uint32_t cputype
= getCPUType(Obj
);
1024 while (state
< end
) {
1025 if(state
+ sizeof(uint32_t) > end
)
1026 return malformedError("load command " + Twine(LoadCommandIndex
) +
1027 "flavor in " + CmdName
+ " extends past end of "
1030 memcpy(&flavor
, state
, sizeof(uint32_t));
1031 if (Obj
.isLittleEndian() != sys::IsLittleEndianHost
)
1032 sys::swapByteOrder(flavor
);
1033 state
+= sizeof(uint32_t);
1035 if(state
+ sizeof(uint32_t) > end
)
1036 return malformedError("load command " + Twine(LoadCommandIndex
) +
1037 " count in " + CmdName
+ " extends past end of "
1040 memcpy(&count
, state
, sizeof(uint32_t));
1041 if (Obj
.isLittleEndian() != sys::IsLittleEndianHost
)
1042 sys::swapByteOrder(count
);
1043 state
+= sizeof(uint32_t);
1045 if (cputype
== MachO::CPU_TYPE_I386
) {
1046 if (flavor
== MachO::x86_THREAD_STATE32
) {
1047 if (count
!= MachO::x86_THREAD_STATE32_COUNT
)
1048 return malformedError("load command " + Twine(LoadCommandIndex
) +
1049 " count not x86_THREAD_STATE32_COUNT for "
1050 "flavor number " + Twine(nflavor
) + " which is "
1051 "a x86_THREAD_STATE32 flavor in " + CmdName
+
1053 if (state
+ sizeof(MachO::x86_thread_state32_t
) > end
)
1054 return malformedError("load command " + Twine(LoadCommandIndex
) +
1055 " x86_THREAD_STATE32 extends past end of "
1056 "command in " + CmdName
+ " command");
1057 state
+= sizeof(MachO::x86_thread_state32_t
);
1059 return malformedError("load command " + Twine(LoadCommandIndex
) +
1060 " unknown flavor (" + Twine(flavor
) + ") for "
1061 "flavor number " + Twine(nflavor
) + " in " +
1062 CmdName
+ " command");
1064 } else if (cputype
== MachO::CPU_TYPE_X86_64
) {
1065 if (flavor
== MachO::x86_THREAD_STATE
) {
1066 if (count
!= MachO::x86_THREAD_STATE_COUNT
)
1067 return malformedError("load command " + Twine(LoadCommandIndex
) +
1068 " count not x86_THREAD_STATE_COUNT for "
1069 "flavor number " + Twine(nflavor
) + " which is "
1070 "a x86_THREAD_STATE flavor in " + CmdName
+
1072 if (state
+ sizeof(MachO::x86_thread_state_t
) > end
)
1073 return malformedError("load command " + Twine(LoadCommandIndex
) +
1074 " x86_THREAD_STATE extends past end of "
1075 "command in " + CmdName
+ " command");
1076 state
+= sizeof(MachO::x86_thread_state_t
);
1077 } else if (flavor
== MachO::x86_FLOAT_STATE
) {
1078 if (count
!= MachO::x86_FLOAT_STATE_COUNT
)
1079 return malformedError("load command " + Twine(LoadCommandIndex
) +
1080 " count not x86_FLOAT_STATE_COUNT for "
1081 "flavor number " + Twine(nflavor
) + " which is "
1082 "a x86_FLOAT_STATE flavor in " + CmdName
+
1084 if (state
+ sizeof(MachO::x86_float_state_t
) > end
)
1085 return malformedError("load command " + Twine(LoadCommandIndex
) +
1086 " x86_FLOAT_STATE extends past end of "
1087 "command in " + CmdName
+ " command");
1088 state
+= sizeof(MachO::x86_float_state_t
);
1089 } else if (flavor
== MachO::x86_EXCEPTION_STATE
) {
1090 if (count
!= MachO::x86_EXCEPTION_STATE_COUNT
)
1091 return malformedError("load command " + Twine(LoadCommandIndex
) +
1092 " count not x86_EXCEPTION_STATE_COUNT for "
1093 "flavor number " + Twine(nflavor
) + " which is "
1094 "a x86_EXCEPTION_STATE flavor in " + CmdName
+
1096 if (state
+ sizeof(MachO::x86_exception_state_t
) > end
)
1097 return malformedError("load command " + Twine(LoadCommandIndex
) +
1098 " x86_EXCEPTION_STATE extends past end of "
1099 "command in " + CmdName
+ " command");
1100 state
+= sizeof(MachO::x86_exception_state_t
);
1101 } else if (flavor
== MachO::x86_THREAD_STATE64
) {
1102 if (count
!= MachO::x86_THREAD_STATE64_COUNT
)
1103 return malformedError("load command " + Twine(LoadCommandIndex
) +
1104 " count not x86_THREAD_STATE64_COUNT for "
1105 "flavor number " + Twine(nflavor
) + " which is "
1106 "a x86_THREAD_STATE64 flavor in " + CmdName
+
1108 if (state
+ sizeof(MachO::x86_thread_state64_t
) > end
)
1109 return malformedError("load command " + Twine(LoadCommandIndex
) +
1110 " x86_THREAD_STATE64 extends past end of "
1111 "command in " + CmdName
+ " command");
1112 state
+= sizeof(MachO::x86_thread_state64_t
);
1113 } else if (flavor
== MachO::x86_EXCEPTION_STATE64
) {
1114 if (count
!= MachO::x86_EXCEPTION_STATE64_COUNT
)
1115 return malformedError("load command " + Twine(LoadCommandIndex
) +
1116 " count not x86_EXCEPTION_STATE64_COUNT for "
1117 "flavor number " + Twine(nflavor
) + " which is "
1118 "a x86_EXCEPTION_STATE64 flavor in " + CmdName
+
1120 if (state
+ sizeof(MachO::x86_exception_state64_t
) > end
)
1121 return malformedError("load command " + Twine(LoadCommandIndex
) +
1122 " x86_EXCEPTION_STATE64 extends past end of "
1123 "command in " + CmdName
+ " command");
1124 state
+= sizeof(MachO::x86_exception_state64_t
);
1126 return malformedError("load command " + Twine(LoadCommandIndex
) +
1127 " unknown flavor (" + Twine(flavor
) + ") for "
1128 "flavor number " + Twine(nflavor
) + " in " +
1129 CmdName
+ " command");
1131 } else if (cputype
== MachO::CPU_TYPE_ARM
) {
1132 if (flavor
== MachO::ARM_THREAD_STATE
) {
1133 if (count
!= MachO::ARM_THREAD_STATE_COUNT
)
1134 return malformedError("load command " + Twine(LoadCommandIndex
) +
1135 " count not ARM_THREAD_STATE_COUNT for "
1136 "flavor number " + Twine(nflavor
) + " which is "
1137 "a ARM_THREAD_STATE flavor in " + CmdName
+
1139 if (state
+ sizeof(MachO::arm_thread_state32_t
) > end
)
1140 return malformedError("load command " + Twine(LoadCommandIndex
) +
1141 " ARM_THREAD_STATE extends past end of "
1142 "command in " + CmdName
+ " command");
1143 state
+= sizeof(MachO::arm_thread_state32_t
);
1145 return malformedError("load command " + Twine(LoadCommandIndex
) +
1146 " unknown flavor (" + Twine(flavor
) + ") for "
1147 "flavor number " + Twine(nflavor
) + " in " +
1148 CmdName
+ " command");
1150 } else if (cputype
== MachO::CPU_TYPE_ARM64
||
1151 cputype
== MachO::CPU_TYPE_ARM64_32
) {
1152 if (flavor
== MachO::ARM_THREAD_STATE64
) {
1153 if (count
!= MachO::ARM_THREAD_STATE64_COUNT
)
1154 return malformedError("load command " + Twine(LoadCommandIndex
) +
1155 " count not ARM_THREAD_STATE64_COUNT for "
1156 "flavor number " + Twine(nflavor
) + " which is "
1157 "a ARM_THREAD_STATE64 flavor in " + CmdName
+
1159 if (state
+ sizeof(MachO::arm_thread_state64_t
) > end
)
1160 return malformedError("load command " + Twine(LoadCommandIndex
) +
1161 " ARM_THREAD_STATE64 extends past end of "
1162 "command in " + CmdName
+ " command");
1163 state
+= sizeof(MachO::arm_thread_state64_t
);
1165 return malformedError("load command " + Twine(LoadCommandIndex
) +
1166 " unknown flavor (" + Twine(flavor
) + ") for "
1167 "flavor number " + Twine(nflavor
) + " in " +
1168 CmdName
+ " command");
1170 } else if (cputype
== MachO::CPU_TYPE_POWERPC
) {
1171 if (flavor
== MachO::PPC_THREAD_STATE
) {
1172 if (count
!= MachO::PPC_THREAD_STATE_COUNT
)
1173 return malformedError("load command " + Twine(LoadCommandIndex
) +
1174 " count not PPC_THREAD_STATE_COUNT for "
1175 "flavor number " + Twine(nflavor
) + " which is "
1176 "a PPC_THREAD_STATE flavor in " + CmdName
+
1178 if (state
+ sizeof(MachO::ppc_thread_state32_t
) > end
)
1179 return malformedError("load command " + Twine(LoadCommandIndex
) +
1180 " PPC_THREAD_STATE extends past end of "
1181 "command in " + CmdName
+ " command");
1182 state
+= sizeof(MachO::ppc_thread_state32_t
);
1184 return malformedError("load command " + Twine(LoadCommandIndex
) +
1185 " unknown flavor (" + Twine(flavor
) + ") for "
1186 "flavor number " + Twine(nflavor
) + " in " +
1187 CmdName
+ " command");
1190 return malformedError("unknown cputype (" + Twine(cputype
) + ") load "
1191 "command " + Twine(LoadCommandIndex
) + " for " +
1192 CmdName
+ " command can't be checked");
1196 return Error::success();
1199 static Error
checkTwoLevelHintsCommand(const MachOObjectFile
&Obj
,
1200 const MachOObjectFile::LoadCommandInfo
1202 uint32_t LoadCommandIndex
,
1203 const char **LoadCmd
,
1204 std::list
<MachOElement
> &Elements
) {
1205 if (Load
.C
.cmdsize
!= sizeof(MachO::twolevel_hints_command
))
1206 return malformedError("load command " + Twine(LoadCommandIndex
) +
1207 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1208 if (*LoadCmd
!= nullptr)
1209 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1210 auto HintsOrErr
= getStructOrErr
<MachO::twolevel_hints_command
>(Obj
, Load
.Ptr
);
1212 return HintsOrErr
.takeError();
1213 MachO::twolevel_hints_command Hints
= HintsOrErr
.get();
1214 uint64_t FileSize
= Obj
.getData().size();
1215 if (Hints
.offset
> FileSize
)
1216 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1217 Twine(LoadCommandIndex
) + " extends past the end of "
1219 uint64_t BigSize
= Hints
.nhints
;
1220 BigSize
*= sizeof(MachO::twolevel_hint
);
1221 BigSize
+= Hints
.offset
;
1222 if (BigSize
> FileSize
)
1223 return malformedError("offset field plus nhints times sizeof(struct "
1224 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1225 Twine(LoadCommandIndex
) + " extends past the end of "
1227 if (Error Err
= checkOverlappingElement(Elements
, Hints
.offset
, Hints
.nhints
*
1228 sizeof(MachO::twolevel_hint
),
1231 *LoadCmd
= Load
.Ptr
;
1232 return Error::success();
1235 // Returns true if the libObject code does not support the load command and its
1236 // contents. The cmd value it is treated as an unknown load command but with
1237 // an error message that says the cmd value is obsolete.
1238 static bool isLoadCommandObsolete(uint32_t cmd
) {
1239 if (cmd
== MachO::LC_SYMSEG
||
1240 cmd
== MachO::LC_LOADFVMLIB
||
1241 cmd
== MachO::LC_IDFVMLIB
||
1242 cmd
== MachO::LC_IDENT
||
1243 cmd
== MachO::LC_FVMFILE
||
1244 cmd
== MachO::LC_PREPAGE
||
1245 cmd
== MachO::LC_PREBOUND_DYLIB
||
1246 cmd
== MachO::LC_TWOLEVEL_HINTS
||
1247 cmd
== MachO::LC_PREBIND_CKSUM
)
1252 Expected
<std::unique_ptr
<MachOObjectFile
>>
1253 MachOObjectFile::create(MemoryBufferRef Object
, bool IsLittleEndian
,
1254 bool Is64Bits
, uint32_t UniversalCputype
,
1255 uint32_t UniversalIndex
,
1256 size_t MachOFilesetEntryOffset
) {
1257 Error Err
= Error::success();
1258 std::unique_ptr
<MachOObjectFile
> Obj(new MachOObjectFile(
1259 std::move(Object
), IsLittleEndian
, Is64Bits
, Err
, UniversalCputype
,
1260 UniversalIndex
, MachOFilesetEntryOffset
));
1262 return std::move(Err
);
1263 return std::move(Obj
);
1266 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object
, bool IsLittleEndian
,
1267 bool Is64bits
, Error
&Err
,
1268 uint32_t UniversalCputype
,
1269 uint32_t UniversalIndex
,
1270 size_t MachOFilesetEntryOffset
)
1271 : ObjectFile(getMachOType(IsLittleEndian
, Is64bits
), Object
),
1272 MachOFilesetEntryOffset(MachOFilesetEntryOffset
) {
1273 ErrorAsOutParameter
ErrAsOutParam(&Err
);
1274 uint64_t SizeOfHeaders
;
1277 parseHeader(*this, Header64
, Err
);
1278 SizeOfHeaders
= sizeof(MachO::mach_header_64
);
1279 cputype
= Header64
.cputype
;
1281 parseHeader(*this, Header
, Err
);
1282 SizeOfHeaders
= sizeof(MachO::mach_header
);
1283 cputype
= Header
.cputype
;
1287 SizeOfHeaders
+= getHeader().sizeofcmds
;
1288 if (getData().data() + SizeOfHeaders
> getData().end()) {
1289 Err
= malformedError("load commands extend past the end of the file");
1292 if (UniversalCputype
!= 0 && cputype
!= UniversalCputype
) {
1293 Err
= malformedError("universal header architecture: " +
1294 Twine(UniversalIndex
) + "'s cputype does not match "
1295 "object file's mach header");
1298 std::list
<MachOElement
> Elements
;
1299 Elements
.push_back({0, SizeOfHeaders
, "Mach-O headers"});
1301 uint32_t LoadCommandCount
= getHeader().ncmds
;
1302 LoadCommandInfo Load
;
1303 if (LoadCommandCount
!= 0) {
1304 if (auto LoadOrErr
= getFirstLoadCommandInfo(*this))
1307 Err
= LoadOrErr
.takeError();
1312 const char *DyldIdLoadCmd
= nullptr;
1313 const char *SplitInfoLoadCmd
= nullptr;
1314 const char *CodeSignDrsLoadCmd
= nullptr;
1315 const char *CodeSignLoadCmd
= nullptr;
1316 const char *VersLoadCmd
= nullptr;
1317 const char *SourceLoadCmd
= nullptr;
1318 const char *EntryPointLoadCmd
= nullptr;
1319 const char *EncryptLoadCmd
= nullptr;
1320 const char *RoutinesLoadCmd
= nullptr;
1321 const char *UnixThreadLoadCmd
= nullptr;
1322 const char *TwoLevelHintsLoadCmd
= nullptr;
1323 for (unsigned I
= 0; I
< LoadCommandCount
; ++I
) {
1325 if (Load
.C
.cmdsize
% 8 != 0) {
1326 // We have a hack here to allow 64-bit Mach-O core files to have
1327 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1328 // allowed since the macOS kernel produces them.
1329 if (getHeader().filetype
!= MachO::MH_CORE
||
1330 Load
.C
.cmd
!= MachO::LC_THREAD
|| Load
.C
.cmdsize
% 4) {
1331 Err
= malformedError("load command " + Twine(I
) + " cmdsize not a "
1337 if (Load
.C
.cmdsize
% 4 != 0) {
1338 Err
= malformedError("load command " + Twine(I
) + " cmdsize not a "
1343 LoadCommands
.push_back(Load
);
1344 if (Load
.C
.cmd
== MachO::LC_SYMTAB
) {
1345 if ((Err
= checkSymtabCommand(*this, Load
, I
, &SymtabLoadCmd
, Elements
)))
1347 } else if (Load
.C
.cmd
== MachO::LC_DYSYMTAB
) {
1348 if ((Err
= checkDysymtabCommand(*this, Load
, I
, &DysymtabLoadCmd
,
1351 } else if (Load
.C
.cmd
== MachO::LC_DATA_IN_CODE
) {
1352 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &DataInCodeLoadCmd
,
1353 "LC_DATA_IN_CODE", Elements
,
1354 "data in code info")))
1356 } else if (Load
.C
.cmd
== MachO::LC_LINKER_OPTIMIZATION_HINT
) {
1357 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &LinkOptHintsLoadCmd
,
1358 "LC_LINKER_OPTIMIZATION_HINT",
1359 Elements
, "linker optimization "
1362 } else if (Load
.C
.cmd
== MachO::LC_FUNCTION_STARTS
) {
1363 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &FuncStartsLoadCmd
,
1364 "LC_FUNCTION_STARTS", Elements
,
1365 "function starts data")))
1367 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT_SPLIT_INFO
) {
1368 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &SplitInfoLoadCmd
,
1369 "LC_SEGMENT_SPLIT_INFO", Elements
,
1370 "split info data")))
1372 } else if (Load
.C
.cmd
== MachO::LC_DYLIB_CODE_SIGN_DRS
) {
1373 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &CodeSignDrsLoadCmd
,
1374 "LC_DYLIB_CODE_SIGN_DRS", Elements
,
1375 "code signing RDs data")))
1377 } else if (Load
.C
.cmd
== MachO::LC_CODE_SIGNATURE
) {
1378 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &CodeSignLoadCmd
,
1379 "LC_CODE_SIGNATURE", Elements
,
1380 "code signature data")))
1382 } else if (Load
.C
.cmd
== MachO::LC_DYLD_INFO
) {
1383 if ((Err
= checkDyldInfoCommand(*this, Load
, I
, &DyldInfoLoadCmd
,
1384 "LC_DYLD_INFO", Elements
)))
1386 } else if (Load
.C
.cmd
== MachO::LC_DYLD_INFO_ONLY
) {
1387 if ((Err
= checkDyldInfoCommand(*this, Load
, I
, &DyldInfoLoadCmd
,
1388 "LC_DYLD_INFO_ONLY", Elements
)))
1390 } else if (Load
.C
.cmd
== MachO::LC_DYLD_CHAINED_FIXUPS
) {
1391 if ((Err
= checkLinkeditDataCommand(
1392 *this, Load
, I
, &DyldChainedFixupsLoadCmd
,
1393 "LC_DYLD_CHAINED_FIXUPS", Elements
, "chained fixups")))
1395 } else if (Load
.C
.cmd
== MachO::LC_DYLD_EXPORTS_TRIE
) {
1396 if ((Err
= checkLinkeditDataCommand(
1397 *this, Load
, I
, &DyldExportsTrieLoadCmd
, "LC_DYLD_EXPORTS_TRIE",
1398 Elements
, "exports trie")))
1400 } else if (Load
.C
.cmd
== MachO::LC_UUID
) {
1401 if (Load
.C
.cmdsize
!= sizeof(MachO::uuid_command
)) {
1402 Err
= malformedError("LC_UUID command " + Twine(I
) + " has incorrect "
1407 Err
= malformedError("more than one LC_UUID command");
1410 UuidLoadCmd
= Load
.Ptr
;
1411 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
1412 if ((Err
= parseSegmentLoadCommand
<MachO::segment_command_64
,
1414 *this, Load
, Sections
, HasPageZeroSegment
, I
,
1415 "LC_SEGMENT_64", SizeOfHeaders
, Elements
)))
1417 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
1418 if ((Err
= parseSegmentLoadCommand
<MachO::segment_command
,
1420 *this, Load
, Sections
, HasPageZeroSegment
, I
,
1421 "LC_SEGMENT", SizeOfHeaders
, Elements
)))
1423 } else if (Load
.C
.cmd
== MachO::LC_ID_DYLIB
) {
1424 if ((Err
= checkDylibIdCommand(*this, Load
, I
, &DyldIdLoadCmd
)))
1426 } else if (Load
.C
.cmd
== MachO::LC_LOAD_DYLIB
) {
1427 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_DYLIB")))
1429 Libraries
.push_back(Load
.Ptr
);
1430 } else if (Load
.C
.cmd
== MachO::LC_LOAD_WEAK_DYLIB
) {
1431 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_WEAK_DYLIB")))
1433 Libraries
.push_back(Load
.Ptr
);
1434 } else if (Load
.C
.cmd
== MachO::LC_LAZY_LOAD_DYLIB
) {
1435 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LAZY_LOAD_DYLIB")))
1437 Libraries
.push_back(Load
.Ptr
);
1438 } else if (Load
.C
.cmd
== MachO::LC_REEXPORT_DYLIB
) {
1439 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_REEXPORT_DYLIB")))
1441 Libraries
.push_back(Load
.Ptr
);
1442 } else if (Load
.C
.cmd
== MachO::LC_LOAD_UPWARD_DYLIB
) {
1443 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_UPWARD_DYLIB")))
1445 Libraries
.push_back(Load
.Ptr
);
1446 } else if (Load
.C
.cmd
== MachO::LC_ID_DYLINKER
) {
1447 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_ID_DYLINKER")))
1449 } else if (Load
.C
.cmd
== MachO::LC_LOAD_DYLINKER
) {
1450 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_LOAD_DYLINKER")))
1452 } else if (Load
.C
.cmd
== MachO::LC_DYLD_ENVIRONMENT
) {
1453 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_DYLD_ENVIRONMENT")))
1455 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_MACOSX
) {
1456 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1457 "LC_VERSION_MIN_MACOSX")))
1459 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_IPHONEOS
) {
1460 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1461 "LC_VERSION_MIN_IPHONEOS")))
1463 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_TVOS
) {
1464 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1465 "LC_VERSION_MIN_TVOS")))
1467 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_WATCHOS
) {
1468 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1469 "LC_VERSION_MIN_WATCHOS")))
1471 } else if (Load
.C
.cmd
== MachO::LC_NOTE
) {
1472 if ((Err
= checkNoteCommand(*this, Load
, I
, Elements
)))
1474 } else if (Load
.C
.cmd
== MachO::LC_BUILD_VERSION
) {
1475 if ((Err
= parseBuildVersionCommand(*this, Load
, BuildTools
, I
)))
1477 } else if (Load
.C
.cmd
== MachO::LC_RPATH
) {
1478 if ((Err
= checkRpathCommand(*this, Load
, I
)))
1480 } else if (Load
.C
.cmd
== MachO::LC_SOURCE_VERSION
) {
1481 if (Load
.C
.cmdsize
!= sizeof(MachO::source_version_command
)) {
1482 Err
= malformedError("LC_SOURCE_VERSION command " + Twine(I
) +
1483 " has incorrect cmdsize");
1486 if (SourceLoadCmd
) {
1487 Err
= malformedError("more than one LC_SOURCE_VERSION command");
1490 SourceLoadCmd
= Load
.Ptr
;
1491 } else if (Load
.C
.cmd
== MachO::LC_MAIN
) {
1492 if (Load
.C
.cmdsize
!= sizeof(MachO::entry_point_command
)) {
1493 Err
= malformedError("LC_MAIN command " + Twine(I
) +
1494 " has incorrect cmdsize");
1497 if (EntryPointLoadCmd
) {
1498 Err
= malformedError("more than one LC_MAIN command");
1501 EntryPointLoadCmd
= Load
.Ptr
;
1502 } else if (Load
.C
.cmd
== MachO::LC_ENCRYPTION_INFO
) {
1503 if (Load
.C
.cmdsize
!= sizeof(MachO::encryption_info_command
)) {
1504 Err
= malformedError("LC_ENCRYPTION_INFO command " + Twine(I
) +
1505 " has incorrect cmdsize");
1508 MachO::encryption_info_command E
=
1509 getStruct
<MachO::encryption_info_command
>(*this, Load
.Ptr
);
1510 if ((Err
= checkEncryptCommand(*this, Load
, I
, E
.cryptoff
, E
.cryptsize
,
1511 &EncryptLoadCmd
, "LC_ENCRYPTION_INFO")))
1513 } else if (Load
.C
.cmd
== MachO::LC_ENCRYPTION_INFO_64
) {
1514 if (Load
.C
.cmdsize
!= sizeof(MachO::encryption_info_command_64
)) {
1515 Err
= malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I
) +
1516 " has incorrect cmdsize");
1519 MachO::encryption_info_command_64 E
=
1520 getStruct
<MachO::encryption_info_command_64
>(*this, Load
.Ptr
);
1521 if ((Err
= checkEncryptCommand(*this, Load
, I
, E
.cryptoff
, E
.cryptsize
,
1522 &EncryptLoadCmd
, "LC_ENCRYPTION_INFO_64")))
1524 } else if (Load
.C
.cmd
== MachO::LC_LINKER_OPTION
) {
1525 if ((Err
= checkLinkerOptCommand(*this, Load
, I
)))
1527 } else if (Load
.C
.cmd
== MachO::LC_SUB_FRAMEWORK
) {
1528 if (Load
.C
.cmdsize
< sizeof(MachO::sub_framework_command
)) {
1529 Err
= malformedError("load command " + Twine(I
) +
1530 " LC_SUB_FRAMEWORK cmdsize too small");
1533 MachO::sub_framework_command S
=
1534 getStruct
<MachO::sub_framework_command
>(*this, Load
.Ptr
);
1535 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_FRAMEWORK",
1536 sizeof(MachO::sub_framework_command
),
1537 "sub_framework_command", S
.umbrella
,
1540 } else if (Load
.C
.cmd
== MachO::LC_SUB_UMBRELLA
) {
1541 if (Load
.C
.cmdsize
< sizeof(MachO::sub_umbrella_command
)) {
1542 Err
= malformedError("load command " + Twine(I
) +
1543 " LC_SUB_UMBRELLA cmdsize too small");
1546 MachO::sub_umbrella_command S
=
1547 getStruct
<MachO::sub_umbrella_command
>(*this, Load
.Ptr
);
1548 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_UMBRELLA",
1549 sizeof(MachO::sub_umbrella_command
),
1550 "sub_umbrella_command", S
.sub_umbrella
,
1553 } else if (Load
.C
.cmd
== MachO::LC_SUB_LIBRARY
) {
1554 if (Load
.C
.cmdsize
< sizeof(MachO::sub_library_command
)) {
1555 Err
= malformedError("load command " + Twine(I
) +
1556 " LC_SUB_LIBRARY cmdsize too small");
1559 MachO::sub_library_command S
=
1560 getStruct
<MachO::sub_library_command
>(*this, Load
.Ptr
);
1561 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_LIBRARY",
1562 sizeof(MachO::sub_library_command
),
1563 "sub_library_command", S
.sub_library
,
1566 } else if (Load
.C
.cmd
== MachO::LC_SUB_CLIENT
) {
1567 if (Load
.C
.cmdsize
< sizeof(MachO::sub_client_command
)) {
1568 Err
= malformedError("load command " + Twine(I
) +
1569 " LC_SUB_CLIENT cmdsize too small");
1572 MachO::sub_client_command S
=
1573 getStruct
<MachO::sub_client_command
>(*this, Load
.Ptr
);
1574 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_CLIENT",
1575 sizeof(MachO::sub_client_command
),
1576 "sub_client_command", S
.client
, "client")))
1578 } else if (Load
.C
.cmd
== MachO::LC_ROUTINES
) {
1579 if (Load
.C
.cmdsize
!= sizeof(MachO::routines_command
)) {
1580 Err
= malformedError("LC_ROUTINES command " + Twine(I
) +
1581 " has incorrect cmdsize");
1584 if (RoutinesLoadCmd
) {
1585 Err
= malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1589 RoutinesLoadCmd
= Load
.Ptr
;
1590 } else if (Load
.C
.cmd
== MachO::LC_ROUTINES_64
) {
1591 if (Load
.C
.cmdsize
!= sizeof(MachO::routines_command_64
)) {
1592 Err
= malformedError("LC_ROUTINES_64 command " + Twine(I
) +
1593 " has incorrect cmdsize");
1596 if (RoutinesLoadCmd
) {
1597 Err
= malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1601 RoutinesLoadCmd
= Load
.Ptr
;
1602 } else if (Load
.C
.cmd
== MachO::LC_UNIXTHREAD
) {
1603 if ((Err
= checkThreadCommand(*this, Load
, I
, "LC_UNIXTHREAD")))
1605 if (UnixThreadLoadCmd
) {
1606 Err
= malformedError("more than one LC_UNIXTHREAD command");
1609 UnixThreadLoadCmd
= Load
.Ptr
;
1610 } else if (Load
.C
.cmd
== MachO::LC_THREAD
) {
1611 if ((Err
= checkThreadCommand(*this, Load
, I
, "LC_THREAD")))
1613 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1614 } else if (Load
.C
.cmd
== MachO::LC_TWOLEVEL_HINTS
) {
1615 if ((Err
= checkTwoLevelHintsCommand(*this, Load
, I
,
1616 &TwoLevelHintsLoadCmd
, Elements
)))
1618 } else if (Load
.C
.cmd
== MachO::LC_IDENT
) {
1619 // Note: LC_IDENT is ignored.
1621 } else if (isLoadCommandObsolete(Load
.C
.cmd
)) {
1622 Err
= malformedError("load command " + Twine(I
) + " for cmd value of: " +
1623 Twine(Load
.C
.cmd
) + " is obsolete and not "
1627 // TODO: generate a error for unknown load commands by default. But still
1628 // need work out an approach to allow or not allow unknown values like this
1629 // as an option for some uses like lldb.
1630 if (I
< LoadCommandCount
- 1) {
1631 if (auto LoadOrErr
= getNextLoadCommandInfo(*this, I
, Load
))
1634 Err
= LoadOrErr
.takeError();
1639 if (!SymtabLoadCmd
) {
1640 if (DysymtabLoadCmd
) {
1641 Err
= malformedError("contains LC_DYSYMTAB load command without a "
1642 "LC_SYMTAB load command");
1645 } else if (DysymtabLoadCmd
) {
1646 MachO::symtab_command Symtab
=
1647 getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
1648 MachO::dysymtab_command Dysymtab
=
1649 getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
1650 if (Dysymtab
.nlocalsym
!= 0 && Dysymtab
.ilocalsym
> Symtab
.nsyms
) {
1651 Err
= malformedError("ilocalsym in LC_DYSYMTAB load command "
1652 "extends past the end of the symbol table");
1655 uint64_t BigSize
= Dysymtab
.ilocalsym
;
1656 BigSize
+= Dysymtab
.nlocalsym
;
1657 if (Dysymtab
.nlocalsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1658 Err
= malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1659 "command extends past the end of the symbol table");
1662 if (Dysymtab
.nextdefsym
!= 0 && Dysymtab
.iextdefsym
> Symtab
.nsyms
) {
1663 Err
= malformedError("iextdefsym in LC_DYSYMTAB load command "
1664 "extends past the end of the symbol table");
1667 BigSize
= Dysymtab
.iextdefsym
;
1668 BigSize
+= Dysymtab
.nextdefsym
;
1669 if (Dysymtab
.nextdefsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1670 Err
= malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1671 "load command extends past the end of the symbol "
1675 if (Dysymtab
.nundefsym
!= 0 && Dysymtab
.iundefsym
> Symtab
.nsyms
) {
1676 Err
= malformedError("iundefsym in LC_DYSYMTAB load command "
1677 "extends past the end of the symbol table");
1680 BigSize
= Dysymtab
.iundefsym
;
1681 BigSize
+= Dysymtab
.nundefsym
;
1682 if (Dysymtab
.nundefsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1683 Err
= malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1684 " command extends past the end of the symbol table");
1688 if ((getHeader().filetype
== MachO::MH_DYLIB
||
1689 getHeader().filetype
== MachO::MH_DYLIB_STUB
) &&
1690 DyldIdLoadCmd
== nullptr) {
1691 Err
= malformedError("no LC_ID_DYLIB load command in dynamic library "
1695 assert(LoadCommands
.size() == LoadCommandCount
);
1697 Err
= Error::success();
1700 Error
MachOObjectFile::checkSymbolTable() const {
1703 MachO::mach_header_64 H_64
= MachOObjectFile::getHeader64();
1706 MachO::mach_header H
= MachOObjectFile::getHeader();
1713 uint64_t NValue
= 0;
1714 uint32_t SymbolIndex
= 0;
1715 MachO::symtab_command S
= getSymtabLoadCommand();
1716 for (const SymbolRef
&Symbol
: symbols()) {
1717 DataRefImpl SymDRI
= Symbol
.getRawDataRefImpl();
1719 MachO::nlist_64 STE_64
= getSymbol64TableEntry(SymDRI
);
1720 NType
= STE_64
.n_type
;
1721 NSect
= STE_64
.n_sect
;
1722 NDesc
= STE_64
.n_desc
;
1723 NStrx
= STE_64
.n_strx
;
1724 NValue
= STE_64
.n_value
;
1726 MachO::nlist STE
= getSymbolTableEntry(SymDRI
);
1731 NValue
= STE
.n_value
;
1733 if ((NType
& MachO::N_STAB
) == 0) {
1734 if ((NType
& MachO::N_TYPE
) == MachO::N_SECT
) {
1735 if (NSect
== 0 || NSect
> Sections
.size())
1736 return malformedError("bad section index: " + Twine((int)NSect
) +
1737 " for symbol at index " + Twine(SymbolIndex
));
1739 if ((NType
& MachO::N_TYPE
) == MachO::N_INDR
) {
1740 if (NValue
>= S
.strsize
)
1741 return malformedError("bad n_value: " + Twine((int)NValue
) + " past "
1742 "the end of string table, for N_INDR symbol at "
1743 "index " + Twine(SymbolIndex
));
1745 if ((Flags
& MachO::MH_TWOLEVEL
) == MachO::MH_TWOLEVEL
&&
1746 (((NType
& MachO::N_TYPE
) == MachO::N_UNDF
&& NValue
== 0) ||
1747 (NType
& MachO::N_TYPE
) == MachO::N_PBUD
)) {
1748 uint32_t LibraryOrdinal
= MachO::GET_LIBRARY_ORDINAL(NDesc
);
1749 if (LibraryOrdinal
!= 0 &&
1750 LibraryOrdinal
!= MachO::EXECUTABLE_ORDINAL
&&
1751 LibraryOrdinal
!= MachO::DYNAMIC_LOOKUP_ORDINAL
&&
1752 LibraryOrdinal
- 1 >= Libraries
.size() ) {
1753 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal
) +
1754 " for symbol at index " + Twine(SymbolIndex
));
1758 if (NStrx
>= S
.strsize
)
1759 return malformedError("bad string table index: " + Twine((int)NStrx
) +
1760 " past the end of string table, for symbol at "
1761 "index " + Twine(SymbolIndex
));
1764 return Error::success();
1767 void MachOObjectFile::moveSymbolNext(DataRefImpl
&Symb
) const {
1768 unsigned SymbolTableEntrySize
= is64Bit() ?
1769 sizeof(MachO::nlist_64
) :
1770 sizeof(MachO::nlist
);
1771 Symb
.p
+= SymbolTableEntrySize
;
1774 Expected
<StringRef
> MachOObjectFile::getSymbolName(DataRefImpl Symb
) const {
1775 StringRef StringTable
= getStringTableData();
1776 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1777 if (Entry
.n_strx
== 0)
1778 // A n_strx value of 0 indicates that no name is associated with a
1779 // particular symbol table entry.
1781 const char *Start
= &StringTable
.data()[Entry
.n_strx
];
1782 if (Start
< getData().begin() || Start
>= getData().end()) {
1783 return malformedError("bad string index: " + Twine(Entry
.n_strx
) +
1784 " for symbol at index " + Twine(getSymbolIndex(Symb
)));
1786 return StringRef(Start
);
1789 unsigned MachOObjectFile::getSectionType(SectionRef Sec
) const {
1790 DataRefImpl DRI
= Sec
.getRawDataRefImpl();
1791 uint32_t Flags
= getSectionFlags(*this, DRI
);
1792 return Flags
& MachO::SECTION_TYPE
;
1795 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym
) const {
1797 MachO::nlist_64 Entry
= getSymbol64TableEntry(Sym
);
1798 return Entry
.n_value
;
1800 MachO::nlist Entry
= getSymbolTableEntry(Sym
);
1801 return Entry
.n_value
;
1804 // getIndirectName() returns the name of the alias'ed symbol who's string table
1805 // index is in the n_value field.
1806 std::error_code
MachOObjectFile::getIndirectName(DataRefImpl Symb
,
1807 StringRef
&Res
) const {
1808 StringRef StringTable
= getStringTableData();
1809 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1810 if ((Entry
.n_type
& MachO::N_TYPE
) != MachO::N_INDR
)
1811 return object_error::parse_failed
;
1812 uint64_t NValue
= getNValue(Symb
);
1813 if (NValue
>= StringTable
.size())
1814 return object_error::parse_failed
;
1815 const char *Start
= &StringTable
.data()[NValue
];
1816 Res
= StringRef(Start
);
1817 return std::error_code();
1820 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym
) const {
1821 return getNValue(Sym
);
1824 Expected
<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym
) const {
1825 return getSymbolValue(Sym
);
1828 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI
) const {
1829 uint32_t Flags
= cantFail(getSymbolFlags(DRI
));
1830 if (Flags
& SymbolRef::SF_Common
) {
1831 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, DRI
);
1832 return 1 << MachO::GET_COMM_ALIGN(Entry
.n_desc
);
1837 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI
) const {
1838 return getNValue(DRI
);
1841 Expected
<SymbolRef::Type
>
1842 MachOObjectFile::getSymbolType(DataRefImpl Symb
) const {
1843 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1844 uint8_t n_type
= Entry
.n_type
;
1846 // If this is a STAB debugging symbol, we can do nothing more.
1847 if (n_type
& MachO::N_STAB
)
1848 return SymbolRef::ST_Debug
;
1850 switch (n_type
& MachO::N_TYPE
) {
1851 case MachO::N_UNDF
:
1852 return SymbolRef::ST_Unknown
;
1853 case MachO::N_SECT
:
1854 Expected
<section_iterator
> SecOrError
= getSymbolSection(Symb
);
1856 return SecOrError
.takeError();
1857 section_iterator Sec
= *SecOrError
;
1858 if (Sec
== section_end())
1859 return SymbolRef::ST_Other
;
1860 if (Sec
->isData() || Sec
->isBSS())
1861 return SymbolRef::ST_Data
;
1862 return SymbolRef::ST_Function
;
1864 return SymbolRef::ST_Other
;
1867 Expected
<uint32_t> MachOObjectFile::getSymbolFlags(DataRefImpl DRI
) const {
1868 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, DRI
);
1870 uint8_t MachOType
= Entry
.n_type
;
1871 uint16_t MachOFlags
= Entry
.n_desc
;
1873 uint32_t Result
= SymbolRef::SF_None
;
1875 if ((MachOType
& MachO::N_TYPE
) == MachO::N_INDR
)
1876 Result
|= SymbolRef::SF_Indirect
;
1878 if (MachOType
& MachO::N_STAB
)
1879 Result
|= SymbolRef::SF_FormatSpecific
;
1881 if (MachOType
& MachO::N_EXT
) {
1882 Result
|= SymbolRef::SF_Global
;
1883 if ((MachOType
& MachO::N_TYPE
) == MachO::N_UNDF
) {
1885 Result
|= SymbolRef::SF_Common
;
1887 Result
|= SymbolRef::SF_Undefined
;
1890 if (MachOType
& MachO::N_PEXT
)
1891 Result
|= SymbolRef::SF_Hidden
;
1893 Result
|= SymbolRef::SF_Exported
;
1895 } else if (MachOType
& MachO::N_PEXT
)
1896 Result
|= SymbolRef::SF_Hidden
;
1898 if (MachOFlags
& (MachO::N_WEAK_REF
| MachO::N_WEAK_DEF
))
1899 Result
|= SymbolRef::SF_Weak
;
1901 if (MachOFlags
& (MachO::N_ARM_THUMB_DEF
))
1902 Result
|= SymbolRef::SF_Thumb
;
1904 if ((MachOType
& MachO::N_TYPE
) == MachO::N_ABS
)
1905 Result
|= SymbolRef::SF_Absolute
;
1910 Expected
<section_iterator
>
1911 MachOObjectFile::getSymbolSection(DataRefImpl Symb
) const {
1912 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1913 uint8_t index
= Entry
.n_sect
;
1916 return section_end();
1918 DRI
.d
.a
= index
- 1;
1919 if (DRI
.d
.a
>= Sections
.size()){
1920 return malformedError("bad section index: " + Twine((int)index
) +
1921 " for symbol at index " + Twine(getSymbolIndex(Symb
)));
1923 return section_iterator(SectionRef(DRI
, this));
1926 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym
) const {
1927 MachO::nlist_base Entry
=
1928 getSymbolTableEntryBase(*this, Sym
.getRawDataRefImpl());
1929 return Entry
.n_sect
- 1;
1932 void MachOObjectFile::moveSectionNext(DataRefImpl
&Sec
) const {
1936 Expected
<StringRef
> MachOObjectFile::getSectionName(DataRefImpl Sec
) const {
1937 ArrayRef
<char> Raw
= getSectionRawName(Sec
);
1938 return parseSegmentOrSectionName(Raw
.data());
1941 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec
) const {
1943 return getSection64(Sec
).addr
;
1944 return getSection(Sec
).addr
;
1947 uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec
) const {
1951 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec
) const {
1952 // In the case if a malformed Mach-O file where the section offset is past
1953 // the end of the file or some part of the section size is past the end of
1954 // the file return a size of zero or a size that covers the rest of the file
1955 // but does not extend past the end of the file.
1956 uint32_t SectOffset
, SectType
;
1960 MachO::section_64 Sect
= getSection64(Sec
);
1961 SectOffset
= Sect
.offset
;
1962 SectSize
= Sect
.size
;
1963 SectType
= Sect
.flags
& MachO::SECTION_TYPE
;
1965 MachO::section Sect
= getSection(Sec
);
1966 SectOffset
= Sect
.offset
;
1967 SectSize
= Sect
.size
;
1968 SectType
= Sect
.flags
& MachO::SECTION_TYPE
;
1970 if (SectType
== MachO::S_ZEROFILL
|| SectType
== MachO::S_GB_ZEROFILL
)
1972 uint64_t FileSize
= getData().size();
1973 if (SectOffset
> FileSize
)
1975 if (FileSize
- SectOffset
< SectSize
)
1976 return FileSize
- SectOffset
;
1980 ArrayRef
<uint8_t> MachOObjectFile::getSectionContents(uint32_t Offset
,
1981 uint64_t Size
) const {
1982 return arrayRefFromStringRef(getData().substr(Offset
, Size
));
1985 Expected
<ArrayRef
<uint8_t>>
1986 MachOObjectFile::getSectionContents(DataRefImpl Sec
) const {
1991 MachO::section_64 Sect
= getSection64(Sec
);
1992 Offset
= Sect
.offset
;
1995 MachO::section Sect
= getSection(Sec
);
1996 Offset
= Sect
.offset
;
2000 return getSectionContents(Offset
, Size
);
2003 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
2006 MachO::section_64 Sect
= getSection64(Sec
);
2009 MachO::section Sect
= getSection(Sec
);
2013 return uint64_t(1) << Align
;
2016 Expected
<SectionRef
> MachOObjectFile::getSection(unsigned SectionIndex
) const {
2017 if (SectionIndex
< 1 || SectionIndex
> Sections
.size())
2018 return malformedError("bad section index: " + Twine((int)SectionIndex
));
2021 DRI
.d
.a
= SectionIndex
- 1;
2022 return SectionRef(DRI
, this);
2025 Expected
<SectionRef
> MachOObjectFile::getSection(StringRef SectionName
) const {
2026 for (const SectionRef
&Section
: sections()) {
2027 auto NameOrErr
= Section
.getName();
2029 return NameOrErr
.takeError();
2030 if (*NameOrErr
== SectionName
)
2033 return errorCodeToError(object_error::parse_failed
);
2036 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
2040 bool MachOObjectFile::isSectionText(DataRefImpl Sec
) const {
2041 uint32_t Flags
= getSectionFlags(*this, Sec
);
2042 return Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
;
2045 bool MachOObjectFile::isSectionData(DataRefImpl Sec
) const {
2046 uint32_t Flags
= getSectionFlags(*this, Sec
);
2047 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2048 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
2049 !(SectionType
== MachO::S_ZEROFILL
||
2050 SectionType
== MachO::S_GB_ZEROFILL
);
2053 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec
) const {
2054 uint32_t Flags
= getSectionFlags(*this, Sec
);
2055 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2056 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
2057 (SectionType
== MachO::S_ZEROFILL
||
2058 SectionType
== MachO::S_GB_ZEROFILL
);
2061 bool MachOObjectFile::isDebugSection(DataRefImpl Sec
) const {
2062 Expected
<StringRef
> SectionNameOrErr
= getSectionName(Sec
);
2063 if (!SectionNameOrErr
) {
2064 // TODO: Report the error message properly.
2065 consumeError(SectionNameOrErr
.takeError());
2068 StringRef SectionName
= SectionNameOrErr
.get();
2069 return SectionName
.startswith("__debug") ||
2070 SectionName
.startswith("__zdebug") ||
2071 SectionName
.startswith("__apple") || SectionName
== "__gdb_index" ||
2072 SectionName
== "__swift_ast";
2076 template <typename LoadCommandType
>
2077 ArrayRef
<uint8_t> getSegmentContents(const MachOObjectFile
&Obj
,
2078 MachOObjectFile::LoadCommandInfo LoadCmd
,
2079 StringRef SegmentName
) {
2080 auto SegmentOrErr
= getStructOrErr
<LoadCommandType
>(Obj
, LoadCmd
.Ptr
);
2081 if (!SegmentOrErr
) {
2082 consumeError(SegmentOrErr
.takeError());
2085 auto &Segment
= SegmentOrErr
.get();
2086 if (StringRef(Segment
.segname
, 16).startswith(SegmentName
))
2087 return arrayRefFromStringRef(Obj
.getData().slice(
2088 Segment
.fileoff
, Segment
.fileoff
+ Segment
.filesize
));
2092 template <typename LoadCommandType
>
2093 ArrayRef
<uint8_t> getSegmentContents(const MachOObjectFile
&Obj
,
2094 MachOObjectFile::LoadCommandInfo LoadCmd
) {
2095 auto SegmentOrErr
= getStructOrErr
<LoadCommandType
>(Obj
, LoadCmd
.Ptr
);
2096 if (!SegmentOrErr
) {
2097 consumeError(SegmentOrErr
.takeError());
2100 auto &Segment
= SegmentOrErr
.get();
2101 return arrayRefFromStringRef(
2102 Obj
.getData().slice(Segment
.fileoff
, Segment
.fileoff
+ Segment
.filesize
));
2107 MachOObjectFile::getSegmentContents(StringRef SegmentName
) const {
2108 for (auto LoadCmd
: load_commands()) {
2109 ArrayRef
<uint8_t> Contents
;
2110 switch (LoadCmd
.C
.cmd
) {
2111 case MachO::LC_SEGMENT
:
2112 Contents
= ::getSegmentContents
<MachO::segment_command
>(*this, LoadCmd
,
2115 case MachO::LC_SEGMENT_64
:
2116 Contents
= ::getSegmentContents
<MachO::segment_command_64
>(*this, LoadCmd
,
2122 if (!Contents
.empty())
2129 MachOObjectFile::getSegmentContents(size_t SegmentIndex
) const {
2131 for (auto LoadCmd
: load_commands()) {
2132 switch (LoadCmd
.C
.cmd
) {
2133 case MachO::LC_SEGMENT
:
2134 if (Idx
== SegmentIndex
)
2135 return ::getSegmentContents
<MachO::segment_command
>(*this, LoadCmd
);
2138 case MachO::LC_SEGMENT_64
:
2139 if (Idx
== SegmentIndex
)
2140 return ::getSegmentContents
<MachO::segment_command_64
>(*this, LoadCmd
);
2150 unsigned MachOObjectFile::getSectionID(SectionRef Sec
) const {
2151 return Sec
.getRawDataRefImpl().d
.a
;
2154 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec
) const {
2155 uint32_t Flags
= getSectionFlags(*this, Sec
);
2156 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2157 return SectionType
== MachO::S_ZEROFILL
||
2158 SectionType
== MachO::S_GB_ZEROFILL
;
2161 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec
) const {
2162 StringRef SegmentName
= getSectionFinalSegmentName(Sec
);
2163 if (Expected
<StringRef
> NameOrErr
= getSectionName(Sec
))
2164 return (SegmentName
== "__LLVM" && *NameOrErr
== "__bitcode");
2168 bool MachOObjectFile::isSectionStripped(DataRefImpl Sec
) const {
2170 return getSection64(Sec
).offset
== 0;
2171 return getSection(Sec
).offset
== 0;
2174 relocation_iterator
MachOObjectFile::section_rel_begin(DataRefImpl Sec
) const {
2178 return relocation_iterator(RelocationRef(Ret
, this));
2182 MachOObjectFile::section_rel_end(DataRefImpl Sec
) const {
2185 MachO::section_64 Sect
= getSection64(Sec
);
2188 MachO::section Sect
= getSection(Sec
);
2195 return relocation_iterator(RelocationRef(Ret
, this));
2198 relocation_iterator
MachOObjectFile::extrel_begin() const {
2200 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2201 Ret
.d
.a
= 0; // Would normally be a section index.
2202 Ret
.d
.b
= 0; // Index into the external relocations
2203 return relocation_iterator(RelocationRef(Ret
, this));
2206 relocation_iterator
MachOObjectFile::extrel_end() const {
2207 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2209 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2210 Ret
.d
.a
= 0; // Would normally be a section index.
2211 Ret
.d
.b
= DysymtabLoadCmd
.nextrel
; // Index into the external relocations
2212 return relocation_iterator(RelocationRef(Ret
, this));
2215 relocation_iterator
MachOObjectFile::locrel_begin() const {
2217 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2218 Ret
.d
.a
= 1; // Would normally be a section index.
2219 Ret
.d
.b
= 0; // Index into the local relocations
2220 return relocation_iterator(RelocationRef(Ret
, this));
2223 relocation_iterator
MachOObjectFile::locrel_end() const {
2224 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2226 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2227 Ret
.d
.a
= 1; // Would normally be a section index.
2228 Ret
.d
.b
= DysymtabLoadCmd
.nlocrel
; // Index into the local relocations
2229 return relocation_iterator(RelocationRef(Ret
, this));
2232 void MachOObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
2236 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
2237 assert((getHeader().filetype
== MachO::MH_OBJECT
||
2238 getHeader().filetype
== MachO::MH_KEXT_BUNDLE
) &&
2239 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2240 MachO::any_relocation_info RE
= getRelocation(Rel
);
2241 return getAnyRelocationAddress(RE
);
2245 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
2246 MachO::any_relocation_info RE
= getRelocation(Rel
);
2247 if (isRelocationScattered(RE
))
2248 return symbol_end();
2250 uint32_t SymbolIdx
= getPlainRelocationSymbolNum(RE
);
2251 bool isExtern
= getPlainRelocationExternal(RE
);
2253 return symbol_end();
2255 MachO::symtab_command S
= getSymtabLoadCommand();
2256 unsigned SymbolTableEntrySize
= is64Bit() ?
2257 sizeof(MachO::nlist_64
) :
2258 sizeof(MachO::nlist
);
2259 uint64_t Offset
= S
.symoff
+ SymbolIdx
* SymbolTableEntrySize
;
2261 Sym
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2262 return symbol_iterator(SymbolRef(Sym
, this));
2266 MachOObjectFile::getRelocationSection(DataRefImpl Rel
) const {
2267 return section_iterator(getAnyRelocationSection(getRelocation(Rel
)));
2270 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel
) const {
2271 MachO::any_relocation_info RE
= getRelocation(Rel
);
2272 return getAnyRelocationType(RE
);
2275 void MachOObjectFile::getRelocationTypeName(
2276 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
2278 uint64_t RType
= getRelocationType(Rel
);
2280 unsigned Arch
= this->getArch();
2284 static const char *const Table
[] = {
2285 "GENERIC_RELOC_VANILLA",
2286 "GENERIC_RELOC_PAIR",
2287 "GENERIC_RELOC_SECTDIFF",
2288 "GENERIC_RELOC_PB_LA_PTR",
2289 "GENERIC_RELOC_LOCAL_SECTDIFF",
2290 "GENERIC_RELOC_TLV" };
2298 case Triple::x86_64
: {
2299 static const char *const Table
[] = {
2300 "X86_64_RELOC_UNSIGNED",
2301 "X86_64_RELOC_SIGNED",
2302 "X86_64_RELOC_BRANCH",
2303 "X86_64_RELOC_GOT_LOAD",
2305 "X86_64_RELOC_SUBTRACTOR",
2306 "X86_64_RELOC_SIGNED_1",
2307 "X86_64_RELOC_SIGNED_2",
2308 "X86_64_RELOC_SIGNED_4",
2309 "X86_64_RELOC_TLV" };
2318 static const char *const Table
[] = {
2319 "ARM_RELOC_VANILLA",
2321 "ARM_RELOC_SECTDIFF",
2322 "ARM_RELOC_LOCAL_SECTDIFF",
2323 "ARM_RELOC_PB_LA_PTR",
2325 "ARM_THUMB_RELOC_BR22",
2326 "ARM_THUMB_32BIT_BRANCH",
2328 "ARM_RELOC_HALF_SECTDIFF" };
2336 case Triple::aarch64
:
2337 case Triple::aarch64_32
: {
2338 static const char *const Table
[] = {
2339 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2340 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2341 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2342 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2343 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2344 "ARM64_RELOC_ADDEND"
2347 if (RType
>= std::size(Table
))
2354 static const char *const Table
[] = {
2355 "PPC_RELOC_VANILLA",
2363 "PPC_RELOC_SECTDIFF",
2364 "PPC_RELOC_PB_LA_PTR",
2365 "PPC_RELOC_HI16_SECTDIFF",
2366 "PPC_RELOC_LO16_SECTDIFF",
2367 "PPC_RELOC_HA16_SECTDIFF",
2369 "PPC_RELOC_LO14_SECTDIFF",
2370 "PPC_RELOC_LOCAL_SECTDIFF" };
2378 case Triple::UnknownArch
:
2382 Result
.append(res
.begin(), res
.end());
2385 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel
) const {
2386 MachO::any_relocation_info RE
= getRelocation(Rel
);
2387 return getAnyRelocationLength(RE
);
2391 // guessLibraryShortName() is passed a name of a dynamic library and returns a
2392 // guess on what the short name is. Then name is returned as a substring of the
2393 // StringRef Name passed in. The name of the dynamic library is recognized as
2394 // a framework if it has one of the two following forms:
2395 // Foo.framework/Versions/A/Foo
2396 // Foo.framework/Foo
2397 // Where A and Foo can be any string. And may contain a trailing suffix
2398 // starting with an underbar. If the Name is recognized as a framework then
2399 // isFramework is set to true else it is set to false. If the Name has a
2400 // suffix then Suffix is set to the substring in Name that contains the suffix
2401 // else it is set to a NULL StringRef.
2403 // The Name of the dynamic library is recognized as a library name if it has
2404 // one of the two following forms:
2408 // The library may have a suffix trailing the name Foo of the form:
2409 // libFoo_profile.A.dylib
2410 // libFoo_profile.dylib
2411 // These dyld image suffixes are separated from the short name by a '_'
2412 // character. Because the '_' character is commonly used to separate words in
2413 // filenames guessLibraryShortName() cannot reliably separate a dylib's short
2414 // name from an arbitrary image suffix; imagine if both the short name and the
2415 // suffix contains an '_' character! To better deal with this ambiguity,
2416 // guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
2417 // Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
2418 // guessing incorrectly.
2420 // The Name of the dynamic library is also recognized as a library name if it
2421 // has the following form:
2424 // If the Name of the dynamic library is none of the forms above then a NULL
2425 // StringRef is returned.
2426 StringRef
MachOObjectFile::guessLibraryShortName(StringRef Name
,
2428 StringRef
&Suffix
) {
2429 StringRef Foo
, F
, DotFramework
, V
, Dylib
, Lib
, Dot
, Qtx
;
2430 size_t a
, b
, c
, d
, Idx
;
2432 isFramework
= false;
2433 Suffix
= StringRef();
2435 // Pull off the last component and make Foo point to it
2436 a
= Name
.rfind('/');
2437 if (a
== Name
.npos
|| a
== 0)
2439 Foo
= Name
.slice(a
+1, Name
.npos
);
2441 // Look for a suffix starting with a '_'
2442 Idx
= Foo
.rfind('_');
2443 if (Idx
!= Foo
.npos
&& Foo
.size() >= 2) {
2444 Suffix
= Foo
.slice(Idx
, Foo
.npos
);
2445 if (Suffix
!= "_debug" && Suffix
!= "_profile")
2446 Suffix
= StringRef();
2448 Foo
= Foo
.slice(0, Idx
);
2451 // First look for the form Foo.framework/Foo
2452 b
= Name
.rfind('/', a
);
2457 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2458 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2459 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2460 if (F
== Foo
&& DotFramework
== ".framework/") {
2465 // Next look for the form Foo.framework/Versions/A/Foo
2468 c
= Name
.rfind('/', b
);
2469 if (c
== Name
.npos
|| c
== 0)
2471 V
= Name
.slice(c
+1, Name
.npos
);
2472 if (!V
.startswith("Versions/"))
2474 d
= Name
.rfind('/', c
);
2479 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2480 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2481 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2482 if (F
== Foo
&& DotFramework
== ".framework/") {
2488 // pull off the suffix after the "." and make a point to it
2489 a
= Name
.rfind('.');
2490 if (a
== Name
.npos
|| a
== 0)
2492 Dylib
= Name
.slice(a
, Name
.npos
);
2493 if (Dylib
!= ".dylib")
2496 // First pull off the version letter for the form Foo.A.dylib if any.
2498 Dot
= Name
.slice(a
-2, a
-1);
2503 b
= Name
.rfind('/', a
);
2508 // ignore any suffix after an underbar like Foo_profile.A.dylib
2509 Idx
= Name
.rfind('_');
2510 if (Idx
!= Name
.npos
&& Idx
!= b
) {
2511 Lib
= Name
.slice(b
, Idx
);
2512 Suffix
= Name
.slice(Idx
, a
);
2513 if (Suffix
!= "_debug" && Suffix
!= "_profile") {
2514 Suffix
= StringRef();
2515 Lib
= Name
.slice(b
, a
);
2519 Lib
= Name
.slice(b
, a
);
2520 // There are incorrect library names of the form:
2521 // libATS.A_profile.dylib so check for these.
2522 if (Lib
.size() >= 3) {
2523 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2525 Lib
= Lib
.slice(0, Lib
.size()-2);
2530 Qtx
= Name
.slice(a
, Name
.npos
);
2533 b
= Name
.rfind('/', a
);
2535 Lib
= Name
.slice(0, a
);
2537 Lib
= Name
.slice(b
+1, a
);
2538 // There are library names of the form: QT.A.qtx so check for these.
2539 if (Lib
.size() >= 3) {
2540 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2542 Lib
= Lib
.slice(0, Lib
.size()-2);
2547 // getLibraryShortNameByIndex() is used to get the short name of the library
2548 // for an undefined symbol in a linked Mach-O binary that was linked with the
2549 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
2550 // It is passed the index (0 - based) of the library as translated from
2551 // GET_LIBRARY_ORDINAL (1 - based).
2552 std::error_code
MachOObjectFile::getLibraryShortNameByIndex(unsigned Index
,
2553 StringRef
&Res
) const {
2554 if (Index
>= Libraries
.size())
2555 return object_error::parse_failed
;
2557 // If the cache of LibrariesShortNames is not built up do that first for
2558 // all the Libraries.
2559 if (LibrariesShortNames
.size() == 0) {
2560 for (unsigned i
= 0; i
< Libraries
.size(); i
++) {
2562 getStructOrErr
<MachO::dylib_command
>(*this, Libraries
[i
]);
2564 return object_error::parse_failed
;
2565 MachO::dylib_command D
= CommandOrErr
.get();
2566 if (D
.dylib
.name
>= D
.cmdsize
)
2567 return object_error::parse_failed
;
2568 const char *P
= (const char *)(Libraries
[i
]) + D
.dylib
.name
;
2569 StringRef Name
= StringRef(P
);
2570 if (D
.dylib
.name
+Name
.size() >= D
.cmdsize
)
2571 return object_error::parse_failed
;
2574 StringRef shortName
= guessLibraryShortName(Name
, isFramework
, Suffix
);
2575 if (shortName
.empty())
2576 LibrariesShortNames
.push_back(Name
);
2578 LibrariesShortNames
.push_back(shortName
);
2582 Res
= LibrariesShortNames
[Index
];
2583 return std::error_code();
2586 uint32_t MachOObjectFile::getLibraryCount() const {
2587 return Libraries
.size();
2591 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel
) const {
2593 Sec
.d
.a
= Rel
->getRawDataRefImpl().d
.a
;
2594 return section_iterator(SectionRef(Sec
, this));
2597 basic_symbol_iterator
MachOObjectFile::symbol_begin() const {
2599 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2600 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2601 return basic_symbol_iterator(SymbolRef(DRI
, this));
2603 return getSymbolByIndex(0);
2606 basic_symbol_iterator
MachOObjectFile::symbol_end() const {
2608 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2609 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2610 return basic_symbol_iterator(SymbolRef(DRI
, this));
2612 unsigned SymbolTableEntrySize
= is64Bit() ?
2613 sizeof(MachO::nlist_64
) :
2614 sizeof(MachO::nlist
);
2615 unsigned Offset
= Symtab
.symoff
+
2616 Symtab
.nsyms
* SymbolTableEntrySize
;
2617 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2618 return basic_symbol_iterator(SymbolRef(DRI
, this));
2621 symbol_iterator
MachOObjectFile::getSymbolByIndex(unsigned Index
) const {
2622 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2623 if (!SymtabLoadCmd
|| Index
>= Symtab
.nsyms
)
2624 report_fatal_error("Requested symbol index is out of range.");
2625 unsigned SymbolTableEntrySize
=
2626 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2628 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2629 DRI
.p
+= Index
* SymbolTableEntrySize
;
2630 return basic_symbol_iterator(SymbolRef(DRI
, this));
2633 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb
) const {
2634 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2636 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2637 unsigned SymbolTableEntrySize
=
2638 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2639 DataRefImpl DRIstart
;
2640 DRIstart
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2641 uint64_t Index
= (Symb
.p
- DRIstart
.p
) / SymbolTableEntrySize
;
2645 section_iterator
MachOObjectFile::section_begin() const {
2647 return section_iterator(SectionRef(DRI
, this));
2650 section_iterator
MachOObjectFile::section_end() const {
2652 DRI
.d
.a
= Sections
.size();
2653 return section_iterator(SectionRef(DRI
, this));
2656 uint8_t MachOObjectFile::getBytesInAddress() const {
2657 return is64Bit() ? 8 : 4;
2660 StringRef
MachOObjectFile::getFileFormatName() const {
2661 unsigned CPUType
= getCPUType(*this);
2664 case MachO::CPU_TYPE_I386
:
2665 return "Mach-O 32-bit i386";
2666 case MachO::CPU_TYPE_ARM
:
2667 return "Mach-O arm";
2668 case MachO::CPU_TYPE_ARM64_32
:
2669 return "Mach-O arm64 (ILP32)";
2670 case MachO::CPU_TYPE_POWERPC
:
2671 return "Mach-O 32-bit ppc";
2673 return "Mach-O 32-bit unknown";
2678 case MachO::CPU_TYPE_X86_64
:
2679 return "Mach-O 64-bit x86-64";
2680 case MachO::CPU_TYPE_ARM64
:
2681 return "Mach-O arm64";
2682 case MachO::CPU_TYPE_POWERPC64
:
2683 return "Mach-O 64-bit ppc64";
2685 return "Mach-O 64-bit unknown";
2689 Triple::ArchType
MachOObjectFile::getArch(uint32_t CPUType
, uint32_t CPUSubType
) {
2691 case MachO::CPU_TYPE_I386
:
2693 case MachO::CPU_TYPE_X86_64
:
2694 return Triple::x86_64
;
2695 case MachO::CPU_TYPE_ARM
:
2697 case MachO::CPU_TYPE_ARM64
:
2698 return Triple::aarch64
;
2699 case MachO::CPU_TYPE_ARM64_32
:
2700 return Triple::aarch64_32
;
2701 case MachO::CPU_TYPE_POWERPC
:
2703 case MachO::CPU_TYPE_POWERPC64
:
2704 return Triple::ppc64
;
2706 return Triple::UnknownArch
;
2710 Triple
MachOObjectFile::getArchTriple(uint32_t CPUType
, uint32_t CPUSubType
,
2711 const char **McpuDefault
,
2712 const char **ArchFlag
) {
2714 *McpuDefault
= nullptr;
2716 *ArchFlag
= nullptr;
2719 case MachO::CPU_TYPE_I386
:
2720 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2721 case MachO::CPU_SUBTYPE_I386_ALL
:
2724 return Triple("i386-apple-darwin");
2728 case MachO::CPU_TYPE_X86_64
:
2729 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2730 case MachO::CPU_SUBTYPE_X86_64_ALL
:
2732 *ArchFlag
= "x86_64";
2733 return Triple("x86_64-apple-darwin");
2734 case MachO::CPU_SUBTYPE_X86_64_H
:
2736 *ArchFlag
= "x86_64h";
2737 return Triple("x86_64h-apple-darwin");
2741 case MachO::CPU_TYPE_ARM
:
2742 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2743 case MachO::CPU_SUBTYPE_ARM_V4T
:
2745 *ArchFlag
= "armv4t";
2746 return Triple("armv4t-apple-darwin");
2747 case MachO::CPU_SUBTYPE_ARM_V5TEJ
:
2749 *ArchFlag
= "armv5e";
2750 return Triple("armv5e-apple-darwin");
2751 case MachO::CPU_SUBTYPE_ARM_XSCALE
:
2753 *ArchFlag
= "xscale";
2754 return Triple("xscale-apple-darwin");
2755 case MachO::CPU_SUBTYPE_ARM_V6
:
2757 *ArchFlag
= "armv6";
2758 return Triple("armv6-apple-darwin");
2759 case MachO::CPU_SUBTYPE_ARM_V6M
:
2761 *McpuDefault
= "cortex-m0";
2763 *ArchFlag
= "armv6m";
2764 return Triple("armv6m-apple-darwin");
2765 case MachO::CPU_SUBTYPE_ARM_V7
:
2767 *ArchFlag
= "armv7";
2768 return Triple("armv7-apple-darwin");
2769 case MachO::CPU_SUBTYPE_ARM_V7EM
:
2771 *McpuDefault
= "cortex-m4";
2773 *ArchFlag
= "armv7em";
2774 return Triple("thumbv7em-apple-darwin");
2775 case MachO::CPU_SUBTYPE_ARM_V7K
:
2777 *McpuDefault
= "cortex-a7";
2779 *ArchFlag
= "armv7k";
2780 return Triple("armv7k-apple-darwin");
2781 case MachO::CPU_SUBTYPE_ARM_V7M
:
2783 *McpuDefault
= "cortex-m3";
2785 *ArchFlag
= "armv7m";
2786 return Triple("thumbv7m-apple-darwin");
2787 case MachO::CPU_SUBTYPE_ARM_V7S
:
2789 *McpuDefault
= "cortex-a7";
2791 *ArchFlag
= "armv7s";
2792 return Triple("armv7s-apple-darwin");
2796 case MachO::CPU_TYPE_ARM64
:
2797 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2798 case MachO::CPU_SUBTYPE_ARM64_ALL
:
2800 *McpuDefault
= "cyclone";
2802 *ArchFlag
= "arm64";
2803 return Triple("arm64-apple-darwin");
2804 case MachO::CPU_SUBTYPE_ARM64E
:
2806 *McpuDefault
= "apple-a12";
2808 *ArchFlag
= "arm64e";
2809 return Triple("arm64e-apple-darwin");
2813 case MachO::CPU_TYPE_ARM64_32
:
2814 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2815 case MachO::CPU_SUBTYPE_ARM64_32_V8
:
2817 *McpuDefault
= "cyclone";
2819 *ArchFlag
= "arm64_32";
2820 return Triple("arm64_32-apple-darwin");
2824 case MachO::CPU_TYPE_POWERPC
:
2825 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2826 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2829 return Triple("ppc-apple-darwin");
2833 case MachO::CPU_TYPE_POWERPC64
:
2834 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2835 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2837 *ArchFlag
= "ppc64";
2838 return Triple("ppc64-apple-darwin");
2847 Triple
MachOObjectFile::getHostArch() {
2848 return Triple(sys::getDefaultTargetTriple());
2851 bool MachOObjectFile::isValidArch(StringRef ArchFlag
) {
2852 auto validArchs
= getValidArchs();
2853 return llvm::is_contained(validArchs
, ArchFlag
);
2856 ArrayRef
<StringRef
> MachOObjectFile::getValidArchs() {
2857 static const std::array
<StringRef
, 18> ValidArchs
= {{
2881 Triple::ArchType
MachOObjectFile::getArch() const {
2882 return getArch(getCPUType(*this), getCPUSubType(*this));
2885 Triple
MachOObjectFile::getArchTriple(const char **McpuDefault
) const {
2886 return getArchTriple(Header
.cputype
, Header
.cpusubtype
, McpuDefault
);
2889 relocation_iterator
MachOObjectFile::section_rel_begin(unsigned Index
) const {
2892 return section_rel_begin(DRI
);
2895 relocation_iterator
MachOObjectFile::section_rel_end(unsigned Index
) const {
2898 return section_rel_end(DRI
);
2901 dice_iterator
MachOObjectFile::begin_dices() const {
2903 if (!DataInCodeLoadCmd
)
2904 return dice_iterator(DiceRef(DRI
, this));
2906 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2907 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, DicLC
.dataoff
));
2908 return dice_iterator(DiceRef(DRI
, this));
2911 dice_iterator
MachOObjectFile::end_dices() const {
2913 if (!DataInCodeLoadCmd
)
2914 return dice_iterator(DiceRef(DRI
, this));
2916 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2917 unsigned Offset
= DicLC
.dataoff
+ DicLC
.datasize
;
2918 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2919 return dice_iterator(DiceRef(DRI
, this));
2922 ExportEntry::ExportEntry(Error
*E
, const MachOObjectFile
*O
,
2923 ArrayRef
<uint8_t> T
) : E(E
), O(O
), Trie(T
) {}
2925 void ExportEntry::moveToFirst() {
2926 ErrorAsOutParameter
ErrAsOutParam(E
);
2930 pushDownUntilBottom();
2933 void ExportEntry::moveToEnd() {
2938 bool ExportEntry::operator==(const ExportEntry
&Other
) const {
2939 // Common case, one at end, other iterating from begin.
2940 if (Done
|| Other
.Done
)
2941 return (Done
== Other
.Done
);
2942 // Not equal if different stack sizes.
2943 if (Stack
.size() != Other
.Stack
.size())
2945 // Not equal if different cumulative strings.
2946 if (!CumulativeString
.equals(Other
.CumulativeString
))
2948 // Equal if all nodes in both stacks match.
2949 for (unsigned i
=0; i
< Stack
.size(); ++i
) {
2950 if (Stack
[i
].Start
!= Other
.Stack
[i
].Start
)
2956 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr
, const char **error
) {
2958 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Trie
.end(), error
);
2960 if (Ptr
> Trie
.end())
2965 StringRef
ExportEntry::name() const {
2966 return CumulativeString
;
2969 uint64_t ExportEntry::flags() const {
2970 return Stack
.back().Flags
;
2973 uint64_t ExportEntry::address() const {
2974 return Stack
.back().Address
;
2977 uint64_t ExportEntry::other() const {
2978 return Stack
.back().Other
;
2981 StringRef
ExportEntry::otherName() const {
2982 const char* ImportName
= Stack
.back().ImportName
;
2984 return StringRef(ImportName
);
2988 uint32_t ExportEntry::nodeOffset() const {
2989 return Stack
.back().Start
- Trie
.begin();
2992 ExportEntry::NodeState::NodeState(const uint8_t *Ptr
)
2993 : Start(Ptr
), Current(Ptr
) {}
2995 void ExportEntry::pushNode(uint64_t offset
) {
2996 ErrorAsOutParameter
ErrAsOutParam(E
);
2997 const uint8_t *Ptr
= Trie
.begin() + offset
;
2998 NodeState
State(Ptr
);
3000 uint64_t ExportInfoSize
= readULEB128(State
.Current
, &error
);
3002 *E
= malformedError("export info size " + Twine(error
) +
3003 " in export trie data at node: 0x" +
3004 Twine::utohexstr(offset
));
3008 State
.IsExportNode
= (ExportInfoSize
!= 0);
3009 const uint8_t* Children
= State
.Current
+ ExportInfoSize
;
3010 if (Children
> Trie
.end()) {
3011 *E
= malformedError(
3012 "export info size: 0x" + Twine::utohexstr(ExportInfoSize
) +
3013 " in export trie data at node: 0x" + Twine::utohexstr(offset
) +
3014 " too big and extends past end of trie data");
3018 if (State
.IsExportNode
) {
3019 const uint8_t *ExportStart
= State
.Current
;
3020 State
.Flags
= readULEB128(State
.Current
, &error
);
3022 *E
= malformedError("flags " + Twine(error
) +
3023 " in export trie data at node: 0x" +
3024 Twine::utohexstr(offset
));
3028 uint64_t Kind
= State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK
;
3029 if (State
.Flags
!= 0 &&
3030 (Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR
&&
3031 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
&&
3032 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
)) {
3033 *E
= malformedError(
3034 "unsupported exported symbol kind: " + Twine((int)Kind
) +
3035 " in flags: 0x" + Twine::utohexstr(State
.Flags
) +
3036 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
3040 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_REEXPORT
) {
3042 State
.Other
= readULEB128(State
.Current
, &error
); // dylib ordinal
3044 *E
= malformedError("dylib ordinal of re-export " + Twine(error
) +
3045 " in export trie data at node: 0x" +
3046 Twine::utohexstr(offset
));
3051 // Only positive numbers represent library ordinals. Zero and negative
3052 // numbers have special meaning (see BindSpecialDylib).
3053 if ((int64_t)State
.Other
> 0 && State
.Other
> O
->getLibraryCount()) {
3054 *E
= malformedError(
3055 "bad library ordinal: " + Twine((int)State
.Other
) + " (max " +
3056 Twine((int)O
->getLibraryCount()) +
3057 ") in export trie data at node: 0x" + Twine::utohexstr(offset
));
3062 State
.ImportName
= reinterpret_cast<const char*>(State
.Current
);
3063 if (*State
.ImportName
== '\0') {
3066 const uint8_t *End
= State
.Current
+ 1;
3067 if (End
>= Trie
.end()) {
3068 *E
= malformedError("import name of re-export in export trie data at "
3070 Twine::utohexstr(offset
) +
3071 " starts past end of trie data");
3075 while(*End
!= '\0' && End
< Trie
.end())
3078 *E
= malformedError("import name of re-export in export trie data at "
3080 Twine::utohexstr(offset
) +
3081 " extends past end of trie data");
3085 State
.Current
= End
+ 1;
3088 State
.Address
= readULEB128(State
.Current
, &error
);
3090 *E
= malformedError("address " + Twine(error
) +
3091 " in export trie data at node: 0x" +
3092 Twine::utohexstr(offset
));
3096 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
) {
3097 State
.Other
= readULEB128(State
.Current
, &error
);
3099 *E
= malformedError("resolver of stub and resolver " + Twine(error
) +
3100 " in export trie data at node: 0x" +
3101 Twine::utohexstr(offset
));
3107 if(ExportStart
+ ExportInfoSize
!= State
.Current
) {
3108 *E
= malformedError(
3109 "inconsistent export info size: 0x" +
3110 Twine::utohexstr(ExportInfoSize
) + " where actual size was: 0x" +
3111 Twine::utohexstr(State
.Current
- ExportStart
) +
3112 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
3117 State
.ChildCount
= *Children
;
3118 if (State
.ChildCount
!= 0 && Children
+ 1 >= Trie
.end()) {
3119 *E
= malformedError("byte for count of childern in export trie data at "
3121 Twine::utohexstr(offset
) +
3122 " extends past end of trie data");
3126 State
.Current
= Children
+ 1;
3127 State
.NextChildIndex
= 0;
3128 State
.ParentStringLength
= CumulativeString
.size();
3129 Stack
.push_back(State
);
3132 void ExportEntry::pushDownUntilBottom() {
3133 ErrorAsOutParameter
ErrAsOutParam(E
);
3135 while (Stack
.back().NextChildIndex
< Stack
.back().ChildCount
) {
3136 NodeState
&Top
= Stack
.back();
3137 CumulativeString
.resize(Top
.ParentStringLength
);
3138 for (;*Top
.Current
!= 0 && Top
.Current
< Trie
.end(); Top
.Current
++) {
3139 char C
= *Top
.Current
;
3140 CumulativeString
.push_back(C
);
3142 if (Top
.Current
>= Trie
.end()) {
3143 *E
= malformedError("edge sub-string in export trie data at node: 0x" +
3144 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
3145 " for child #" + Twine((int)Top
.NextChildIndex
) +
3146 " extends past end of trie data");
3151 uint64_t childNodeIndex
= readULEB128(Top
.Current
, &error
);
3153 *E
= malformedError("child node offset " + Twine(error
) +
3154 " in export trie data at node: 0x" +
3155 Twine::utohexstr(Top
.Start
- Trie
.begin()));
3159 for (const NodeState
&node
: nodes()) {
3160 if (node
.Start
== Trie
.begin() + childNodeIndex
){
3161 *E
= malformedError("loop in childern in export trie data at node: 0x" +
3162 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
3163 " back to node: 0x" +
3164 Twine::utohexstr(childNodeIndex
));
3169 Top
.NextChildIndex
+= 1;
3170 pushNode(childNodeIndex
);
3174 if (!Stack
.back().IsExportNode
) {
3175 *E
= malformedError("node is not an export node in export trie data at "
3177 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3183 // We have a trie data structure and need a way to walk it that is compatible
3184 // with the C++ iterator model. The solution is a non-recursive depth first
3185 // traversal where the iterator contains a stack of parent nodes along with a
3186 // string that is the accumulation of all edge strings along the parent chain
3189 // There is one "export" node for each exported symbol. But because some
3190 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
3191 // node may have child nodes too.
3193 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
3194 // child until hitting a node with no children (which is an export node or
3195 // else the trie is malformed). On the way down, each node is pushed on the
3196 // stack ivar. If there is no more ways down, it pops up one and tries to go
3197 // down a sibling path until a childless node is reached.
3198 void ExportEntry::moveNext() {
3199 assert(!Stack
.empty() && "ExportEntry::moveNext() with empty node stack");
3200 if (!Stack
.back().IsExportNode
) {
3201 *E
= malformedError("node is not an export node in export trie data at "
3203 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3209 while (!Stack
.empty()) {
3210 NodeState
&Top
= Stack
.back();
3211 if (Top
.NextChildIndex
< Top
.ChildCount
) {
3212 pushDownUntilBottom();
3213 // Now at the next export node.
3216 if (Top
.IsExportNode
) {
3217 // This node has no children but is itself an export node.
3218 CumulativeString
.resize(Top
.ParentStringLength
);
3227 iterator_range
<export_iterator
>
3228 MachOObjectFile::exports(Error
&E
, ArrayRef
<uint8_t> Trie
,
3229 const MachOObjectFile
*O
) {
3230 ExportEntry
Start(&E
, O
, Trie
);
3234 Start
.moveToFirst();
3236 ExportEntry
Finish(&E
, O
, Trie
);
3239 return make_range(export_iterator(Start
), export_iterator(Finish
));
3242 iterator_range
<export_iterator
> MachOObjectFile::exports(Error
&Err
) const {
3243 ArrayRef
<uint8_t> Trie
;
3244 if (DyldInfoLoadCmd
)
3245 Trie
= getDyldInfoExportsTrie();
3246 else if (DyldExportsTrieLoadCmd
)
3247 Trie
= getDyldExportsTrie();
3249 return exports(Err
, Trie
, this);
3252 MachOAbstractFixupEntry::MachOAbstractFixupEntry(Error
*E
,
3253 const MachOObjectFile
*O
)
3255 // Cache the vmaddress of __TEXT
3256 for (const auto &Command
: O
->load_commands()) {
3257 if (Command
.C
.cmd
== MachO::LC_SEGMENT
) {
3258 MachO::segment_command SLC
= O
->getSegmentLoadCommand(Command
);
3259 if (StringRef(SLC
.segname
) == StringRef("__TEXT")) {
3260 TextAddress
= SLC
.vmaddr
;
3263 } else if (Command
.C
.cmd
== MachO::LC_SEGMENT_64
) {
3264 MachO::segment_command_64 SLC_64
= O
->getSegment64LoadCommand(Command
);
3265 if (StringRef(SLC_64
.segname
) == StringRef("__TEXT")) {
3266 TextAddress
= SLC_64
.vmaddr
;
3273 int32_t MachOAbstractFixupEntry::segmentIndex() const { return SegmentIndex
; }
3275 uint64_t MachOAbstractFixupEntry::segmentOffset() const {
3276 return SegmentOffset
;
3279 uint64_t MachOAbstractFixupEntry::segmentAddress() const {
3280 return O
->BindRebaseAddress(SegmentIndex
, 0);
3283 StringRef
MachOAbstractFixupEntry::segmentName() const {
3284 return O
->BindRebaseSegmentName(SegmentIndex
);
3287 StringRef
MachOAbstractFixupEntry::sectionName() const {
3288 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3291 uint64_t MachOAbstractFixupEntry::address() const {
3292 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3295 StringRef
MachOAbstractFixupEntry::symbolName() const { return SymbolName
; }
3297 int64_t MachOAbstractFixupEntry::addend() const { return Addend
; }
3299 uint32_t MachOAbstractFixupEntry::flags() const { return Flags
; }
3301 int MachOAbstractFixupEntry::ordinal() const { return Ordinal
; }
3303 StringRef
MachOAbstractFixupEntry::typeName() const { return "unknown"; }
3305 void MachOAbstractFixupEntry::moveToFirst() {
3314 void MachOAbstractFixupEntry::moveToEnd() { Done
= true; }
3316 void MachOAbstractFixupEntry::moveNext() {}
3318 MachOChainedFixupEntry::MachOChainedFixupEntry(Error
*E
,
3319 const MachOObjectFile
*O
,
3321 : MachOAbstractFixupEntry(E
, O
) {
3322 ErrorAsOutParameter
e(E
);
3326 if (auto FixupTargetsOrErr
= O
->getDyldChainedFixupTargets()) {
3327 FixupTargets
= *FixupTargetsOrErr
;
3329 *E
= FixupTargetsOrErr
.takeError();
3333 if (auto SegmentsOrErr
= O
->getChainedFixupsSegments()) {
3334 Segments
= std::move(SegmentsOrErr
->second
);
3336 *E
= SegmentsOrErr
.takeError();
3341 void MachOChainedFixupEntry::findNextPageWithFixups() {
3342 auto FindInSegment
= [this]() {
3343 const ChainedFixupsSegment
&SegInfo
= Segments
[InfoSegIndex
];
3344 while (PageIndex
< SegInfo
.PageStarts
.size() &&
3345 SegInfo
.PageStarts
[PageIndex
] == MachO::DYLD_CHAINED_PTR_START_NONE
)
3347 return PageIndex
< SegInfo
.PageStarts
.size();
3350 while (InfoSegIndex
< Segments
.size()) {
3351 if (FindInSegment()) {
3352 PageOffset
= Segments
[InfoSegIndex
].PageStarts
[PageIndex
];
3353 SegmentData
= O
->getSegmentContents(Segments
[InfoSegIndex
].SegIdx
);
3362 void MachOChainedFixupEntry::moveToFirst() {
3363 MachOAbstractFixupEntry::moveToFirst();
3364 if (Segments
.empty()) {
3372 findNextPageWithFixups();
3376 void MachOChainedFixupEntry::moveToEnd() {
3377 MachOAbstractFixupEntry::moveToEnd();
3380 void MachOChainedFixupEntry::moveNext() {
3381 ErrorAsOutParameter
ErrAsOutParam(E
);
3383 if (InfoSegIndex
== Segments
.size()) {
3388 const ChainedFixupsSegment
&SegInfo
= Segments
[InfoSegIndex
];
3389 SegmentIndex
= SegInfo
.SegIdx
;
3390 SegmentOffset
= SegInfo
.Header
.page_size
* PageIndex
+ PageOffset
;
3392 // FIXME: Handle other pointer formats.
3393 uint16_t PointerFormat
= SegInfo
.Header
.pointer_format
;
3394 if (PointerFormat
!= MachO::DYLD_CHAINED_PTR_64
&&
3395 PointerFormat
!= MachO::DYLD_CHAINED_PTR_64_OFFSET
) {
3396 *E
= createError("segment " + Twine(SegmentIndex
) +
3397 " has unsupported chained fixup pointer_format " +
3398 Twine(PointerFormat
));
3409 if (SegmentOffset
+ sizeof(RawValue
) > SegmentData
.size()) {
3410 *E
= malformedError("fixup in segment " + Twine(SegmentIndex
) +
3411 " at offset " + Twine(SegmentOffset
) +
3412 " extends past segment's end");
3417 static_assert(sizeof(RawValue
) == sizeof(MachO::dyld_chained_import_addend
));
3418 memcpy(&RawValue
, SegmentData
.data() + SegmentOffset
, sizeof(RawValue
));
3419 if (O
->isLittleEndian() != sys::IsLittleEndianHost
)
3420 sys::swapByteOrder(RawValue
);
3422 // The bit extraction below assumes little-endian fixup entries.
3423 assert(O
->isLittleEndian() && "big-endian object should have been rejected "
3424 "by getDyldChainedFixupTargets()");
3425 auto Field
= [this](uint8_t Right
, uint8_t Count
) {
3426 return (RawValue
>> Right
) & ((1ULL << Count
) - 1);
3429 // The `bind` field (most significant bit) of the encoded fixup determines
3430 // whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase.
3431 bool IsBind
= Field(63, 1);
3432 Kind
= IsBind
? FixupKind::Bind
: FixupKind::Rebase
;
3433 uint32_t Next
= Field(51, 12);
3435 uint32_t ImportOrdinal
= Field(0, 24);
3436 uint8_t InlineAddend
= Field(24, 8);
3438 if (ImportOrdinal
>= FixupTargets
.size()) {
3439 *E
= malformedError("fixup in segment " + Twine(SegmentIndex
) +
3440 " at offset " + Twine(SegmentOffset
) +
3441 " has out-of range import ordinal " +
3442 Twine(ImportOrdinal
));
3447 ChainedFixupTarget
&Target
= FixupTargets
[ImportOrdinal
];
3448 Ordinal
= Target
.libOrdinal();
3449 Addend
= InlineAddend
? InlineAddend
: Target
.addend();
3450 Flags
= Target
.weakImport() ? MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT
: 0;
3451 SymbolName
= Target
.symbolName();
3453 uint64_t Target
= Field(0, 36);
3454 uint64_t High8
= Field(36, 8);
3456 PointerValue
= Target
| (High8
<< 56);
3457 if (PointerFormat
== MachO::DYLD_CHAINED_PTR_64_OFFSET
)
3458 PointerValue
+= textAddress();
3461 // The stride is 4 bytes for DYLD_CHAINED_PTR_64(_OFFSET).
3463 PageOffset
+= 4 * Next
;
3466 findNextPageWithFixups();
3470 bool MachOChainedFixupEntry::operator==(
3471 const MachOChainedFixupEntry
&Other
) const {
3472 if (Done
&& Other
.Done
)
3474 if (Done
!= Other
.Done
)
3476 return InfoSegIndex
== Other
.InfoSegIndex
&& PageIndex
== Other
.PageIndex
&&
3477 PageOffset
== Other
.PageOffset
;
3480 MachORebaseEntry::MachORebaseEntry(Error
*E
, const MachOObjectFile
*O
,
3481 ArrayRef
<uint8_t> Bytes
, bool is64Bit
)
3482 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3483 PointerSize(is64Bit
? 8 : 4) {}
3485 void MachORebaseEntry::moveToFirst() {
3486 Ptr
= Opcodes
.begin();
3490 void MachORebaseEntry::moveToEnd() {
3491 Ptr
= Opcodes
.end();
3492 RemainingLoopCount
= 0;
3496 void MachORebaseEntry::moveNext() {
3497 ErrorAsOutParameter
ErrAsOutParam(E
);
3498 // If in the middle of some loop, move to next rebasing in loop.
3499 SegmentOffset
+= AdvanceAmount
;
3500 if (RemainingLoopCount
) {
3501 --RemainingLoopCount
;
3504 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3505 // pointer size. Therefore it is possible to reach the end without ever having
3506 // seen REBASE_OPCODE_DONE.
3507 if (Ptr
== Opcodes
.end()) {
3513 // Parse next opcode and set up next loop.
3514 const uint8_t *OpcodeStart
= Ptr
;
3515 uint8_t Byte
= *Ptr
++;
3516 uint8_t ImmValue
= Byte
& MachO::REBASE_IMMEDIATE_MASK
;
3517 uint8_t Opcode
= Byte
& MachO::REBASE_OPCODE_MASK
;
3518 uint32_t Count
, Skip
;
3519 const char *error
= nullptr;
3521 case MachO::REBASE_OPCODE_DONE
:
3525 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
3527 case MachO::REBASE_OPCODE_SET_TYPE_IMM
:
3528 RebaseType
= ImmValue
;
3529 if (RebaseType
> MachO::REBASE_TYPE_TEXT_PCREL32
) {
3530 *E
= malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3531 Twine((int)RebaseType
) + " for opcode at: 0x" +
3532 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3538 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3539 << "RebaseType=" << (int) RebaseType
<< "\n");
3541 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3542 SegmentIndex
= ImmValue
;
3543 SegmentOffset
= readULEB128(&error
);
3545 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3546 Twine(error
) + " for opcode at: 0x" +
3547 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3551 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3554 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3555 Twine(error
) + " for opcode at: 0x" +
3556 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3562 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3563 << "SegmentIndex=" << SegmentIndex
<< ", "
3564 << format("SegmentOffset=0x%06X", SegmentOffset
)
3567 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB
:
3568 SegmentOffset
+= readULEB128(&error
);
3570 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3571 " for opcode at: 0x" +
3572 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3576 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3579 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3580 " for opcode at: 0x" +
3581 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3585 DEBUG_WITH_TYPE("mach-o-rebase",
3586 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3587 << format("SegmentOffset=0x%06X",
3588 SegmentOffset
) << "\n");
3590 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED
:
3591 SegmentOffset
+= ImmValue
* PointerSize
;
3592 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3595 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3596 Twine(error
) + " for opcode at: 0x" +
3597 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3601 DEBUG_WITH_TYPE("mach-o-rebase",
3602 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3603 << format("SegmentOffset=0x%06X",
3604 SegmentOffset
) << "\n");
3606 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES
:
3607 AdvanceAmount
= PointerSize
;
3611 RemainingLoopCount
= ImmValue
- 1;
3613 RemainingLoopCount
= 0;
3614 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3615 PointerSize
, Count
, Skip
);
3617 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3618 Twine(error
) + " for opcode at: 0x" +
3619 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3625 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3626 << format("SegmentOffset=0x%06X", SegmentOffset
)
3627 << ", AdvanceAmount=" << AdvanceAmount
3628 << ", RemainingLoopCount=" << RemainingLoopCount
3631 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES
:
3632 AdvanceAmount
= PointerSize
;
3634 Count
= readULEB128(&error
);
3636 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3637 Twine(error
) + " for opcode at: 0x" +
3638 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3643 RemainingLoopCount
= Count
- 1;
3645 RemainingLoopCount
= 0;
3646 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3647 PointerSize
, Count
, Skip
);
3649 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3650 Twine(error
) + " for opcode at: 0x" +
3651 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3657 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3658 << format("SegmentOffset=0x%06X", SegmentOffset
)
3659 << ", AdvanceAmount=" << AdvanceAmount
3660 << ", RemainingLoopCount=" << RemainingLoopCount
3663 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB
:
3664 Skip
= readULEB128(&error
);
3666 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3667 Twine(error
) + " for opcode at: 0x" +
3668 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3672 AdvanceAmount
= Skip
+ PointerSize
;
3674 RemainingLoopCount
= 0;
3675 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3676 PointerSize
, Count
, Skip
);
3678 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3679 Twine(error
) + " for opcode at: 0x" +
3680 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3686 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3687 << format("SegmentOffset=0x%06X", SegmentOffset
)
3688 << ", AdvanceAmount=" << AdvanceAmount
3689 << ", RemainingLoopCount=" << RemainingLoopCount
3692 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB
:
3693 Count
= readULEB128(&error
);
3695 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3697 Twine(error
) + " for opcode at: 0x" +
3698 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3703 RemainingLoopCount
= Count
- 1;
3705 RemainingLoopCount
= 0;
3706 Skip
= readULEB128(&error
);
3708 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3710 Twine(error
) + " for opcode at: 0x" +
3711 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3715 AdvanceAmount
= Skip
+ PointerSize
;
3717 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3718 PointerSize
, Count
, Skip
);
3720 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3722 Twine(error
) + " for opcode at: 0x" +
3723 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3729 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3730 << format("SegmentOffset=0x%06X", SegmentOffset
)
3731 << ", AdvanceAmount=" << AdvanceAmount
3732 << ", RemainingLoopCount=" << RemainingLoopCount
3736 *E
= malformedError("bad rebase info (bad opcode value 0x" +
3737 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3738 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3745 uint64_t MachORebaseEntry::readULEB128(const char **error
) {
3747 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3749 if (Ptr
> Opcodes
.end())
3750 Ptr
= Opcodes
.end();
3754 int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex
; }
3756 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset
; }
3758 StringRef
MachORebaseEntry::typeName() const {
3759 switch (RebaseType
) {
3760 case MachO::REBASE_TYPE_POINTER
:
3762 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32
:
3763 return "text abs32";
3764 case MachO::REBASE_TYPE_TEXT_PCREL32
:
3765 return "text rel32";
3770 // For use with the SegIndex of a checked Mach-O Rebase entry
3771 // to get the segment name.
3772 StringRef
MachORebaseEntry::segmentName() const {
3773 return O
->BindRebaseSegmentName(SegmentIndex
);
3776 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3777 // to get the section name.
3778 StringRef
MachORebaseEntry::sectionName() const {
3779 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3782 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3783 // to get the address.
3784 uint64_t MachORebaseEntry::address() const {
3785 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3788 bool MachORebaseEntry::operator==(const MachORebaseEntry
&Other
) const {
3789 #ifdef EXPENSIVE_CHECKS
3790 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
3792 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
3794 return (Ptr
== Other
.Ptr
) &&
3795 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
3796 (Done
== Other
.Done
);
3799 iterator_range
<rebase_iterator
>
3800 MachOObjectFile::rebaseTable(Error
&Err
, MachOObjectFile
*O
,
3801 ArrayRef
<uint8_t> Opcodes
, bool is64
) {
3802 if (O
->BindRebaseSectionTable
== nullptr)
3803 O
->BindRebaseSectionTable
= std::make_unique
<BindRebaseSegInfo
>(O
);
3804 MachORebaseEntry
Start(&Err
, O
, Opcodes
, is64
);
3805 Start
.moveToFirst();
3807 MachORebaseEntry
Finish(&Err
, O
, Opcodes
, is64
);
3810 return make_range(rebase_iterator(Start
), rebase_iterator(Finish
));
3813 iterator_range
<rebase_iterator
> MachOObjectFile::rebaseTable(Error
&Err
) {
3814 return rebaseTable(Err
, this, getDyldInfoRebaseOpcodes(), is64Bit());
3817 MachOBindEntry::MachOBindEntry(Error
*E
, const MachOObjectFile
*O
,
3818 ArrayRef
<uint8_t> Bytes
, bool is64Bit
, Kind BK
)
3819 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3820 PointerSize(is64Bit
? 8 : 4), TableKind(BK
) {}
3822 void MachOBindEntry::moveToFirst() {
3823 Ptr
= Opcodes
.begin();
3827 void MachOBindEntry::moveToEnd() {
3828 Ptr
= Opcodes
.end();
3829 RemainingLoopCount
= 0;
3833 void MachOBindEntry::moveNext() {
3834 ErrorAsOutParameter
ErrAsOutParam(E
);
3835 // If in the middle of some loop, move to next binding in loop.
3836 SegmentOffset
+= AdvanceAmount
;
3837 if (RemainingLoopCount
) {
3838 --RemainingLoopCount
;
3841 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3842 // pointer size. Therefore it is possible to reach the end without ever having
3843 // seen BIND_OPCODE_DONE.
3844 if (Ptr
== Opcodes
.end()) {
3850 // Parse next opcode and set up next loop.
3851 const uint8_t *OpcodeStart
= Ptr
;
3852 uint8_t Byte
= *Ptr
++;
3853 uint8_t ImmValue
= Byte
& MachO::BIND_IMMEDIATE_MASK
;
3854 uint8_t Opcode
= Byte
& MachO::BIND_OPCODE_MASK
;
3855 int8_t SignExtended
;
3856 const uint8_t *SymStart
;
3857 uint32_t Count
, Skip
;
3858 const char *error
= nullptr;
3860 case MachO::BIND_OPCODE_DONE
:
3861 if (TableKind
== Kind::Lazy
) {
3862 // Lazying bindings have a DONE opcode between entries. Need to ignore
3863 // it to advance to next entry. But need not if this is last entry.
3864 bool NotLastEntry
= false;
3865 for (const uint8_t *P
= Ptr
; P
< Opcodes
.end(); ++P
) {
3867 NotLastEntry
= true;
3875 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3877 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
:
3878 if (TableKind
== Kind::Weak
) {
3879 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3880 "weak bind table for opcode at: 0x" +
3881 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3886 LibraryOrdinalSet
= true;
3887 if (ImmValue
> O
->getLibraryCount()) {
3888 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3889 "library ordinal: " +
3890 Twine((int)ImmValue
) + " (max " +
3891 Twine((int)O
->getLibraryCount()) +
3892 ") for opcode at: 0x" +
3893 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3899 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3900 << "Ordinal=" << Ordinal
<< "\n");
3902 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
:
3903 if (TableKind
== Kind::Weak
) {
3904 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3905 "weak bind table for opcode at: 0x" +
3906 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3910 Ordinal
= readULEB128(&error
);
3911 LibraryOrdinalSet
= true;
3913 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3914 Twine(error
) + " for opcode at: 0x" +
3915 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3919 if (Ordinal
> (int)O
->getLibraryCount()) {
3920 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3921 "library ordinal: " +
3922 Twine((int)Ordinal
) + " (max " +
3923 Twine((int)O
->getLibraryCount()) +
3924 ") for opcode at: 0x" +
3925 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3931 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3932 << "Ordinal=" << Ordinal
<< "\n");
3934 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
:
3935 if (TableKind
== Kind::Weak
) {
3936 *E
= malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3937 "weak bind table for opcode at: 0x" +
3938 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3943 SignExtended
= MachO::BIND_OPCODE_MASK
| ImmValue
;
3944 Ordinal
= SignExtended
;
3945 if (Ordinal
< MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP
) {
3946 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3947 "special ordinal: " +
3948 Twine((int)Ordinal
) + " for opcode at: 0x" +
3949 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3955 LibraryOrdinalSet
= true;
3958 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3959 << "Ordinal=" << Ordinal
<< "\n");
3961 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
:
3964 while (*Ptr
&& (Ptr
< Opcodes
.end())) {
3967 if (Ptr
== Opcodes
.end()) {
3968 *E
= malformedError(
3969 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3970 "symbol name extends past opcodes for opcode at: 0x" +
3971 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3975 SymbolName
= StringRef(reinterpret_cast<const char*>(SymStart
),
3980 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3981 << "SymbolName=" << SymbolName
<< "\n");
3982 if (TableKind
== Kind::Weak
) {
3983 if (ImmValue
& MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
)
3987 case MachO::BIND_OPCODE_SET_TYPE_IMM
:
3988 BindType
= ImmValue
;
3989 if (ImmValue
> MachO::BIND_TYPE_TEXT_PCREL32
) {
3990 *E
= malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3991 Twine((int)ImmValue
) + " for opcode at: 0x" +
3992 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3998 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3999 << "BindType=" << (int)BindType
<< "\n");
4001 case MachO::BIND_OPCODE_SET_ADDEND_SLEB
:
4002 Addend
= readSLEB128(&error
);
4004 *E
= malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error
) +
4005 " for opcode at: 0x" +
4006 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4012 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
4013 << "Addend=" << Addend
<< "\n");
4015 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
4016 SegmentIndex
= ImmValue
;
4017 SegmentOffset
= readULEB128(&error
);
4019 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
4020 Twine(error
) + " for opcode at: 0x" +
4021 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4025 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
4028 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
4029 Twine(error
) + " for opcode at: 0x" +
4030 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4036 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
4037 << "SegmentIndex=" << SegmentIndex
<< ", "
4038 << format("SegmentOffset=0x%06X", SegmentOffset
)
4041 case MachO::BIND_OPCODE_ADD_ADDR_ULEB
:
4042 SegmentOffset
+= readULEB128(&error
);
4044 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
4045 " for opcode at: 0x" +
4046 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4050 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
4053 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
4054 " for opcode at: 0x" +
4055 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4059 DEBUG_WITH_TYPE("mach-o-bind",
4060 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
4061 << format("SegmentOffset=0x%06X",
4062 SegmentOffset
) << "\n");
4064 case MachO::BIND_OPCODE_DO_BIND
:
4065 AdvanceAmount
= PointerSize
;
4066 RemainingLoopCount
= 0;
4067 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
4070 *E
= malformedError("for BIND_OPCODE_DO_BIND " + Twine(error
) +
4071 " for opcode at: 0x" +
4072 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4076 if (SymbolName
== StringRef()) {
4077 *E
= malformedError(
4078 "for BIND_OPCODE_DO_BIND missing preceding "
4079 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
4080 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4084 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
4086 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
4087 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
4088 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4092 DEBUG_WITH_TYPE("mach-o-bind",
4093 dbgs() << "BIND_OPCODE_DO_BIND: "
4094 << format("SegmentOffset=0x%06X",
4095 SegmentOffset
) << "\n");
4097 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
:
4098 if (TableKind
== Kind::Lazy
) {
4099 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
4100 "lazy bind table for opcode at: 0x" +
4101 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4105 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
4108 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
4109 Twine(error
) + " for opcode at: 0x" +
4110 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4114 if (SymbolName
== StringRef()) {
4115 *E
= malformedError(
4116 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
4117 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
4119 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4123 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
4124 *E
= malformedError(
4125 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
4126 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
4127 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4131 AdvanceAmount
= readULEB128(&error
) + PointerSize
;
4133 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
4134 Twine(error
) + " for opcode at: 0x" +
4135 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4139 // Note, this is not really an error until the next bind but make no sense
4140 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
4142 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
+
4143 AdvanceAmount
, PointerSize
);
4145 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
4147 Twine(error
) + " for opcode at: 0x" +
4148 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4152 RemainingLoopCount
= 0;
4155 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
4156 << format("SegmentOffset=0x%06X", SegmentOffset
)
4157 << ", AdvanceAmount=" << AdvanceAmount
4158 << ", RemainingLoopCount=" << RemainingLoopCount
4161 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
:
4162 if (TableKind
== Kind::Lazy
) {
4163 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
4164 "allowed in lazy bind table for opcode at: 0x" +
4165 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4169 if (SymbolName
== StringRef()) {
4170 *E
= malformedError(
4171 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
4172 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
4174 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4178 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
4179 *E
= malformedError(
4180 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
4181 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
4183 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4187 AdvanceAmount
= ImmValue
* PointerSize
+ PointerSize
;
4188 RemainingLoopCount
= 0;
4189 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
+
4190 AdvanceAmount
, PointerSize
);
4192 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
4193 Twine(error
) + " for opcode at: 0x" +
4194 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4198 DEBUG_WITH_TYPE("mach-o-bind",
4200 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
4201 << format("SegmentOffset=0x%06X", SegmentOffset
) << "\n");
4203 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
:
4204 if (TableKind
== Kind::Lazy
) {
4205 *E
= malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
4206 "allowed in lazy bind table for opcode at: 0x" +
4207 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4211 Count
= readULEB128(&error
);
4213 RemainingLoopCount
= Count
- 1;
4215 RemainingLoopCount
= 0;
4217 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4219 Twine(error
) + " for opcode at: 0x" +
4220 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4224 Skip
= readULEB128(&error
);
4225 AdvanceAmount
= Skip
+ PointerSize
;
4227 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4229 Twine(error
) + " for opcode at: 0x" +
4230 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4234 if (SymbolName
== StringRef()) {
4235 *E
= malformedError(
4236 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4237 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
4239 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4243 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
4244 *E
= malformedError(
4245 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4246 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
4248 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4252 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
4253 PointerSize
, Count
, Skip
);
4256 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
4257 Twine(error
) + " for opcode at: 0x" +
4258 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4264 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
4265 << format("SegmentOffset=0x%06X", SegmentOffset
)
4266 << ", AdvanceAmount=" << AdvanceAmount
4267 << ", RemainingLoopCount=" << RemainingLoopCount
4271 *E
= malformedError("bad bind info (bad opcode value 0x" +
4272 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
4273 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4280 uint64_t MachOBindEntry::readULEB128(const char **error
) {
4282 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
4284 if (Ptr
> Opcodes
.end())
4285 Ptr
= Opcodes
.end();
4289 int64_t MachOBindEntry::readSLEB128(const char **error
) {
4291 int64_t Result
= decodeSLEB128(Ptr
, &Count
, Opcodes
.end(), error
);
4293 if (Ptr
> Opcodes
.end())
4294 Ptr
= Opcodes
.end();
4298 int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex
; }
4300 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset
; }
4302 StringRef
MachOBindEntry::typeName() const {
4304 case MachO::BIND_TYPE_POINTER
:
4306 case MachO::BIND_TYPE_TEXT_ABSOLUTE32
:
4307 return "text abs32";
4308 case MachO::BIND_TYPE_TEXT_PCREL32
:
4309 return "text rel32";
4314 StringRef
MachOBindEntry::symbolName() const { return SymbolName
; }
4316 int64_t MachOBindEntry::addend() const { return Addend
; }
4318 uint32_t MachOBindEntry::flags() const { return Flags
; }
4320 int MachOBindEntry::ordinal() const { return Ordinal
; }
4322 // For use with the SegIndex of a checked Mach-O Bind entry
4323 // to get the segment name.
4324 StringRef
MachOBindEntry::segmentName() const {
4325 return O
->BindRebaseSegmentName(SegmentIndex
);
4328 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
4329 // to get the section name.
4330 StringRef
MachOBindEntry::sectionName() const {
4331 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
4334 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
4335 // to get the address.
4336 uint64_t MachOBindEntry::address() const {
4337 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
4340 bool MachOBindEntry::operator==(const MachOBindEntry
&Other
) const {
4341 #ifdef EXPENSIVE_CHECKS
4342 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
4344 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
4346 return (Ptr
== Other
.Ptr
) &&
4347 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
4348 (Done
== Other
.Done
);
4351 // Build table of sections so SegIndex/SegOffset pairs can be translated.
4352 BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile
*Obj
) {
4353 uint32_t CurSegIndex
= Obj
->hasPageZeroSegment() ? 1 : 0;
4354 StringRef CurSegName
;
4355 uint64_t CurSegAddress
;
4356 for (const SectionRef
&Section
: Obj
->sections()) {
4358 Expected
<StringRef
> NameOrErr
= Section
.getName();
4360 consumeError(NameOrErr
.takeError());
4362 Info
.SectionName
= *NameOrErr
;
4363 Info
.Address
= Section
.getAddress();
4364 Info
.Size
= Section
.getSize();
4366 Obj
->getSectionFinalSegmentName(Section
.getRawDataRefImpl());
4367 if (!Info
.SegmentName
.equals(CurSegName
)) {
4369 CurSegName
= Info
.SegmentName
;
4370 CurSegAddress
= Info
.Address
;
4372 Info
.SegmentIndex
= CurSegIndex
- 1;
4373 Info
.OffsetInSegment
= Info
.Address
- CurSegAddress
;
4374 Info
.SegmentStartAddress
= CurSegAddress
;
4375 Sections
.push_back(Info
);
4377 MaxSegIndex
= CurSegIndex
;
4380 // For use with a SegIndex, SegOffset, and PointerSize triple in
4381 // MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
4383 // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
4384 // that fully contains a pointer at that location. Multiple fixups in a bind
4385 // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
4386 // be tested via the Count and Skip parameters.
4387 const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex
,
4389 uint8_t PointerSize
,
4393 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4394 if (SegIndex
>= MaxSegIndex
)
4395 return "bad segIndex (too large)";
4396 for (uint32_t i
= 0; i
< Count
; ++i
) {
4397 uint32_t Start
= SegOffset
+ i
* (PointerSize
+ Skip
);
4398 uint32_t End
= Start
+ PointerSize
;
4400 for (const SectionInfo
&SI
: Sections
) {
4401 if (SI
.SegmentIndex
!= SegIndex
)
4403 if ((SI
.OffsetInSegment
<=Start
) && (Start
<(SI
.OffsetInSegment
+SI
.Size
))) {
4404 if (End
<= SI
.OffsetInSegment
+ SI
.Size
) {
4409 return "bad offset, extends beyond section boundary";
4413 return "bad offset, not in section";
4418 // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4419 // to get the segment name.
4420 StringRef
BindRebaseSegInfo::segmentName(int32_t SegIndex
) {
4421 for (const SectionInfo
&SI
: Sections
) {
4422 if (SI
.SegmentIndex
== SegIndex
)
4423 return SI
.SegmentName
;
4425 llvm_unreachable("invalid SegIndex");
4428 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4429 // to get the SectionInfo.
4430 const BindRebaseSegInfo::SectionInfo
&BindRebaseSegInfo::findSection(
4431 int32_t SegIndex
, uint64_t SegOffset
) {
4432 for (const SectionInfo
&SI
: Sections
) {
4433 if (SI
.SegmentIndex
!= SegIndex
)
4435 if (SI
.OffsetInSegment
> SegOffset
)
4437 if (SegOffset
>= (SI
.OffsetInSegment
+ SI
.Size
))
4441 llvm_unreachable("SegIndex and SegOffset not in any section");
4444 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4445 // entry to get the section name.
4446 StringRef
BindRebaseSegInfo::sectionName(int32_t SegIndex
,
4447 uint64_t SegOffset
) {
4448 return findSection(SegIndex
, SegOffset
).SectionName
;
4451 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4452 // entry to get the address.
4453 uint64_t BindRebaseSegInfo::address(uint32_t SegIndex
, uint64_t OffsetInSeg
) {
4454 const SectionInfo
&SI
= findSection(SegIndex
, OffsetInSeg
);
4455 return SI
.SegmentStartAddress
+ OffsetInSeg
;
4458 iterator_range
<bind_iterator
>
4459 MachOObjectFile::bindTable(Error
&Err
, MachOObjectFile
*O
,
4460 ArrayRef
<uint8_t> Opcodes
, bool is64
,
4461 MachOBindEntry::Kind BKind
) {
4462 if (O
->BindRebaseSectionTable
== nullptr)
4463 O
->BindRebaseSectionTable
= std::make_unique
<BindRebaseSegInfo
>(O
);
4464 MachOBindEntry
Start(&Err
, O
, Opcodes
, is64
, BKind
);
4465 Start
.moveToFirst();
4467 MachOBindEntry
Finish(&Err
, O
, Opcodes
, is64
, BKind
);
4470 return make_range(bind_iterator(Start
), bind_iterator(Finish
));
4473 iterator_range
<bind_iterator
> MachOObjectFile::bindTable(Error
&Err
) {
4474 return bindTable(Err
, this, getDyldInfoBindOpcodes(), is64Bit(),
4475 MachOBindEntry::Kind::Regular
);
4478 iterator_range
<bind_iterator
> MachOObjectFile::lazyBindTable(Error
&Err
) {
4479 return bindTable(Err
, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4480 MachOBindEntry::Kind::Lazy
);
4483 iterator_range
<bind_iterator
> MachOObjectFile::weakBindTable(Error
&Err
) {
4484 return bindTable(Err
, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
4485 MachOBindEntry::Kind::Weak
);
4488 iterator_range
<fixup_iterator
> MachOObjectFile::fixupTable(Error
&Err
) {
4489 if (BindRebaseSectionTable
== nullptr)
4490 BindRebaseSectionTable
= std::make_unique
<BindRebaseSegInfo
>(this);
4492 MachOChainedFixupEntry
Start(&Err
, this, true);
4493 Start
.moveToFirst();
4495 MachOChainedFixupEntry
Finish(&Err
, this, false);
4498 return make_range(fixup_iterator(Start
), fixup_iterator(Finish
));
4501 MachOObjectFile::load_command_iterator
4502 MachOObjectFile::begin_load_commands() const {
4503 return LoadCommands
.begin();
4506 MachOObjectFile::load_command_iterator
4507 MachOObjectFile::end_load_commands() const {
4508 return LoadCommands
.end();
4511 iterator_range
<MachOObjectFile::load_command_iterator
>
4512 MachOObjectFile::load_commands() const {
4513 return make_range(begin_load_commands(), end_load_commands());
4517 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec
) const {
4518 ArrayRef
<char> Raw
= getSectionRawFinalSegmentName(Sec
);
4519 return parseSegmentOrSectionName(Raw
.data());
4523 MachOObjectFile::getSectionRawName(DataRefImpl Sec
) const {
4524 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4525 const section_base
*Base
=
4526 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4527 return ArrayRef(Base
->sectname
);
4531 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec
) const {
4532 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4533 const section_base
*Base
=
4534 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4535 return ArrayRef(Base
->segname
);
4539 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info
&RE
)
4541 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64
)
4543 return getPlainRelocationAddress(RE
) & MachO::R_SCATTERED
;
4546 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4547 const MachO::any_relocation_info
&RE
) const {
4548 if (isLittleEndian())
4549 return RE
.r_word1
& 0xffffff;
4550 return RE
.r_word1
>> 8;
4553 bool MachOObjectFile::getPlainRelocationExternal(
4554 const MachO::any_relocation_info
&RE
) const {
4555 if (isLittleEndian())
4556 return (RE
.r_word1
>> 27) & 1;
4557 return (RE
.r_word1
>> 4) & 1;
4560 bool MachOObjectFile::getScatteredRelocationScattered(
4561 const MachO::any_relocation_info
&RE
) const {
4562 return RE
.r_word0
>> 31;
4565 uint32_t MachOObjectFile::getScatteredRelocationValue(
4566 const MachO::any_relocation_info
&RE
) const {
4570 uint32_t MachOObjectFile::getScatteredRelocationType(
4571 const MachO::any_relocation_info
&RE
) const {
4572 return (RE
.r_word0
>> 24) & 0xf;
4575 unsigned MachOObjectFile::getAnyRelocationAddress(
4576 const MachO::any_relocation_info
&RE
) const {
4577 if (isRelocationScattered(RE
))
4578 return getScatteredRelocationAddress(RE
);
4579 return getPlainRelocationAddress(RE
);
4582 unsigned MachOObjectFile::getAnyRelocationPCRel(
4583 const MachO::any_relocation_info
&RE
) const {
4584 if (isRelocationScattered(RE
))
4585 return getScatteredRelocationPCRel(RE
);
4586 return getPlainRelocationPCRel(*this, RE
);
4589 unsigned MachOObjectFile::getAnyRelocationLength(
4590 const MachO::any_relocation_info
&RE
) const {
4591 if (isRelocationScattered(RE
))
4592 return getScatteredRelocationLength(RE
);
4593 return getPlainRelocationLength(*this, RE
);
4597 MachOObjectFile::getAnyRelocationType(
4598 const MachO::any_relocation_info
&RE
) const {
4599 if (isRelocationScattered(RE
))
4600 return getScatteredRelocationType(RE
);
4601 return getPlainRelocationType(*this, RE
);
4605 MachOObjectFile::getAnyRelocationSection(
4606 const MachO::any_relocation_info
&RE
) const {
4607 if (isRelocationScattered(RE
) || getPlainRelocationExternal(RE
))
4608 return *section_end();
4609 unsigned SecNum
= getPlainRelocationSymbolNum(RE
);
4610 if (SecNum
== MachO::R_ABS
|| SecNum
> Sections
.size())
4611 return *section_end();
4613 DRI
.d
.a
= SecNum
- 1;
4614 return SectionRef(DRI
, this);
4617 MachO::section
MachOObjectFile::getSection(DataRefImpl DRI
) const {
4618 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4619 return getStruct
<MachO::section
>(*this, Sections
[DRI
.d
.a
]);
4622 MachO::section_64
MachOObjectFile::getSection64(DataRefImpl DRI
) const {
4623 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4624 return getStruct
<MachO::section_64
>(*this, Sections
[DRI
.d
.a
]);
4627 MachO::section
MachOObjectFile::getSection(const LoadCommandInfo
&L
,
4628 unsigned Index
) const {
4629 const char *Sec
= getSectionPtr(*this, L
, Index
);
4630 return getStruct
<MachO::section
>(*this, Sec
);
4633 MachO::section_64
MachOObjectFile::getSection64(const LoadCommandInfo
&L
,
4634 unsigned Index
) const {
4635 const char *Sec
= getSectionPtr(*this, L
, Index
);
4636 return getStruct
<MachO::section_64
>(*this, Sec
);
4640 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI
) const {
4641 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4642 return getStruct
<MachO::nlist
>(*this, P
);
4646 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI
) const {
4647 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4648 return getStruct
<MachO::nlist_64
>(*this, P
);
4651 MachO::linkedit_data_command
4652 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo
&L
) const {
4653 return getStruct
<MachO::linkedit_data_command
>(*this, L
.Ptr
);
4656 MachO::segment_command
4657 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo
&L
) const {
4658 return getStruct
<MachO::segment_command
>(*this, L
.Ptr
);
4661 MachO::segment_command_64
4662 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo
&L
) const {
4663 return getStruct
<MachO::segment_command_64
>(*this, L
.Ptr
);
4666 MachO::linker_option_command
4667 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo
&L
) const {
4668 return getStruct
<MachO::linker_option_command
>(*this, L
.Ptr
);
4671 MachO::version_min_command
4672 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo
&L
) const {
4673 return getStruct
<MachO::version_min_command
>(*this, L
.Ptr
);
4677 MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo
&L
) const {
4678 return getStruct
<MachO::note_command
>(*this, L
.Ptr
);
4681 MachO::build_version_command
4682 MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo
&L
) const {
4683 return getStruct
<MachO::build_version_command
>(*this, L
.Ptr
);
4686 MachO::build_tool_version
4687 MachOObjectFile::getBuildToolVersion(unsigned index
) const {
4688 return getStruct
<MachO::build_tool_version
>(*this, BuildTools
[index
]);
4691 MachO::dylib_command
4692 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo
&L
) const {
4693 return getStruct
<MachO::dylib_command
>(*this, L
.Ptr
);
4696 MachO::dyld_info_command
4697 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo
&L
) const {
4698 return getStruct
<MachO::dyld_info_command
>(*this, L
.Ptr
);
4701 MachO::dylinker_command
4702 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo
&L
) const {
4703 return getStruct
<MachO::dylinker_command
>(*this, L
.Ptr
);
4707 MachOObjectFile::getUuidCommand(const LoadCommandInfo
&L
) const {
4708 return getStruct
<MachO::uuid_command
>(*this, L
.Ptr
);
4711 MachO::rpath_command
4712 MachOObjectFile::getRpathCommand(const LoadCommandInfo
&L
) const {
4713 return getStruct
<MachO::rpath_command
>(*this, L
.Ptr
);
4716 MachO::source_version_command
4717 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo
&L
) const {
4718 return getStruct
<MachO::source_version_command
>(*this, L
.Ptr
);
4721 MachO::entry_point_command
4722 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo
&L
) const {
4723 return getStruct
<MachO::entry_point_command
>(*this, L
.Ptr
);
4726 MachO::encryption_info_command
4727 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo
&L
) const {
4728 return getStruct
<MachO::encryption_info_command
>(*this, L
.Ptr
);
4731 MachO::encryption_info_command_64
4732 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo
&L
) const {
4733 return getStruct
<MachO::encryption_info_command_64
>(*this, L
.Ptr
);
4736 MachO::sub_framework_command
4737 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo
&L
) const {
4738 return getStruct
<MachO::sub_framework_command
>(*this, L
.Ptr
);
4741 MachO::sub_umbrella_command
4742 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo
&L
) const {
4743 return getStruct
<MachO::sub_umbrella_command
>(*this, L
.Ptr
);
4746 MachO::sub_library_command
4747 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo
&L
) const {
4748 return getStruct
<MachO::sub_library_command
>(*this, L
.Ptr
);
4751 MachO::sub_client_command
4752 MachOObjectFile::getSubClientCommand(const LoadCommandInfo
&L
) const {
4753 return getStruct
<MachO::sub_client_command
>(*this, L
.Ptr
);
4756 MachO::routines_command
4757 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo
&L
) const {
4758 return getStruct
<MachO::routines_command
>(*this, L
.Ptr
);
4761 MachO::routines_command_64
4762 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo
&L
) const {
4763 return getStruct
<MachO::routines_command_64
>(*this, L
.Ptr
);
4766 MachO::thread_command
4767 MachOObjectFile::getThreadCommand(const LoadCommandInfo
&L
) const {
4768 return getStruct
<MachO::thread_command
>(*this, L
.Ptr
);
4771 MachO::fileset_entry_command
4772 MachOObjectFile::getFilesetEntryLoadCommand(const LoadCommandInfo
&L
) const {
4773 return getStruct
<MachO::fileset_entry_command
>(*this, L
.Ptr
);
4776 MachO::any_relocation_info
4777 MachOObjectFile::getRelocation(DataRefImpl Rel
) const {
4779 if (getHeader().filetype
== MachO::MH_OBJECT
) {
4783 MachO::section_64 Sect
= getSection64(Sec
);
4784 Offset
= Sect
.reloff
;
4786 MachO::section Sect
= getSection(Sec
);
4787 Offset
= Sect
.reloff
;
4790 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
4792 Offset
= DysymtabLoadCmd
.extreloff
; // Offset to the external relocations
4794 Offset
= DysymtabLoadCmd
.locreloff
; // Offset to the local relocations
4797 auto P
= reinterpret_cast<const MachO::any_relocation_info
*>(
4798 getPtr(*this, Offset
)) + Rel
.d
.b
;
4799 return getStruct
<MachO::any_relocation_info
>(
4800 *this, reinterpret_cast<const char *>(P
));
4803 MachO::data_in_code_entry
4804 MachOObjectFile::getDice(DataRefImpl Rel
) const {
4805 const char *P
= reinterpret_cast<const char *>(Rel
.p
);
4806 return getStruct
<MachO::data_in_code_entry
>(*this, P
);
4809 const MachO::mach_header
&MachOObjectFile::getHeader() const {
4813 const MachO::mach_header_64
&MachOObjectFile::getHeader64() const {
4818 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4819 const MachO::dysymtab_command
&DLC
,
4820 unsigned Index
) const {
4821 uint64_t Offset
= DLC
.indirectsymoff
+ Index
* sizeof(uint32_t);
4822 return getStruct
<uint32_t>(*this, getPtr(*this, Offset
));
4825 MachO::data_in_code_entry
4826 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset
,
4827 unsigned Index
) const {
4828 uint64_t Offset
= DataOffset
+ Index
* sizeof(MachO::data_in_code_entry
);
4829 return getStruct
<MachO::data_in_code_entry
>(*this, getPtr(*this, Offset
));
4832 MachO::symtab_command
MachOObjectFile::getSymtabLoadCommand() const {
4834 return getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
4836 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4837 MachO::symtab_command Cmd
;
4838 Cmd
.cmd
= MachO::LC_SYMTAB
;
4839 Cmd
.cmdsize
= sizeof(MachO::symtab_command
);
4847 MachO::dysymtab_command
MachOObjectFile::getDysymtabLoadCommand() const {
4848 if (DysymtabLoadCmd
)
4849 return getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
4851 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4852 MachO::dysymtab_command Cmd
;
4853 Cmd
.cmd
= MachO::LC_DYSYMTAB
;
4854 Cmd
.cmdsize
= sizeof(MachO::dysymtab_command
);
4865 Cmd
.extrefsymoff
= 0;
4866 Cmd
.nextrefsyms
= 0;
4867 Cmd
.indirectsymoff
= 0;
4868 Cmd
.nindirectsyms
= 0;
4876 MachO::linkedit_data_command
4877 MachOObjectFile::getDataInCodeLoadCommand() const {
4878 if (DataInCodeLoadCmd
)
4879 return getStruct
<MachO::linkedit_data_command
>(*this, DataInCodeLoadCmd
);
4881 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4882 MachO::linkedit_data_command Cmd
;
4883 Cmd
.cmd
= MachO::LC_DATA_IN_CODE
;
4884 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4890 MachO::linkedit_data_command
4891 MachOObjectFile::getLinkOptHintsLoadCommand() const {
4892 if (LinkOptHintsLoadCmd
)
4893 return getStruct
<MachO::linkedit_data_command
>(*this, LinkOptHintsLoadCmd
);
4895 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4897 MachO::linkedit_data_command Cmd
;
4898 Cmd
.cmd
= MachO::LC_LINKER_OPTIMIZATION_HINT
;
4899 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4905 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4906 if (!DyldInfoLoadCmd
)
4907 return std::nullopt
;
4909 auto DyldInfoOrErr
=
4910 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4912 return std::nullopt
;
4913 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4914 const uint8_t *Ptr
=
4915 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.rebase_off
));
4916 return ArrayRef(Ptr
, DyldInfo
.rebase_size
);
4919 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4920 if (!DyldInfoLoadCmd
)
4921 return std::nullopt
;
4923 auto DyldInfoOrErr
=
4924 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4926 return std::nullopt
;
4927 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4928 const uint8_t *Ptr
=
4929 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.bind_off
));
4930 return ArrayRef(Ptr
, DyldInfo
.bind_size
);
4933 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4934 if (!DyldInfoLoadCmd
)
4935 return std::nullopt
;
4937 auto DyldInfoOrErr
=
4938 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4940 return std::nullopt
;
4941 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4942 const uint8_t *Ptr
=
4943 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.weak_bind_off
));
4944 return ArrayRef(Ptr
, DyldInfo
.weak_bind_size
);
4947 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4948 if (!DyldInfoLoadCmd
)
4949 return std::nullopt
;
4951 auto DyldInfoOrErr
=
4952 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4954 return std::nullopt
;
4955 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4956 const uint8_t *Ptr
=
4957 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.lazy_bind_off
));
4958 return ArrayRef(Ptr
, DyldInfo
.lazy_bind_size
);
4961 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4962 if (!DyldInfoLoadCmd
)
4963 return std::nullopt
;
4965 auto DyldInfoOrErr
=
4966 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4968 return std::nullopt
;
4969 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4970 const uint8_t *Ptr
=
4971 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.export_off
));
4972 return ArrayRef(Ptr
, DyldInfo
.export_size
);
4975 Expected
<std::optional
<MachO::linkedit_data_command
>>
4976 MachOObjectFile::getChainedFixupsLoadCommand() const {
4977 // Load the dyld chained fixups load command.
4978 if (!DyldChainedFixupsLoadCmd
)
4979 return std::nullopt
;
4980 auto DyldChainedFixupsOrErr
= getStructOrErr
<MachO::linkedit_data_command
>(
4981 *this, DyldChainedFixupsLoadCmd
);
4982 if (!DyldChainedFixupsOrErr
)
4983 return DyldChainedFixupsOrErr
.takeError();
4984 const MachO::linkedit_data_command
&DyldChainedFixups
=
4985 *DyldChainedFixupsOrErr
;
4987 // If the load command is present but the data offset has been zeroed out,
4988 // as is the case for dylib stubs, return std::nullopt (no error).
4989 if (!DyldChainedFixups
.dataoff
)
4990 return std::nullopt
;
4991 return DyldChainedFixups
;
4994 Expected
<std::optional
<MachO::dyld_chained_fixups_header
>>
4995 MachOObjectFile::getChainedFixupsHeader() const {
4996 auto CFOrErr
= getChainedFixupsLoadCommand();
4998 return CFOrErr
.takeError();
4999 if (!CFOrErr
->has_value())
5000 return std::nullopt
;
5002 const MachO::linkedit_data_command
&DyldChainedFixups
= **CFOrErr
;
5004 uint64_t CFHeaderOffset
= DyldChainedFixups
.dataoff
;
5005 uint64_t CFSize
= DyldChainedFixups
.datasize
;
5007 // Load the dyld chained fixups header.
5008 const char *CFHeaderPtr
= getPtr(*this, CFHeaderOffset
);
5009 auto CFHeaderOrErr
=
5010 getStructOrErr
<MachO::dyld_chained_fixups_header
>(*this, CFHeaderPtr
);
5012 return CFHeaderOrErr
.takeError();
5013 MachO::dyld_chained_fixups_header CFHeader
= CFHeaderOrErr
.get();
5015 // Reject unknown chained fixup formats.
5016 if (CFHeader
.fixups_version
!= 0)
5017 return malformedError(Twine("bad chained fixups: unknown version: ") +
5018 Twine(CFHeader
.fixups_version
));
5019 if (CFHeader
.imports_format
< 1 || CFHeader
.imports_format
> 3)
5020 return malformedError(
5021 Twine("bad chained fixups: unknown imports format: ") +
5022 Twine(CFHeader
.imports_format
));
5024 // Validate the image format.
5026 // Load the image starts.
5027 uint64_t CFImageStartsOffset
= (CFHeaderOffset
+ CFHeader
.starts_offset
);
5028 if (CFHeader
.starts_offset
< sizeof(MachO::dyld_chained_fixups_header
)) {
5029 return malformedError(Twine("bad chained fixups: image starts offset ") +
5030 Twine(CFHeader
.starts_offset
) +
5031 " overlaps with chained fixups header");
5033 uint32_t EndOffset
= CFHeaderOffset
+ CFSize
;
5034 if (CFImageStartsOffset
+ sizeof(MachO::dyld_chained_starts_in_image
) >
5036 return malformedError(Twine("bad chained fixups: image starts end ") +
5037 Twine(CFImageStartsOffset
+
5038 sizeof(MachO::dyld_chained_starts_in_image
)) +
5039 " extends past end " + Twine(EndOffset
));
5045 Expected
<std::pair
<size_t, std::vector
<ChainedFixupsSegment
>>>
5046 MachOObjectFile::getChainedFixupsSegments() const {
5047 auto CFOrErr
= getChainedFixupsLoadCommand();
5049 return CFOrErr
.takeError();
5051 std::vector
<ChainedFixupsSegment
> Segments
;
5052 if (!CFOrErr
->has_value())
5053 return std::make_pair(0, Segments
);
5055 const MachO::linkedit_data_command
&DyldChainedFixups
= **CFOrErr
;
5057 auto HeaderOrErr
= getChainedFixupsHeader();
5059 return HeaderOrErr
.takeError();
5060 if (!HeaderOrErr
->has_value())
5061 return std::make_pair(0, Segments
);
5062 const MachO::dyld_chained_fixups_header
&Header
= **HeaderOrErr
;
5064 const char *Contents
= getPtr(*this, DyldChainedFixups
.dataoff
);
5066 auto ImageStartsOrErr
= getStructOrErr
<MachO::dyld_chained_starts_in_image
>(
5067 *this, Contents
+ Header
.starts_offset
);
5068 if (!ImageStartsOrErr
)
5069 return ImageStartsOrErr
.takeError();
5070 const MachO::dyld_chained_starts_in_image
&ImageStarts
= *ImageStartsOrErr
;
5072 const char *SegOffsPtr
=
5073 Contents
+ Header
.starts_offset
+
5074 offsetof(MachO::dyld_chained_starts_in_image
, seg_info_offset
);
5075 const char *SegOffsEnd
=
5076 SegOffsPtr
+ ImageStarts
.seg_count
* sizeof(uint32_t);
5077 if (SegOffsEnd
> Contents
+ DyldChainedFixups
.datasize
)
5078 return malformedError(
5079 "bad chained fixups: seg_info_offset extends past end");
5081 const char *LastSegEnd
= nullptr;
5082 for (size_t I
= 0, N
= ImageStarts
.seg_count
; I
< N
; ++I
) {
5084 getStructOrErr
<uint32_t>(*this, SegOffsPtr
+ I
* sizeof(uint32_t));
5086 return OffOrErr
.takeError();
5087 // seg_info_offset == 0 means there is no associated starts_in_segment
5092 auto Fail
= [&](Twine Message
) {
5093 return malformedError("bad chained fixups: segment info" + Twine(I
) +
5094 " at offset " + Twine(*OffOrErr
) + Message
);
5097 const char *SegPtr
= Contents
+ Header
.starts_offset
+ *OffOrErr
;
5098 if (LastSegEnd
&& SegPtr
< LastSegEnd
)
5099 return Fail(" overlaps with previous segment info");
5102 getStructOrErr
<MachO::dyld_chained_starts_in_segment
>(*this, SegPtr
);
5104 return SegOrErr
.takeError();
5105 const MachO::dyld_chained_starts_in_segment
&Seg
= *SegOrErr
;
5107 LastSegEnd
= SegPtr
+ Seg
.size
;
5108 if (Seg
.pointer_format
< 1 || Seg
.pointer_format
> 12)
5109 return Fail(" has unknown pointer format: " + Twine(Seg
.pointer_format
));
5111 const char *PageStart
=
5112 SegPtr
+ offsetof(MachO::dyld_chained_starts_in_segment
, page_start
);
5113 const char *PageEnd
= PageStart
+ Seg
.page_count
* sizeof(uint16_t);
5114 if (PageEnd
> SegPtr
+ Seg
.size
)
5115 return Fail(" : page_starts extend past seg_info size");
5117 // FIXME: This does not account for multiple offsets on a single page
5118 // (DYLD_CHAINED_PTR_START_MULTI; 32-bit only).
5119 std::vector
<uint16_t> PageStarts
;
5120 for (size_t PageIdx
= 0; PageIdx
< Seg
.page_count
; ++PageIdx
) {
5122 memcpy(&Start
, PageStart
+ PageIdx
* sizeof(uint16_t), sizeof(uint16_t));
5123 if (isLittleEndian() != sys::IsLittleEndianHost
)
5124 sys::swapByteOrder(Start
);
5125 PageStarts
.push_back(Start
);
5128 Segments
.emplace_back(I
, *OffOrErr
, Seg
, std::move(PageStarts
));
5131 return std::make_pair(ImageStarts
.seg_count
, Segments
);
5134 // The special library ordinals have a negative value, but they are encoded in
5135 // an unsigned bitfield, so we need to sign extend the value.
5136 template <typename T
> static int getEncodedOrdinal(T Value
) {
5137 if (Value
== static_cast<T
>(MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE
) ||
5138 Value
== static_cast<T
>(MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP
) ||
5139 Value
== static_cast<T
>(MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP
))
5140 return SignExtend32
<sizeof(T
) * CHAR_BIT
>(Value
);
5144 template <typename T
, unsigned N
>
5145 static std::array
<T
, N
> getArray(const MachOObjectFile
&O
, const void *Ptr
) {
5146 std::array
<T
, N
> RawValue
;
5147 memcpy(RawValue
.data(), Ptr
, N
* sizeof(T
));
5148 if (O
.isLittleEndian() != sys::IsLittleEndianHost
)
5149 for (auto &Element
: RawValue
)
5150 sys::swapByteOrder(Element
);
5154 Expected
<std::vector
<ChainedFixupTarget
>>
5155 MachOObjectFile::getDyldChainedFixupTargets() const {
5156 auto CFOrErr
= getChainedFixupsLoadCommand();
5158 return CFOrErr
.takeError();
5160 std::vector
<ChainedFixupTarget
> Targets
;
5161 if (!CFOrErr
->has_value())
5164 const MachO::linkedit_data_command
&DyldChainedFixups
= **CFOrErr
;
5166 auto CFHeaderOrErr
= getChainedFixupsHeader();
5168 return CFHeaderOrErr
.takeError();
5169 if (!(*CFHeaderOrErr
))
5171 const MachO::dyld_chained_fixups_header
&Header
= **CFHeaderOrErr
;
5173 size_t ImportSize
= 0;
5174 if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT
)
5175 ImportSize
= sizeof(MachO::dyld_chained_import
);
5176 else if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT_ADDEND
)
5177 ImportSize
= sizeof(MachO::dyld_chained_import_addend
);
5178 else if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT_ADDEND64
)
5179 ImportSize
= sizeof(MachO::dyld_chained_import_addend64
);
5181 return malformedError("bad chained fixups: unknown imports format: " +
5182 Twine(Header
.imports_format
));
5184 const char *Contents
= getPtr(*this, DyldChainedFixups
.dataoff
);
5185 const char *Imports
= Contents
+ Header
.imports_offset
;
5186 size_t ImportsEndOffset
=
5187 Header
.imports_offset
+ ImportSize
* Header
.imports_count
;
5188 const char *ImportsEnd
= Contents
+ ImportsEndOffset
;
5189 const char *Symbols
= Contents
+ Header
.symbols_offset
;
5190 const char *SymbolsEnd
= Contents
+ DyldChainedFixups
.datasize
;
5192 if (ImportsEnd
> Symbols
)
5193 return malformedError("bad chained fixups: imports end " +
5194 Twine(ImportsEndOffset
) + " extends past end " +
5195 Twine(DyldChainedFixups
.datasize
));
5197 if (ImportsEnd
> Symbols
)
5198 return malformedError("bad chained fixups: imports end " +
5199 Twine(ImportsEndOffset
) + " overlaps with symbols");
5201 // We use bit manipulation to extract data from the bitfields. This is correct
5202 // for both LE and BE hosts, but we assume that the object is little-endian.
5203 if (!isLittleEndian())
5204 return createError("parsing big-endian chained fixups is not implemented");
5205 for (const char *ImportPtr
= Imports
; ImportPtr
< ImportsEnd
;
5206 ImportPtr
+= ImportSize
) {
5209 uint32_t NameOffset
;
5211 if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT
) {
5212 static_assert(sizeof(uint32_t) == sizeof(MachO::dyld_chained_import
));
5213 auto RawValue
= getArray
<uint32_t, 1>(*this, ImportPtr
);
5215 LibOrdinal
= getEncodedOrdinal
<uint8_t>(RawValue
[0] & 0xFF);
5216 WeakImport
= (RawValue
[0] >> 8) & 1;
5217 NameOffset
= RawValue
[0] >> 9;
5219 } else if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT_ADDEND
) {
5220 static_assert(sizeof(uint64_t) ==
5221 sizeof(MachO::dyld_chained_import_addend
));
5222 auto RawValue
= getArray
<uint32_t, 2>(*this, ImportPtr
);
5224 LibOrdinal
= getEncodedOrdinal
<uint8_t>(RawValue
[0] & 0xFF);
5225 WeakImport
= (RawValue
[0] >> 8) & 1;
5226 NameOffset
= RawValue
[0] >> 9;
5227 Addend
= bit_cast
<int32_t>(RawValue
[1]);
5228 } else if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT_ADDEND64
) {
5229 static_assert(2 * sizeof(uint64_t) ==
5230 sizeof(MachO::dyld_chained_import_addend64
));
5231 auto RawValue
= getArray
<uint64_t, 2>(*this, ImportPtr
);
5233 LibOrdinal
= getEncodedOrdinal
<uint16_t>(RawValue
[0] & 0xFFFF);
5234 NameOffset
= (RawValue
[0] >> 16) & 1;
5235 WeakImport
= RawValue
[0] >> 17;
5236 Addend
= RawValue
[1];
5238 llvm_unreachable("Import format should have been checked");
5241 const char *Str
= Symbols
+ NameOffset
;
5242 if (Str
>= SymbolsEnd
)
5243 return malformedError("bad chained fixups: symbol offset " +
5244 Twine(NameOffset
) + " extends past end " +
5245 Twine(DyldChainedFixups
.datasize
));
5246 Targets
.emplace_back(LibOrdinal
, NameOffset
, Str
, Addend
, WeakImport
);
5249 return std::move(Targets
);
5252 ArrayRef
<uint8_t> MachOObjectFile::getDyldExportsTrie() const {
5253 if (!DyldExportsTrieLoadCmd
)
5254 return std::nullopt
;
5256 auto DyldExportsTrieOrError
= getStructOrErr
<MachO::linkedit_data_command
>(
5257 *this, DyldExportsTrieLoadCmd
);
5258 if (!DyldExportsTrieOrError
)
5259 return std::nullopt
;
5260 MachO::linkedit_data_command DyldExportsTrie
= DyldExportsTrieOrError
.get();
5261 const uint8_t *Ptr
=
5262 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldExportsTrie
.dataoff
));
5263 return ArrayRef(Ptr
, DyldExportsTrie
.datasize
);
5266 SmallVector
<uint64_t> MachOObjectFile::getFunctionStarts() const {
5267 if (!FuncStartsLoadCmd
)
5271 getStructOrErr
<MachO::linkedit_data_command
>(*this, FuncStartsLoadCmd
);
5275 MachO::linkedit_data_command Info
= InfoOrErr
.get();
5276 SmallVector
<uint64_t, 8> FunctionStarts
;
5277 this->ReadULEB128s(Info
.dataoff
, FunctionStarts
);
5278 return std::move(FunctionStarts
);
5281 ArrayRef
<uint8_t> MachOObjectFile::getUuid() const {
5283 return std::nullopt
;
5284 // Returning a pointer is fine as uuid doesn't need endian swapping.
5285 const char *Ptr
= UuidLoadCmd
+ offsetof(MachO::uuid_command
, uuid
);
5286 return ArrayRef(reinterpret_cast<const uint8_t *>(Ptr
), 16);
5289 StringRef
MachOObjectFile::getStringTableData() const {
5290 MachO::symtab_command S
= getSymtabLoadCommand();
5291 return getData().substr(S
.stroff
, S
.strsize
);
5294 bool MachOObjectFile::is64Bit() const {
5295 return getType() == getMachOType(false, true) ||
5296 getType() == getMachOType(true, true);
5299 void MachOObjectFile::ReadULEB128s(uint64_t Index
,
5300 SmallVectorImpl
<uint64_t> &Out
) const {
5301 DataExtractor
extractor(ObjectFile::getData(), true, 0);
5303 uint64_t offset
= Index
;
5305 while (uint64_t delta
= extractor
.getULEB128(&offset
)) {
5307 Out
.push_back(data
);
5311 bool MachOObjectFile::isRelocatableObject() const {
5312 return getHeader().filetype
== MachO::MH_OBJECT
;
5315 /// Create a MachOObjectFile instance from a given buffer.
5317 /// \param Buffer Memory buffer containing the MachO binary data.
5318 /// \param UniversalCputype CPU type when the MachO part of a universal binary.
5319 /// \param UniversalIndex Index of the MachO within a universal binary.
5320 /// \param MachOFilesetEntryOffset Offset of the MachO entry in a fileset MachO.
5321 /// \returns A std::unique_ptr to a MachOObjectFile instance on success.
5322 Expected
<std::unique_ptr
<MachOObjectFile
>> ObjectFile::createMachOObjectFile(
5323 MemoryBufferRef Buffer
, uint32_t UniversalCputype
, uint32_t UniversalIndex
,
5324 size_t MachOFilesetEntryOffset
) {
5325 StringRef Magic
= Buffer
.getBuffer().slice(0, 4);
5326 if (Magic
== "\xFE\xED\xFA\xCE")
5327 return MachOObjectFile::create(Buffer
, false, false, UniversalCputype
,
5328 UniversalIndex
, MachOFilesetEntryOffset
);
5329 if (Magic
== "\xCE\xFA\xED\xFE")
5330 return MachOObjectFile::create(Buffer
, true, false, UniversalCputype
,
5331 UniversalIndex
, MachOFilesetEntryOffset
);
5332 if (Magic
== "\xFE\xED\xFA\xCF")
5333 return MachOObjectFile::create(Buffer
, false, true, UniversalCputype
,
5334 UniversalIndex
, MachOFilesetEntryOffset
);
5335 if (Magic
== "\xCF\xFA\xED\xFE")
5336 return MachOObjectFile::create(Buffer
, true, true, UniversalCputype
,
5337 UniversalIndex
, MachOFilesetEntryOffset
);
5338 return make_error
<GenericBinaryError
>("Unrecognized MachO magic number",
5339 object_error::invalid_file_type
);
5342 StringRef
MachOObjectFile::mapDebugSectionName(StringRef Name
) const {
5343 return StringSwitch
<StringRef
>(Name
)
5344 .Case("debug_str_offs", "debug_str_offsets")
5348 Expected
<std::vector
<std::string
>>
5349 MachOObjectFile::findDsymObjectMembers(StringRef Path
) {
5350 SmallString
<256> BundlePath(Path
);
5351 // Normalize input path. This is necessary to accept `bundle.dSYM/`.
5352 sys::path::remove_dots(BundlePath
);
5353 if (!sys::fs::is_directory(BundlePath
) ||
5354 sys::path::extension(BundlePath
) != ".dSYM")
5355 return std::vector
<std::string
>();
5356 sys::path::append(BundlePath
, "Contents", "Resources", "DWARF");
5358 auto EC
= sys::fs::is_directory(BundlePath
, IsDir
);
5359 if (EC
== errc::no_such_file_or_directory
|| (!EC
&& !IsDir
))
5360 return createStringError(
5361 EC
, "%s: expected directory 'Contents/Resources/DWARF' in dSYM bundle",
5362 Path
.str().c_str());
5364 return createFileError(BundlePath
, errorCodeToError(EC
));
5366 std::vector
<std::string
> ObjectPaths
;
5367 for (sys::fs::directory_iterator
Dir(BundlePath
, EC
), DirEnd
;
5368 Dir
!= DirEnd
&& !EC
; Dir
.increment(EC
)) {
5369 StringRef ObjectPath
= Dir
->path();
5370 sys::fs::file_status Status
;
5371 if (auto EC
= sys::fs::status(ObjectPath
, Status
))
5372 return createFileError(ObjectPath
, errorCodeToError(EC
));
5373 switch (Status
.type()) {
5374 case sys::fs::file_type::regular_file
:
5375 case sys::fs::file_type::symlink_file
:
5376 case sys::fs::file_type::type_unknown
:
5377 ObjectPaths
.push_back(ObjectPath
.str());
5379 default: /*ignore*/;
5383 return createFileError(BundlePath
, errorCodeToError(EC
));
5384 if (ObjectPaths
.empty())
5385 return createStringError(std::error_code(),
5386 "%s: no objects found in dSYM bundle",
5387 Path
.str().c_str());
5391 llvm::binaryformat::Swift5ReflectionSectionKind
5392 MachOObjectFile::mapReflectionSectionNameToEnumValue(
5393 StringRef SectionName
) const {
5394 #define HANDLE_SWIFT_SECTION(KIND, MACHO, ELF, COFF) \
5395 .Case(MACHO, llvm::binaryformat::Swift5ReflectionSectionKind::KIND)
5396 return StringSwitch
<llvm::binaryformat::Swift5ReflectionSectionKind
>(
5398 #include "llvm/BinaryFormat/Swift.def"
5399 .Default(llvm::binaryformat::Swift5ReflectionSectionKind::unknown
);
5400 #undef HANDLE_SWIFT_SECTION
5403 bool MachOObjectFile::isMachOPairedReloc(uint64_t RelocType
, uint64_t Arch
) {
5406 return RelocType
== MachO::GENERIC_RELOC_SECTDIFF
||
5407 RelocType
== MachO::GENERIC_RELOC_LOCAL_SECTDIFF
;
5408 case Triple::x86_64
:
5409 return RelocType
== MachO::X86_64_RELOC_SUBTRACTOR
;
5412 return RelocType
== MachO::ARM_RELOC_SECTDIFF
||
5413 RelocType
== MachO::ARM_RELOC_LOCAL_SECTDIFF
||
5414 RelocType
== MachO::ARM_RELOC_HALF
||
5415 RelocType
== MachO::ARM_RELOC_HALF_SECTDIFF
;
5416 case Triple::aarch64
:
5417 return RelocType
== MachO::ARM64_RELOC_SUBTRACTOR
;