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
& ~MachO::CPU_SUBTYPE_MASK
;
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") == 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
.starts_with("__debug") ||
2070 SectionName
.starts_with("__zdebug") ||
2071 SectionName
.starts_with("__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).starts_with(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().substr(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", "ARM64_RELOC_AUTHENTICATED_POINTER"
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
.substr(a
+ 1);
2441 // Look for a suffix starting with a '_'
2442 Idx
= Foo
.rfind('_');
2443 if (Idx
!= Foo
.npos
&& Foo
.size() >= 2) {
2444 Suffix
= Foo
.substr(Idx
);
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
.substr(Idx
, Foo
.size());
2458 DotFramework
= Name
.substr(Idx
+ Foo
.size(), sizeof(".framework/") - 1);
2459 if (F
== Foo
&& DotFramework
== ".framework/") {
2464 // Next look for the form Foo.framework/Versions/A/Foo
2467 c
= Name
.rfind('/', b
);
2468 if (c
== Name
.npos
|| c
== 0)
2470 V
= Name
.substr(c
+ 1);
2471 if (!V
.starts_with("Versions/"))
2473 d
= Name
.rfind('/', c
);
2478 F
= Name
.substr(Idx
, Foo
.size());
2479 DotFramework
= Name
.substr(Idx
+ Foo
.size(), sizeof(".framework/") - 1);
2480 if (F
== Foo
&& DotFramework
== ".framework/") {
2486 // pull off the suffix after the "." and make a point to it
2487 a
= Name
.rfind('.');
2488 if (a
== Name
.npos
|| a
== 0)
2490 Dylib
= Name
.substr(a
);
2491 if (Dylib
!= ".dylib")
2494 // First pull off the version letter for the form Foo.A.dylib if any.
2496 Dot
= Name
.substr(a
- 2, 1);
2501 b
= Name
.rfind('/', a
);
2506 // ignore any suffix after an underbar like Foo_profile.A.dylib
2507 Idx
= Name
.rfind('_');
2508 if (Idx
!= Name
.npos
&& Idx
!= b
) {
2509 Lib
= Name
.slice(b
, Idx
);
2510 Suffix
= Name
.slice(Idx
, a
);
2511 if (Suffix
!= "_debug" && Suffix
!= "_profile") {
2512 Suffix
= StringRef();
2513 Lib
= Name
.slice(b
, a
);
2517 Lib
= Name
.slice(b
, a
);
2518 // There are incorrect library names of the form:
2519 // libATS.A_profile.dylib so check for these.
2520 if (Lib
.size() >= 3) {
2521 Dot
= Lib
.substr(Lib
.size() - 2, 1);
2523 Lib
= Lib
.slice(0, Lib
.size()-2);
2528 Qtx
= Name
.substr(a
);
2531 b
= Name
.rfind('/', a
);
2533 Lib
= Name
.slice(0, a
);
2535 Lib
= Name
.slice(b
+1, a
);
2536 // There are library names of the form: QT.A.qtx so check for these.
2537 if (Lib
.size() >= 3) {
2538 Dot
= Lib
.substr(Lib
.size() - 2, 1);
2540 Lib
= Lib
.slice(0, Lib
.size()-2);
2545 // getLibraryShortNameByIndex() is used to get the short name of the library
2546 // for an undefined symbol in a linked Mach-O binary that was linked with the
2547 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
2548 // It is passed the index (0 - based) of the library as translated from
2549 // GET_LIBRARY_ORDINAL (1 - based).
2550 std::error_code
MachOObjectFile::getLibraryShortNameByIndex(unsigned Index
,
2551 StringRef
&Res
) const {
2552 if (Index
>= Libraries
.size())
2553 return object_error::parse_failed
;
2555 // If the cache of LibrariesShortNames is not built up do that first for
2556 // all the Libraries.
2557 if (LibrariesShortNames
.size() == 0) {
2558 for (unsigned i
= 0; i
< Libraries
.size(); i
++) {
2560 getStructOrErr
<MachO::dylib_command
>(*this, Libraries
[i
]);
2562 return object_error::parse_failed
;
2563 MachO::dylib_command D
= CommandOrErr
.get();
2564 if (D
.dylib
.name
>= D
.cmdsize
)
2565 return object_error::parse_failed
;
2566 const char *P
= (const char *)(Libraries
[i
]) + D
.dylib
.name
;
2567 StringRef Name
= StringRef(P
);
2568 if (D
.dylib
.name
+Name
.size() >= D
.cmdsize
)
2569 return object_error::parse_failed
;
2572 StringRef shortName
= guessLibraryShortName(Name
, isFramework
, Suffix
);
2573 if (shortName
.empty())
2574 LibrariesShortNames
.push_back(Name
);
2576 LibrariesShortNames
.push_back(shortName
);
2580 Res
= LibrariesShortNames
[Index
];
2581 return std::error_code();
2584 uint32_t MachOObjectFile::getLibraryCount() const {
2585 return Libraries
.size();
2589 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel
) const {
2591 Sec
.d
.a
= Rel
->getRawDataRefImpl().d
.a
;
2592 return section_iterator(SectionRef(Sec
, this));
2595 basic_symbol_iterator
MachOObjectFile::symbol_begin() const {
2597 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2598 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2599 return basic_symbol_iterator(SymbolRef(DRI
, this));
2601 return getSymbolByIndex(0);
2604 basic_symbol_iterator
MachOObjectFile::symbol_end() const {
2606 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2607 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2608 return basic_symbol_iterator(SymbolRef(DRI
, this));
2610 unsigned SymbolTableEntrySize
= is64Bit() ?
2611 sizeof(MachO::nlist_64
) :
2612 sizeof(MachO::nlist
);
2613 unsigned Offset
= Symtab
.symoff
+
2614 Symtab
.nsyms
* SymbolTableEntrySize
;
2615 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2616 return basic_symbol_iterator(SymbolRef(DRI
, this));
2619 symbol_iterator
MachOObjectFile::getSymbolByIndex(unsigned Index
) const {
2620 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2621 if (!SymtabLoadCmd
|| Index
>= Symtab
.nsyms
)
2622 report_fatal_error("Requested symbol index is out of range.");
2623 unsigned SymbolTableEntrySize
=
2624 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2626 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2627 DRI
.p
+= Index
* SymbolTableEntrySize
;
2628 return basic_symbol_iterator(SymbolRef(DRI
, this));
2631 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb
) const {
2632 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2634 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2635 unsigned SymbolTableEntrySize
=
2636 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2637 DataRefImpl DRIstart
;
2638 DRIstart
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2639 uint64_t Index
= (Symb
.p
- DRIstart
.p
) / SymbolTableEntrySize
;
2643 section_iterator
MachOObjectFile::section_begin() const {
2645 return section_iterator(SectionRef(DRI
, this));
2648 section_iterator
MachOObjectFile::section_end() const {
2650 DRI
.d
.a
= Sections
.size();
2651 return section_iterator(SectionRef(DRI
, this));
2654 uint8_t MachOObjectFile::getBytesInAddress() const {
2655 return is64Bit() ? 8 : 4;
2658 StringRef
MachOObjectFile::getFileFormatName() const {
2659 unsigned CPUType
= getCPUType(*this);
2662 case MachO::CPU_TYPE_I386
:
2663 return "Mach-O 32-bit i386";
2664 case MachO::CPU_TYPE_ARM
:
2665 return "Mach-O arm";
2666 case MachO::CPU_TYPE_ARM64_32
:
2667 return "Mach-O arm64 (ILP32)";
2668 case MachO::CPU_TYPE_POWERPC
:
2669 return "Mach-O 32-bit ppc";
2671 return "Mach-O 32-bit unknown";
2676 case MachO::CPU_TYPE_X86_64
:
2677 return "Mach-O 64-bit x86-64";
2678 case MachO::CPU_TYPE_ARM64
:
2679 return "Mach-O arm64";
2680 case MachO::CPU_TYPE_POWERPC64
:
2681 return "Mach-O 64-bit ppc64";
2683 return "Mach-O 64-bit unknown";
2687 Triple::ArchType
MachOObjectFile::getArch(uint32_t CPUType
, uint32_t CPUSubType
) {
2689 case MachO::CPU_TYPE_I386
:
2691 case MachO::CPU_TYPE_X86_64
:
2692 return Triple::x86_64
;
2693 case MachO::CPU_TYPE_ARM
:
2695 case MachO::CPU_TYPE_ARM64
:
2696 return Triple::aarch64
;
2697 case MachO::CPU_TYPE_ARM64_32
:
2698 return Triple::aarch64_32
;
2699 case MachO::CPU_TYPE_POWERPC
:
2701 case MachO::CPU_TYPE_POWERPC64
:
2702 return Triple::ppc64
;
2704 return Triple::UnknownArch
;
2708 Triple
MachOObjectFile::getArchTriple(uint32_t CPUType
, uint32_t CPUSubType
,
2709 const char **McpuDefault
,
2710 const char **ArchFlag
) {
2712 *McpuDefault
= nullptr;
2714 *ArchFlag
= nullptr;
2717 case MachO::CPU_TYPE_I386
:
2718 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2719 case MachO::CPU_SUBTYPE_I386_ALL
:
2722 return Triple("i386-apple-darwin");
2726 case MachO::CPU_TYPE_X86_64
:
2727 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2728 case MachO::CPU_SUBTYPE_X86_64_ALL
:
2730 *ArchFlag
= "x86_64";
2731 return Triple("x86_64-apple-darwin");
2732 case MachO::CPU_SUBTYPE_X86_64_H
:
2734 *ArchFlag
= "x86_64h";
2735 return Triple("x86_64h-apple-darwin");
2739 case MachO::CPU_TYPE_ARM
:
2740 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2741 case MachO::CPU_SUBTYPE_ARM_V4T
:
2743 *ArchFlag
= "armv4t";
2744 return Triple("armv4t-apple-darwin");
2745 case MachO::CPU_SUBTYPE_ARM_V5TEJ
:
2747 *ArchFlag
= "armv5e";
2748 return Triple("armv5e-apple-darwin");
2749 case MachO::CPU_SUBTYPE_ARM_XSCALE
:
2751 *ArchFlag
= "xscale";
2752 return Triple("xscale-apple-darwin");
2753 case MachO::CPU_SUBTYPE_ARM_V6
:
2755 *ArchFlag
= "armv6";
2756 return Triple("armv6-apple-darwin");
2757 case MachO::CPU_SUBTYPE_ARM_V6M
:
2759 *McpuDefault
= "cortex-m0";
2761 *ArchFlag
= "armv6m";
2762 return Triple("armv6m-apple-darwin");
2763 case MachO::CPU_SUBTYPE_ARM_V7
:
2765 *ArchFlag
= "armv7";
2766 return Triple("armv7-apple-darwin");
2767 case MachO::CPU_SUBTYPE_ARM_V7EM
:
2769 *McpuDefault
= "cortex-m4";
2771 *ArchFlag
= "armv7em";
2772 return Triple("thumbv7em-apple-darwin");
2773 case MachO::CPU_SUBTYPE_ARM_V7K
:
2775 *McpuDefault
= "cortex-a7";
2777 *ArchFlag
= "armv7k";
2778 return Triple("armv7k-apple-darwin");
2779 case MachO::CPU_SUBTYPE_ARM_V7M
:
2781 *McpuDefault
= "cortex-m3";
2783 *ArchFlag
= "armv7m";
2784 return Triple("thumbv7m-apple-darwin");
2785 case MachO::CPU_SUBTYPE_ARM_V7S
:
2787 *McpuDefault
= "cortex-a7";
2789 *ArchFlag
= "armv7s";
2790 return Triple("armv7s-apple-darwin");
2794 case MachO::CPU_TYPE_ARM64
:
2795 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2796 case MachO::CPU_SUBTYPE_ARM64_ALL
:
2798 *McpuDefault
= "cyclone";
2800 *ArchFlag
= "arm64";
2801 return Triple("arm64-apple-darwin");
2802 case MachO::CPU_SUBTYPE_ARM64E
:
2804 *McpuDefault
= "apple-a12";
2806 *ArchFlag
= "arm64e";
2807 return Triple("arm64e-apple-darwin");
2811 case MachO::CPU_TYPE_ARM64_32
:
2812 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2813 case MachO::CPU_SUBTYPE_ARM64_32_V8
:
2815 *McpuDefault
= "cyclone";
2817 *ArchFlag
= "arm64_32";
2818 return Triple("arm64_32-apple-darwin");
2822 case MachO::CPU_TYPE_POWERPC
:
2823 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2824 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2827 return Triple("ppc-apple-darwin");
2831 case MachO::CPU_TYPE_POWERPC64
:
2832 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2833 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2835 *ArchFlag
= "ppc64";
2836 return Triple("ppc64-apple-darwin");
2845 Triple
MachOObjectFile::getHostArch() {
2846 return Triple(sys::getDefaultTargetTriple());
2849 bool MachOObjectFile::isValidArch(StringRef ArchFlag
) {
2850 auto validArchs
= getValidArchs();
2851 return llvm::is_contained(validArchs
, ArchFlag
);
2854 ArrayRef
<StringRef
> MachOObjectFile::getValidArchs() {
2855 static const std::array
<StringRef
, 18> ValidArchs
= {{
2879 Triple::ArchType
MachOObjectFile::getArch() const {
2880 return getArch(getCPUType(*this), getCPUSubType(*this));
2883 Triple
MachOObjectFile::getArchTriple(const char **McpuDefault
) const {
2884 return getArchTriple(Header
.cputype
, Header
.cpusubtype
, McpuDefault
);
2887 relocation_iterator
MachOObjectFile::section_rel_begin(unsigned Index
) const {
2890 return section_rel_begin(DRI
);
2893 relocation_iterator
MachOObjectFile::section_rel_end(unsigned Index
) const {
2896 return section_rel_end(DRI
);
2899 dice_iterator
MachOObjectFile::begin_dices() const {
2901 if (!DataInCodeLoadCmd
)
2902 return dice_iterator(DiceRef(DRI
, this));
2904 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2905 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, DicLC
.dataoff
));
2906 return dice_iterator(DiceRef(DRI
, this));
2909 dice_iterator
MachOObjectFile::end_dices() const {
2911 if (!DataInCodeLoadCmd
)
2912 return dice_iterator(DiceRef(DRI
, this));
2914 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2915 unsigned Offset
= DicLC
.dataoff
+ DicLC
.datasize
;
2916 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2917 return dice_iterator(DiceRef(DRI
, this));
2920 ExportEntry::ExportEntry(Error
*E
, const MachOObjectFile
*O
,
2921 ArrayRef
<uint8_t> T
) : E(E
), O(O
), Trie(T
) {}
2923 void ExportEntry::moveToFirst() {
2924 ErrorAsOutParameter
ErrAsOutParam(E
);
2928 pushDownUntilBottom();
2931 void ExportEntry::moveToEnd() {
2936 bool ExportEntry::operator==(const ExportEntry
&Other
) const {
2937 // Common case, one at end, other iterating from begin.
2938 if (Done
|| Other
.Done
)
2939 return (Done
== Other
.Done
);
2940 // Not equal if different stack sizes.
2941 if (Stack
.size() != Other
.Stack
.size())
2943 // Not equal if different cumulative strings.
2944 if (!CumulativeString
.equals(Other
.CumulativeString
))
2946 // Equal if all nodes in both stacks match.
2947 for (unsigned i
=0; i
< Stack
.size(); ++i
) {
2948 if (Stack
[i
].Start
!= Other
.Stack
[i
].Start
)
2954 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr
, const char **error
) {
2956 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Trie
.end(), error
);
2958 if (Ptr
> Trie
.end())
2963 StringRef
ExportEntry::name() const {
2964 return CumulativeString
;
2967 uint64_t ExportEntry::flags() const {
2968 return Stack
.back().Flags
;
2971 uint64_t ExportEntry::address() const {
2972 return Stack
.back().Address
;
2975 uint64_t ExportEntry::other() const {
2976 return Stack
.back().Other
;
2979 StringRef
ExportEntry::otherName() const {
2980 const char* ImportName
= Stack
.back().ImportName
;
2982 return StringRef(ImportName
);
2986 uint32_t ExportEntry::nodeOffset() const {
2987 return Stack
.back().Start
- Trie
.begin();
2990 ExportEntry::NodeState::NodeState(const uint8_t *Ptr
)
2991 : Start(Ptr
), Current(Ptr
) {}
2993 void ExportEntry::pushNode(uint64_t offset
) {
2994 ErrorAsOutParameter
ErrAsOutParam(E
);
2995 const uint8_t *Ptr
= Trie
.begin() + offset
;
2996 NodeState
State(Ptr
);
2997 const char *error
= nullptr;
2998 uint64_t ExportInfoSize
= readULEB128(State
.Current
, &error
);
3000 *E
= malformedError("export info size " + Twine(error
) +
3001 " in export trie data at node: 0x" +
3002 Twine::utohexstr(offset
));
3006 State
.IsExportNode
= (ExportInfoSize
!= 0);
3007 const uint8_t* Children
= State
.Current
+ ExportInfoSize
;
3008 if (Children
> Trie
.end()) {
3009 *E
= malformedError(
3010 "export info size: 0x" + Twine::utohexstr(ExportInfoSize
) +
3011 " in export trie data at node: 0x" + Twine::utohexstr(offset
) +
3012 " too big and extends past end of trie data");
3016 if (State
.IsExportNode
) {
3017 const uint8_t *ExportStart
= State
.Current
;
3018 State
.Flags
= readULEB128(State
.Current
, &error
);
3020 *E
= malformedError("flags " + Twine(error
) +
3021 " in export trie data at node: 0x" +
3022 Twine::utohexstr(offset
));
3026 uint64_t Kind
= State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK
;
3027 if (State
.Flags
!= 0 &&
3028 (Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR
&&
3029 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
&&
3030 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
)) {
3031 *E
= malformedError(
3032 "unsupported exported symbol kind: " + Twine((int)Kind
) +
3033 " in flags: 0x" + Twine::utohexstr(State
.Flags
) +
3034 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
3038 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_REEXPORT
) {
3040 State
.Other
= readULEB128(State
.Current
, &error
); // dylib ordinal
3042 *E
= malformedError("dylib ordinal of re-export " + Twine(error
) +
3043 " in export trie data at node: 0x" +
3044 Twine::utohexstr(offset
));
3049 // Only positive numbers represent library ordinals. Zero and negative
3050 // numbers have special meaning (see BindSpecialDylib).
3051 if ((int64_t)State
.Other
> 0 && State
.Other
> O
->getLibraryCount()) {
3052 *E
= malformedError(
3053 "bad library ordinal: " + Twine((int)State
.Other
) + " (max " +
3054 Twine((int)O
->getLibraryCount()) +
3055 ") in export trie data at node: 0x" + Twine::utohexstr(offset
));
3060 State
.ImportName
= reinterpret_cast<const char*>(State
.Current
);
3061 if (*State
.ImportName
== '\0') {
3064 const uint8_t *End
= State
.Current
+ 1;
3065 if (End
>= Trie
.end()) {
3066 *E
= malformedError("import name of re-export in export trie data at "
3068 Twine::utohexstr(offset
) +
3069 " starts past end of trie data");
3073 while(*End
!= '\0' && End
< Trie
.end())
3076 *E
= malformedError("import name of re-export in export trie data at "
3078 Twine::utohexstr(offset
) +
3079 " extends past end of trie data");
3083 State
.Current
= End
+ 1;
3086 State
.Address
= readULEB128(State
.Current
, &error
);
3088 *E
= malformedError("address " + Twine(error
) +
3089 " in export trie data at node: 0x" +
3090 Twine::utohexstr(offset
));
3094 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
) {
3095 State
.Other
= readULEB128(State
.Current
, &error
);
3097 *E
= malformedError("resolver of stub and resolver " + Twine(error
) +
3098 " in export trie data at node: 0x" +
3099 Twine::utohexstr(offset
));
3105 if (ExportStart
+ ExportInfoSize
< State
.Current
) {
3106 *E
= malformedError(
3107 "inconsistent export info size: 0x" +
3108 Twine::utohexstr(ExportInfoSize
) + " where actual size was: 0x" +
3109 Twine::utohexstr(State
.Current
- ExportStart
) +
3110 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
3115 State
.ChildCount
= *Children
;
3116 if (State
.ChildCount
!= 0 && Children
+ 1 >= Trie
.end()) {
3117 *E
= malformedError("byte for count of childern in export trie data at "
3119 Twine::utohexstr(offset
) +
3120 " extends past end of trie data");
3124 State
.Current
= Children
+ 1;
3125 State
.NextChildIndex
= 0;
3126 State
.ParentStringLength
= CumulativeString
.size();
3127 Stack
.push_back(State
);
3130 void ExportEntry::pushDownUntilBottom() {
3131 ErrorAsOutParameter
ErrAsOutParam(E
);
3132 const char *error
= nullptr;
3133 while (Stack
.back().NextChildIndex
< Stack
.back().ChildCount
) {
3134 NodeState
&Top
= Stack
.back();
3135 CumulativeString
.resize(Top
.ParentStringLength
);
3136 for (;*Top
.Current
!= 0 && Top
.Current
< Trie
.end(); Top
.Current
++) {
3137 char C
= *Top
.Current
;
3138 CumulativeString
.push_back(C
);
3140 if (Top
.Current
>= Trie
.end()) {
3141 *E
= malformedError("edge sub-string in export trie data at node: 0x" +
3142 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
3143 " for child #" + Twine((int)Top
.NextChildIndex
) +
3144 " extends past end of trie data");
3149 uint64_t childNodeIndex
= readULEB128(Top
.Current
, &error
);
3151 *E
= malformedError("child node offset " + Twine(error
) +
3152 " in export trie data at node: 0x" +
3153 Twine::utohexstr(Top
.Start
- Trie
.begin()));
3157 for (const NodeState
&node
: nodes()) {
3158 if (node
.Start
== Trie
.begin() + childNodeIndex
){
3159 *E
= malformedError("loop in childern in export trie data at node: 0x" +
3160 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
3161 " back to node: 0x" +
3162 Twine::utohexstr(childNodeIndex
));
3167 Top
.NextChildIndex
+= 1;
3168 pushNode(childNodeIndex
);
3172 if (!Stack
.back().IsExportNode
) {
3173 *E
= malformedError("node is not an export node in export trie data at "
3175 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3181 // We have a trie data structure and need a way to walk it that is compatible
3182 // with the C++ iterator model. The solution is a non-recursive depth first
3183 // traversal where the iterator contains a stack of parent nodes along with a
3184 // string that is the accumulation of all edge strings along the parent chain
3187 // There is one "export" node for each exported symbol. But because some
3188 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
3189 // node may have child nodes too.
3191 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
3192 // child until hitting a node with no children (which is an export node or
3193 // else the trie is malformed). On the way down, each node is pushed on the
3194 // stack ivar. If there is no more ways down, it pops up one and tries to go
3195 // down a sibling path until a childless node is reached.
3196 void ExportEntry::moveNext() {
3197 assert(!Stack
.empty() && "ExportEntry::moveNext() with empty node stack");
3198 if (!Stack
.back().IsExportNode
) {
3199 *E
= malformedError("node is not an export node in export trie data at "
3201 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3207 while (!Stack
.empty()) {
3208 NodeState
&Top
= Stack
.back();
3209 if (Top
.NextChildIndex
< Top
.ChildCount
) {
3210 pushDownUntilBottom();
3211 // Now at the next export node.
3214 if (Top
.IsExportNode
) {
3215 // This node has no children but is itself an export node.
3216 CumulativeString
.resize(Top
.ParentStringLength
);
3225 iterator_range
<export_iterator
>
3226 MachOObjectFile::exports(Error
&E
, ArrayRef
<uint8_t> Trie
,
3227 const MachOObjectFile
*O
) {
3228 ExportEntry
Start(&E
, O
, Trie
);
3232 Start
.moveToFirst();
3234 ExportEntry
Finish(&E
, O
, Trie
);
3237 return make_range(export_iterator(Start
), export_iterator(Finish
));
3240 iterator_range
<export_iterator
> MachOObjectFile::exports(Error
&Err
) const {
3241 ArrayRef
<uint8_t> Trie
;
3242 if (DyldInfoLoadCmd
)
3243 Trie
= getDyldInfoExportsTrie();
3244 else if (DyldExportsTrieLoadCmd
)
3245 Trie
= getDyldExportsTrie();
3247 return exports(Err
, Trie
, this);
3250 MachOAbstractFixupEntry::MachOAbstractFixupEntry(Error
*E
,
3251 const MachOObjectFile
*O
)
3253 // Cache the vmaddress of __TEXT
3254 for (const auto &Command
: O
->load_commands()) {
3255 if (Command
.C
.cmd
== MachO::LC_SEGMENT
) {
3256 MachO::segment_command SLC
= O
->getSegmentLoadCommand(Command
);
3257 if (StringRef(SLC
.segname
) == "__TEXT") {
3258 TextAddress
= SLC
.vmaddr
;
3261 } else if (Command
.C
.cmd
== MachO::LC_SEGMENT_64
) {
3262 MachO::segment_command_64 SLC_64
= O
->getSegment64LoadCommand(Command
);
3263 if (StringRef(SLC_64
.segname
) == "__TEXT") {
3264 TextAddress
= SLC_64
.vmaddr
;
3271 int32_t MachOAbstractFixupEntry::segmentIndex() const { return SegmentIndex
; }
3273 uint64_t MachOAbstractFixupEntry::segmentOffset() const {
3274 return SegmentOffset
;
3277 uint64_t MachOAbstractFixupEntry::segmentAddress() const {
3278 return O
->BindRebaseAddress(SegmentIndex
, 0);
3281 StringRef
MachOAbstractFixupEntry::segmentName() const {
3282 return O
->BindRebaseSegmentName(SegmentIndex
);
3285 StringRef
MachOAbstractFixupEntry::sectionName() const {
3286 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3289 uint64_t MachOAbstractFixupEntry::address() const {
3290 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3293 StringRef
MachOAbstractFixupEntry::symbolName() const { return SymbolName
; }
3295 int64_t MachOAbstractFixupEntry::addend() const { return Addend
; }
3297 uint32_t MachOAbstractFixupEntry::flags() const { return Flags
; }
3299 int MachOAbstractFixupEntry::ordinal() const { return Ordinal
; }
3301 StringRef
MachOAbstractFixupEntry::typeName() const { return "unknown"; }
3303 void MachOAbstractFixupEntry::moveToFirst() {
3312 void MachOAbstractFixupEntry::moveToEnd() { Done
= true; }
3314 void MachOAbstractFixupEntry::moveNext() {}
3316 MachOChainedFixupEntry::MachOChainedFixupEntry(Error
*E
,
3317 const MachOObjectFile
*O
,
3319 : MachOAbstractFixupEntry(E
, O
) {
3320 ErrorAsOutParameter
e(E
);
3324 if (auto FixupTargetsOrErr
= O
->getDyldChainedFixupTargets()) {
3325 FixupTargets
= *FixupTargetsOrErr
;
3327 *E
= FixupTargetsOrErr
.takeError();
3331 if (auto SegmentsOrErr
= O
->getChainedFixupsSegments()) {
3332 Segments
= std::move(SegmentsOrErr
->second
);
3334 *E
= SegmentsOrErr
.takeError();
3339 void MachOChainedFixupEntry::findNextPageWithFixups() {
3340 auto FindInSegment
= [this]() {
3341 const ChainedFixupsSegment
&SegInfo
= Segments
[InfoSegIndex
];
3342 while (PageIndex
< SegInfo
.PageStarts
.size() &&
3343 SegInfo
.PageStarts
[PageIndex
] == MachO::DYLD_CHAINED_PTR_START_NONE
)
3345 return PageIndex
< SegInfo
.PageStarts
.size();
3348 while (InfoSegIndex
< Segments
.size()) {
3349 if (FindInSegment()) {
3350 PageOffset
= Segments
[InfoSegIndex
].PageStarts
[PageIndex
];
3351 SegmentData
= O
->getSegmentContents(Segments
[InfoSegIndex
].SegIdx
);
3360 void MachOChainedFixupEntry::moveToFirst() {
3361 MachOAbstractFixupEntry::moveToFirst();
3362 if (Segments
.empty()) {
3370 findNextPageWithFixups();
3374 void MachOChainedFixupEntry::moveToEnd() {
3375 MachOAbstractFixupEntry::moveToEnd();
3378 void MachOChainedFixupEntry::moveNext() {
3379 ErrorAsOutParameter
ErrAsOutParam(E
);
3381 if (InfoSegIndex
== Segments
.size()) {
3386 const ChainedFixupsSegment
&SegInfo
= Segments
[InfoSegIndex
];
3387 SegmentIndex
= SegInfo
.SegIdx
;
3388 SegmentOffset
= SegInfo
.Header
.page_size
* PageIndex
+ PageOffset
;
3390 // FIXME: Handle other pointer formats.
3391 uint16_t PointerFormat
= SegInfo
.Header
.pointer_format
;
3392 if (PointerFormat
!= MachO::DYLD_CHAINED_PTR_64
&&
3393 PointerFormat
!= MachO::DYLD_CHAINED_PTR_64_OFFSET
) {
3394 *E
= createError("segment " + Twine(SegmentIndex
) +
3395 " has unsupported chained fixup pointer_format " +
3396 Twine(PointerFormat
));
3407 if (SegmentOffset
+ sizeof(RawValue
) > SegmentData
.size()) {
3408 *E
= malformedError("fixup in segment " + Twine(SegmentIndex
) +
3409 " at offset " + Twine(SegmentOffset
) +
3410 " extends past segment's end");
3415 static_assert(sizeof(RawValue
) == sizeof(MachO::dyld_chained_import_addend
));
3416 memcpy(&RawValue
, SegmentData
.data() + SegmentOffset
, sizeof(RawValue
));
3417 if (O
->isLittleEndian() != sys::IsLittleEndianHost
)
3418 sys::swapByteOrder(RawValue
);
3420 // The bit extraction below assumes little-endian fixup entries.
3421 assert(O
->isLittleEndian() && "big-endian object should have been rejected "
3422 "by getDyldChainedFixupTargets()");
3423 auto Field
= [this](uint8_t Right
, uint8_t Count
) {
3424 return (RawValue
>> Right
) & ((1ULL << Count
) - 1);
3427 // The `bind` field (most significant bit) of the encoded fixup determines
3428 // whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase.
3429 bool IsBind
= Field(63, 1);
3430 Kind
= IsBind
? FixupKind::Bind
: FixupKind::Rebase
;
3431 uint32_t Next
= Field(51, 12);
3433 uint32_t ImportOrdinal
= Field(0, 24);
3434 uint8_t InlineAddend
= Field(24, 8);
3436 if (ImportOrdinal
>= FixupTargets
.size()) {
3437 *E
= malformedError("fixup in segment " + Twine(SegmentIndex
) +
3438 " at offset " + Twine(SegmentOffset
) +
3439 " has out-of range import ordinal " +
3440 Twine(ImportOrdinal
));
3445 ChainedFixupTarget
&Target
= FixupTargets
[ImportOrdinal
];
3446 Ordinal
= Target
.libOrdinal();
3447 Addend
= InlineAddend
? InlineAddend
: Target
.addend();
3448 Flags
= Target
.weakImport() ? MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT
: 0;
3449 SymbolName
= Target
.symbolName();
3451 uint64_t Target
= Field(0, 36);
3452 uint64_t High8
= Field(36, 8);
3454 PointerValue
= Target
| (High8
<< 56);
3455 if (PointerFormat
== MachO::DYLD_CHAINED_PTR_64_OFFSET
)
3456 PointerValue
+= textAddress();
3459 // The stride is 4 bytes for DYLD_CHAINED_PTR_64(_OFFSET).
3461 PageOffset
+= 4 * Next
;
3464 findNextPageWithFixups();
3468 bool MachOChainedFixupEntry::operator==(
3469 const MachOChainedFixupEntry
&Other
) const {
3470 if (Done
&& Other
.Done
)
3472 if (Done
!= Other
.Done
)
3474 return InfoSegIndex
== Other
.InfoSegIndex
&& PageIndex
== Other
.PageIndex
&&
3475 PageOffset
== Other
.PageOffset
;
3478 MachORebaseEntry::MachORebaseEntry(Error
*E
, const MachOObjectFile
*O
,
3479 ArrayRef
<uint8_t> Bytes
, bool is64Bit
)
3480 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3481 PointerSize(is64Bit
? 8 : 4) {}
3483 void MachORebaseEntry::moveToFirst() {
3484 Ptr
= Opcodes
.begin();
3488 void MachORebaseEntry::moveToEnd() {
3489 Ptr
= Opcodes
.end();
3490 RemainingLoopCount
= 0;
3494 void MachORebaseEntry::moveNext() {
3495 ErrorAsOutParameter
ErrAsOutParam(E
);
3496 // If in the middle of some loop, move to next rebasing in loop.
3497 SegmentOffset
+= AdvanceAmount
;
3498 if (RemainingLoopCount
) {
3499 --RemainingLoopCount
;
3505 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3506 // pointer size. Therefore it is possible to reach the end without ever
3507 // having seen REBASE_OPCODE_DONE.
3508 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 uint64_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
;
3844 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3845 // pointer size. Therefore it is possible to reach the end without ever
3846 // having seen BIND_OPCODE_DONE.
3847 if (Ptr
== Opcodes
.end()) {
3852 // Parse next opcode and set up next loop.
3853 const uint8_t *OpcodeStart
= Ptr
;
3854 uint8_t Byte
= *Ptr
++;
3855 uint8_t ImmValue
= Byte
& MachO::BIND_IMMEDIATE_MASK
;
3856 uint8_t Opcode
= Byte
& MachO::BIND_OPCODE_MASK
;
3857 int8_t SignExtended
;
3858 const uint8_t *SymStart
;
3859 uint64_t Count
, Skip
;
3860 const char *error
= nullptr;
3862 case MachO::BIND_OPCODE_DONE
:
3863 if (TableKind
== Kind::Lazy
) {
3864 // Lazying bindings have a DONE opcode between entries. Need to ignore
3865 // it to advance to next entry. But need not if this is last entry.
3866 bool NotLastEntry
= false;
3867 for (const uint8_t *P
= Ptr
; P
< Opcodes
.end(); ++P
) {
3869 NotLastEntry
= true;
3877 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3879 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
:
3880 if (TableKind
== Kind::Weak
) {
3881 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3882 "weak bind table for opcode at: 0x" +
3883 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3888 LibraryOrdinalSet
= true;
3889 if (ImmValue
> O
->getLibraryCount()) {
3890 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3891 "library ordinal: " +
3892 Twine((int)ImmValue
) + " (max " +
3893 Twine((int)O
->getLibraryCount()) +
3894 ") for opcode at: 0x" +
3895 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3901 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3902 << "Ordinal=" << Ordinal
<< "\n");
3904 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
:
3905 if (TableKind
== Kind::Weak
) {
3906 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3907 "weak bind table for opcode at: 0x" +
3908 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3912 Ordinal
= readULEB128(&error
);
3913 LibraryOrdinalSet
= true;
3915 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3916 Twine(error
) + " for opcode at: 0x" +
3917 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3921 if (Ordinal
> (int)O
->getLibraryCount()) {
3922 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3923 "library ordinal: " +
3924 Twine((int)Ordinal
) + " (max " +
3925 Twine((int)O
->getLibraryCount()) +
3926 ") for opcode at: 0x" +
3927 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3933 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3934 << "Ordinal=" << Ordinal
<< "\n");
3936 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
:
3937 if (TableKind
== Kind::Weak
) {
3938 *E
= malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3939 "weak bind table for opcode at: 0x" +
3940 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3945 SignExtended
= MachO::BIND_OPCODE_MASK
| ImmValue
;
3946 Ordinal
= SignExtended
;
3947 if (Ordinal
< MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP
) {
3948 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3949 "special ordinal: " +
3950 Twine((int)Ordinal
) + " for opcode at: 0x" +
3951 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3957 LibraryOrdinalSet
= true;
3960 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3961 << "Ordinal=" << Ordinal
<< "\n");
3963 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
:
3966 while (*Ptr
&& (Ptr
< Opcodes
.end())) {
3969 if (Ptr
== Opcodes
.end()) {
3970 *E
= malformedError(
3971 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3972 "symbol name extends past opcodes for opcode at: 0x" +
3973 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3977 SymbolName
= StringRef(reinterpret_cast<const char*>(SymStart
),
3982 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3983 << "SymbolName=" << SymbolName
<< "\n");
3984 if (TableKind
== Kind::Weak
) {
3985 if (ImmValue
& MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
)
3989 case MachO::BIND_OPCODE_SET_TYPE_IMM
:
3990 BindType
= ImmValue
;
3991 if (ImmValue
> MachO::BIND_TYPE_TEXT_PCREL32
) {
3992 *E
= malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3993 Twine((int)ImmValue
) + " for opcode at: 0x" +
3994 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4000 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
4001 << "BindType=" << (int)BindType
<< "\n");
4003 case MachO::BIND_OPCODE_SET_ADDEND_SLEB
:
4004 Addend
= readSLEB128(&error
);
4006 *E
= malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error
) +
4007 " for opcode at: 0x" +
4008 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4014 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
4015 << "Addend=" << Addend
<< "\n");
4017 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
4018 SegmentIndex
= ImmValue
;
4019 SegmentOffset
= readULEB128(&error
);
4021 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
4022 Twine(error
) + " for opcode at: 0x" +
4023 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4027 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
4030 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
4031 Twine(error
) + " for opcode at: 0x" +
4032 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4038 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
4039 << "SegmentIndex=" << SegmentIndex
<< ", "
4040 << format("SegmentOffset=0x%06X", SegmentOffset
)
4043 case MachO::BIND_OPCODE_ADD_ADDR_ULEB
:
4044 SegmentOffset
+= readULEB128(&error
);
4046 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
4047 " for opcode at: 0x" +
4048 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4052 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
4055 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
4056 " for opcode at: 0x" +
4057 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4061 DEBUG_WITH_TYPE("mach-o-bind",
4062 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
4063 << format("SegmentOffset=0x%06X",
4064 SegmentOffset
) << "\n");
4066 case MachO::BIND_OPCODE_DO_BIND
:
4067 AdvanceAmount
= PointerSize
;
4068 RemainingLoopCount
= 0;
4069 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
4072 *E
= malformedError("for BIND_OPCODE_DO_BIND " + Twine(error
) +
4073 " for opcode at: 0x" +
4074 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4078 if (SymbolName
== StringRef()) {
4079 *E
= malformedError(
4080 "for BIND_OPCODE_DO_BIND missing preceding "
4081 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
4082 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4086 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
4088 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
4089 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
4090 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4094 DEBUG_WITH_TYPE("mach-o-bind",
4095 dbgs() << "BIND_OPCODE_DO_BIND: "
4096 << format("SegmentOffset=0x%06X",
4097 SegmentOffset
) << "\n");
4099 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
:
4100 if (TableKind
== Kind::Lazy
) {
4101 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
4102 "lazy bind table for opcode at: 0x" +
4103 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4107 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
4110 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
4111 Twine(error
) + " for opcode at: 0x" +
4112 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4116 if (SymbolName
== StringRef()) {
4117 *E
= malformedError(
4118 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
4119 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
4121 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4125 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
4126 *E
= malformedError(
4127 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
4128 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
4129 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4133 AdvanceAmount
= readULEB128(&error
) + PointerSize
;
4135 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
4136 Twine(error
) + " for opcode at: 0x" +
4137 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4141 // Note, this is not really an error until the next bind but make no sense
4142 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
4144 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
+
4145 AdvanceAmount
, PointerSize
);
4147 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
4149 Twine(error
) + " for opcode at: 0x" +
4150 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4154 RemainingLoopCount
= 0;
4157 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
4158 << format("SegmentOffset=0x%06X", SegmentOffset
)
4159 << ", AdvanceAmount=" << AdvanceAmount
4160 << ", RemainingLoopCount=" << RemainingLoopCount
4163 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
:
4164 if (TableKind
== Kind::Lazy
) {
4165 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
4166 "allowed in lazy bind table for opcode at: 0x" +
4167 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4171 if (SymbolName
== StringRef()) {
4172 *E
= malformedError(
4173 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
4174 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
4176 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4180 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
4181 *E
= malformedError(
4182 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
4183 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
4185 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4189 AdvanceAmount
= ImmValue
* PointerSize
+ PointerSize
;
4190 RemainingLoopCount
= 0;
4191 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
+
4192 AdvanceAmount
, PointerSize
);
4194 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
4195 Twine(error
) + " for opcode at: 0x" +
4196 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4200 DEBUG_WITH_TYPE("mach-o-bind",
4202 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
4203 << format("SegmentOffset=0x%06X", SegmentOffset
) << "\n");
4205 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
:
4206 if (TableKind
== Kind::Lazy
) {
4207 *E
= malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
4208 "allowed in lazy bind table for opcode at: 0x" +
4209 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4213 Count
= readULEB128(&error
);
4215 RemainingLoopCount
= Count
- 1;
4217 RemainingLoopCount
= 0;
4219 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4221 Twine(error
) + " for opcode at: 0x" +
4222 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4226 Skip
= readULEB128(&error
);
4227 AdvanceAmount
= Skip
+ PointerSize
;
4229 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4231 Twine(error
) + " for opcode at: 0x" +
4232 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4236 if (SymbolName
== StringRef()) {
4237 *E
= malformedError(
4238 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4239 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
4241 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4245 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
4246 *E
= malformedError(
4247 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4248 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
4250 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4254 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
4255 PointerSize
, Count
, Skip
);
4258 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
4259 Twine(error
) + " for opcode at: 0x" +
4260 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4266 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
4267 << format("SegmentOffset=0x%06X", SegmentOffset
)
4268 << ", AdvanceAmount=" << AdvanceAmount
4269 << ", RemainingLoopCount=" << RemainingLoopCount
4273 *E
= malformedError("bad bind info (bad opcode value 0x" +
4274 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
4275 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
4282 uint64_t MachOBindEntry::readULEB128(const char **error
) {
4284 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
4286 if (Ptr
> Opcodes
.end())
4287 Ptr
= Opcodes
.end();
4291 int64_t MachOBindEntry::readSLEB128(const char **error
) {
4293 int64_t Result
= decodeSLEB128(Ptr
, &Count
, Opcodes
.end(), error
);
4295 if (Ptr
> Opcodes
.end())
4296 Ptr
= Opcodes
.end();
4300 int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex
; }
4302 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset
; }
4304 StringRef
MachOBindEntry::typeName() const {
4306 case MachO::BIND_TYPE_POINTER
:
4308 case MachO::BIND_TYPE_TEXT_ABSOLUTE32
:
4309 return "text abs32";
4310 case MachO::BIND_TYPE_TEXT_PCREL32
:
4311 return "text rel32";
4316 StringRef
MachOBindEntry::symbolName() const { return SymbolName
; }
4318 int64_t MachOBindEntry::addend() const { return Addend
; }
4320 uint32_t MachOBindEntry::flags() const { return Flags
; }
4322 int MachOBindEntry::ordinal() const { return Ordinal
; }
4324 // For use with the SegIndex of a checked Mach-O Bind entry
4325 // to get the segment name.
4326 StringRef
MachOBindEntry::segmentName() const {
4327 return O
->BindRebaseSegmentName(SegmentIndex
);
4330 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
4331 // to get the section name.
4332 StringRef
MachOBindEntry::sectionName() const {
4333 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
4336 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
4337 // to get the address.
4338 uint64_t MachOBindEntry::address() const {
4339 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
4342 bool MachOBindEntry::operator==(const MachOBindEntry
&Other
) const {
4343 #ifdef EXPENSIVE_CHECKS
4344 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
4346 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
4348 return (Ptr
== Other
.Ptr
) &&
4349 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
4350 (Done
== Other
.Done
);
4353 // Build table of sections so SegIndex/SegOffset pairs can be translated.
4354 BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile
*Obj
) {
4355 uint32_t CurSegIndex
= Obj
->hasPageZeroSegment() ? 1 : 0;
4356 StringRef CurSegName
;
4357 uint64_t CurSegAddress
;
4358 for (const SectionRef
&Section
: Obj
->sections()) {
4360 Expected
<StringRef
> NameOrErr
= Section
.getName();
4362 consumeError(NameOrErr
.takeError());
4364 Info
.SectionName
= *NameOrErr
;
4365 Info
.Address
= Section
.getAddress();
4366 Info
.Size
= Section
.getSize();
4368 Obj
->getSectionFinalSegmentName(Section
.getRawDataRefImpl());
4369 if (Info
.SegmentName
!= CurSegName
) {
4371 CurSegName
= Info
.SegmentName
;
4372 CurSegAddress
= Info
.Address
;
4374 Info
.SegmentIndex
= CurSegIndex
- 1;
4375 Info
.OffsetInSegment
= Info
.Address
- CurSegAddress
;
4376 Info
.SegmentStartAddress
= CurSegAddress
;
4377 Sections
.push_back(Info
);
4379 MaxSegIndex
= CurSegIndex
;
4382 // For use with a SegIndex, SegOffset, and PointerSize triple in
4383 // MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
4385 // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
4386 // that fully contains a pointer at that location. Multiple fixups in a bind
4387 // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
4388 // be tested via the Count and Skip parameters.
4389 const char *BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex
,
4391 uint8_t PointerSize
,
4395 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4396 if (SegIndex
>= MaxSegIndex
)
4397 return "bad segIndex (too large)";
4398 for (uint64_t i
= 0; i
< Count
; ++i
) {
4399 uint64_t Start
= SegOffset
+ i
* (PointerSize
+ Skip
);
4400 uint64_t End
= Start
+ PointerSize
;
4402 for (const SectionInfo
&SI
: Sections
) {
4403 if (SI
.SegmentIndex
!= SegIndex
)
4405 if ((SI
.OffsetInSegment
<=Start
) && (Start
<(SI
.OffsetInSegment
+SI
.Size
))) {
4406 if (End
<= SI
.OffsetInSegment
+ SI
.Size
) {
4411 return "bad offset, extends beyond section boundary";
4415 return "bad offset, not in section";
4420 // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4421 // to get the segment name.
4422 StringRef
BindRebaseSegInfo::segmentName(int32_t SegIndex
) {
4423 for (const SectionInfo
&SI
: Sections
) {
4424 if (SI
.SegmentIndex
== SegIndex
)
4425 return SI
.SegmentName
;
4427 llvm_unreachable("invalid SegIndex");
4430 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4431 // to get the SectionInfo.
4432 const BindRebaseSegInfo::SectionInfo
&BindRebaseSegInfo::findSection(
4433 int32_t SegIndex
, uint64_t SegOffset
) {
4434 for (const SectionInfo
&SI
: Sections
) {
4435 if (SI
.SegmentIndex
!= SegIndex
)
4437 if (SI
.OffsetInSegment
> SegOffset
)
4439 if (SegOffset
>= (SI
.OffsetInSegment
+ SI
.Size
))
4443 llvm_unreachable("SegIndex and SegOffset not in any section");
4446 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4447 // entry to get the section name.
4448 StringRef
BindRebaseSegInfo::sectionName(int32_t SegIndex
,
4449 uint64_t SegOffset
) {
4450 return findSection(SegIndex
, SegOffset
).SectionName
;
4453 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4454 // entry to get the address.
4455 uint64_t BindRebaseSegInfo::address(uint32_t SegIndex
, uint64_t OffsetInSeg
) {
4456 const SectionInfo
&SI
= findSection(SegIndex
, OffsetInSeg
);
4457 return SI
.SegmentStartAddress
+ OffsetInSeg
;
4460 iterator_range
<bind_iterator
>
4461 MachOObjectFile::bindTable(Error
&Err
, MachOObjectFile
*O
,
4462 ArrayRef
<uint8_t> Opcodes
, bool is64
,
4463 MachOBindEntry::Kind BKind
) {
4464 if (O
->BindRebaseSectionTable
== nullptr)
4465 O
->BindRebaseSectionTable
= std::make_unique
<BindRebaseSegInfo
>(O
);
4466 MachOBindEntry
Start(&Err
, O
, Opcodes
, is64
, BKind
);
4467 Start
.moveToFirst();
4469 MachOBindEntry
Finish(&Err
, O
, Opcodes
, is64
, BKind
);
4472 return make_range(bind_iterator(Start
), bind_iterator(Finish
));
4475 iterator_range
<bind_iterator
> MachOObjectFile::bindTable(Error
&Err
) {
4476 return bindTable(Err
, this, getDyldInfoBindOpcodes(), is64Bit(),
4477 MachOBindEntry::Kind::Regular
);
4480 iterator_range
<bind_iterator
> MachOObjectFile::lazyBindTable(Error
&Err
) {
4481 return bindTable(Err
, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4482 MachOBindEntry::Kind::Lazy
);
4485 iterator_range
<bind_iterator
> MachOObjectFile::weakBindTable(Error
&Err
) {
4486 return bindTable(Err
, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
4487 MachOBindEntry::Kind::Weak
);
4490 iterator_range
<fixup_iterator
> MachOObjectFile::fixupTable(Error
&Err
) {
4491 if (BindRebaseSectionTable
== nullptr)
4492 BindRebaseSectionTable
= std::make_unique
<BindRebaseSegInfo
>(this);
4494 MachOChainedFixupEntry
Start(&Err
, this, true);
4495 Start
.moveToFirst();
4497 MachOChainedFixupEntry
Finish(&Err
, this, false);
4500 return make_range(fixup_iterator(Start
), fixup_iterator(Finish
));
4503 MachOObjectFile::load_command_iterator
4504 MachOObjectFile::begin_load_commands() const {
4505 return LoadCommands
.begin();
4508 MachOObjectFile::load_command_iterator
4509 MachOObjectFile::end_load_commands() const {
4510 return LoadCommands
.end();
4513 iterator_range
<MachOObjectFile::load_command_iterator
>
4514 MachOObjectFile::load_commands() const {
4515 return make_range(begin_load_commands(), end_load_commands());
4519 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec
) const {
4520 ArrayRef
<char> Raw
= getSectionRawFinalSegmentName(Sec
);
4521 return parseSegmentOrSectionName(Raw
.data());
4525 MachOObjectFile::getSectionRawName(DataRefImpl Sec
) const {
4526 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4527 const section_base
*Base
=
4528 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4529 return ArrayRef(Base
->sectname
);
4533 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec
) const {
4534 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4535 const section_base
*Base
=
4536 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4537 return ArrayRef(Base
->segname
);
4541 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info
&RE
)
4543 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64
)
4545 return getPlainRelocationAddress(RE
) & MachO::R_SCATTERED
;
4548 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4549 const MachO::any_relocation_info
&RE
) const {
4550 if (isLittleEndian())
4551 return RE
.r_word1
& 0xffffff;
4552 return RE
.r_word1
>> 8;
4555 bool MachOObjectFile::getPlainRelocationExternal(
4556 const MachO::any_relocation_info
&RE
) const {
4557 if (isLittleEndian())
4558 return (RE
.r_word1
>> 27) & 1;
4559 return (RE
.r_word1
>> 4) & 1;
4562 bool MachOObjectFile::getScatteredRelocationScattered(
4563 const MachO::any_relocation_info
&RE
) const {
4564 return RE
.r_word0
>> 31;
4567 uint32_t MachOObjectFile::getScatteredRelocationValue(
4568 const MachO::any_relocation_info
&RE
) const {
4572 uint32_t MachOObjectFile::getScatteredRelocationType(
4573 const MachO::any_relocation_info
&RE
) const {
4574 return (RE
.r_word0
>> 24) & 0xf;
4577 unsigned MachOObjectFile::getAnyRelocationAddress(
4578 const MachO::any_relocation_info
&RE
) const {
4579 if (isRelocationScattered(RE
))
4580 return getScatteredRelocationAddress(RE
);
4581 return getPlainRelocationAddress(RE
);
4584 unsigned MachOObjectFile::getAnyRelocationPCRel(
4585 const MachO::any_relocation_info
&RE
) const {
4586 if (isRelocationScattered(RE
))
4587 return getScatteredRelocationPCRel(RE
);
4588 return getPlainRelocationPCRel(*this, RE
);
4591 unsigned MachOObjectFile::getAnyRelocationLength(
4592 const MachO::any_relocation_info
&RE
) const {
4593 if (isRelocationScattered(RE
))
4594 return getScatteredRelocationLength(RE
);
4595 return getPlainRelocationLength(*this, RE
);
4599 MachOObjectFile::getAnyRelocationType(
4600 const MachO::any_relocation_info
&RE
) const {
4601 if (isRelocationScattered(RE
))
4602 return getScatteredRelocationType(RE
);
4603 return getPlainRelocationType(*this, RE
);
4607 MachOObjectFile::getAnyRelocationSection(
4608 const MachO::any_relocation_info
&RE
) const {
4609 if (isRelocationScattered(RE
) || getPlainRelocationExternal(RE
))
4610 return *section_end();
4611 unsigned SecNum
= getPlainRelocationSymbolNum(RE
);
4612 if (SecNum
== MachO::R_ABS
|| SecNum
> Sections
.size())
4613 return *section_end();
4615 DRI
.d
.a
= SecNum
- 1;
4616 return SectionRef(DRI
, this);
4619 MachO::section
MachOObjectFile::getSection(DataRefImpl DRI
) const {
4620 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4621 return getStruct
<MachO::section
>(*this, Sections
[DRI
.d
.a
]);
4624 MachO::section_64
MachOObjectFile::getSection64(DataRefImpl DRI
) const {
4625 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4626 return getStruct
<MachO::section_64
>(*this, Sections
[DRI
.d
.a
]);
4629 MachO::section
MachOObjectFile::getSection(const LoadCommandInfo
&L
,
4630 unsigned Index
) const {
4631 const char *Sec
= getSectionPtr(*this, L
, Index
);
4632 return getStruct
<MachO::section
>(*this, Sec
);
4635 MachO::section_64
MachOObjectFile::getSection64(const LoadCommandInfo
&L
,
4636 unsigned Index
) const {
4637 const char *Sec
= getSectionPtr(*this, L
, Index
);
4638 return getStruct
<MachO::section_64
>(*this, Sec
);
4642 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI
) const {
4643 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4644 return getStruct
<MachO::nlist
>(*this, P
);
4648 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI
) const {
4649 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4650 return getStruct
<MachO::nlist_64
>(*this, P
);
4653 MachO::linkedit_data_command
4654 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo
&L
) const {
4655 return getStruct
<MachO::linkedit_data_command
>(*this, L
.Ptr
);
4658 MachO::segment_command
4659 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo
&L
) const {
4660 return getStruct
<MachO::segment_command
>(*this, L
.Ptr
);
4663 MachO::segment_command_64
4664 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo
&L
) const {
4665 return getStruct
<MachO::segment_command_64
>(*this, L
.Ptr
);
4668 MachO::linker_option_command
4669 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo
&L
) const {
4670 return getStruct
<MachO::linker_option_command
>(*this, L
.Ptr
);
4673 MachO::version_min_command
4674 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo
&L
) const {
4675 return getStruct
<MachO::version_min_command
>(*this, L
.Ptr
);
4679 MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo
&L
) const {
4680 return getStruct
<MachO::note_command
>(*this, L
.Ptr
);
4683 MachO::build_version_command
4684 MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo
&L
) const {
4685 return getStruct
<MachO::build_version_command
>(*this, L
.Ptr
);
4688 MachO::build_tool_version
4689 MachOObjectFile::getBuildToolVersion(unsigned index
) const {
4690 return getStruct
<MachO::build_tool_version
>(*this, BuildTools
[index
]);
4693 MachO::dylib_command
4694 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo
&L
) const {
4695 return getStruct
<MachO::dylib_command
>(*this, L
.Ptr
);
4698 MachO::dyld_info_command
4699 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo
&L
) const {
4700 return getStruct
<MachO::dyld_info_command
>(*this, L
.Ptr
);
4703 MachO::dylinker_command
4704 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo
&L
) const {
4705 return getStruct
<MachO::dylinker_command
>(*this, L
.Ptr
);
4709 MachOObjectFile::getUuidCommand(const LoadCommandInfo
&L
) const {
4710 return getStruct
<MachO::uuid_command
>(*this, L
.Ptr
);
4713 MachO::rpath_command
4714 MachOObjectFile::getRpathCommand(const LoadCommandInfo
&L
) const {
4715 return getStruct
<MachO::rpath_command
>(*this, L
.Ptr
);
4718 MachO::source_version_command
4719 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo
&L
) const {
4720 return getStruct
<MachO::source_version_command
>(*this, L
.Ptr
);
4723 MachO::entry_point_command
4724 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo
&L
) const {
4725 return getStruct
<MachO::entry_point_command
>(*this, L
.Ptr
);
4728 MachO::encryption_info_command
4729 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo
&L
) const {
4730 return getStruct
<MachO::encryption_info_command
>(*this, L
.Ptr
);
4733 MachO::encryption_info_command_64
4734 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo
&L
) const {
4735 return getStruct
<MachO::encryption_info_command_64
>(*this, L
.Ptr
);
4738 MachO::sub_framework_command
4739 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo
&L
) const {
4740 return getStruct
<MachO::sub_framework_command
>(*this, L
.Ptr
);
4743 MachO::sub_umbrella_command
4744 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo
&L
) const {
4745 return getStruct
<MachO::sub_umbrella_command
>(*this, L
.Ptr
);
4748 MachO::sub_library_command
4749 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo
&L
) const {
4750 return getStruct
<MachO::sub_library_command
>(*this, L
.Ptr
);
4753 MachO::sub_client_command
4754 MachOObjectFile::getSubClientCommand(const LoadCommandInfo
&L
) const {
4755 return getStruct
<MachO::sub_client_command
>(*this, L
.Ptr
);
4758 MachO::routines_command
4759 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo
&L
) const {
4760 return getStruct
<MachO::routines_command
>(*this, L
.Ptr
);
4763 MachO::routines_command_64
4764 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo
&L
) const {
4765 return getStruct
<MachO::routines_command_64
>(*this, L
.Ptr
);
4768 MachO::thread_command
4769 MachOObjectFile::getThreadCommand(const LoadCommandInfo
&L
) const {
4770 return getStruct
<MachO::thread_command
>(*this, L
.Ptr
);
4773 MachO::fileset_entry_command
4774 MachOObjectFile::getFilesetEntryLoadCommand(const LoadCommandInfo
&L
) const {
4775 return getStruct
<MachO::fileset_entry_command
>(*this, L
.Ptr
);
4778 MachO::any_relocation_info
4779 MachOObjectFile::getRelocation(DataRefImpl Rel
) const {
4781 if (getHeader().filetype
== MachO::MH_OBJECT
) {
4785 MachO::section_64 Sect
= getSection64(Sec
);
4786 Offset
= Sect
.reloff
;
4788 MachO::section Sect
= getSection(Sec
);
4789 Offset
= Sect
.reloff
;
4792 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
4794 Offset
= DysymtabLoadCmd
.extreloff
; // Offset to the external relocations
4796 Offset
= DysymtabLoadCmd
.locreloff
; // Offset to the local relocations
4799 auto P
= reinterpret_cast<const MachO::any_relocation_info
*>(
4800 getPtr(*this, Offset
)) + Rel
.d
.b
;
4801 return getStruct
<MachO::any_relocation_info
>(
4802 *this, reinterpret_cast<const char *>(P
));
4805 MachO::data_in_code_entry
4806 MachOObjectFile::getDice(DataRefImpl Rel
) const {
4807 const char *P
= reinterpret_cast<const char *>(Rel
.p
);
4808 return getStruct
<MachO::data_in_code_entry
>(*this, P
);
4811 const MachO::mach_header
&MachOObjectFile::getHeader() const {
4815 const MachO::mach_header_64
&MachOObjectFile::getHeader64() const {
4820 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4821 const MachO::dysymtab_command
&DLC
,
4822 unsigned Index
) const {
4823 uint64_t Offset
= DLC
.indirectsymoff
+ Index
* sizeof(uint32_t);
4824 return getStruct
<uint32_t>(*this, getPtr(*this, Offset
));
4827 MachO::data_in_code_entry
4828 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset
,
4829 unsigned Index
) const {
4830 uint64_t Offset
= DataOffset
+ Index
* sizeof(MachO::data_in_code_entry
);
4831 return getStruct
<MachO::data_in_code_entry
>(*this, getPtr(*this, Offset
));
4834 MachO::symtab_command
MachOObjectFile::getSymtabLoadCommand() const {
4836 return getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
4838 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4839 MachO::symtab_command Cmd
;
4840 Cmd
.cmd
= MachO::LC_SYMTAB
;
4841 Cmd
.cmdsize
= sizeof(MachO::symtab_command
);
4849 MachO::dysymtab_command
MachOObjectFile::getDysymtabLoadCommand() const {
4850 if (DysymtabLoadCmd
)
4851 return getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
4853 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4854 MachO::dysymtab_command Cmd
;
4855 Cmd
.cmd
= MachO::LC_DYSYMTAB
;
4856 Cmd
.cmdsize
= sizeof(MachO::dysymtab_command
);
4867 Cmd
.extrefsymoff
= 0;
4868 Cmd
.nextrefsyms
= 0;
4869 Cmd
.indirectsymoff
= 0;
4870 Cmd
.nindirectsyms
= 0;
4878 MachO::linkedit_data_command
4879 MachOObjectFile::getDataInCodeLoadCommand() const {
4880 if (DataInCodeLoadCmd
)
4881 return getStruct
<MachO::linkedit_data_command
>(*this, DataInCodeLoadCmd
);
4883 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4884 MachO::linkedit_data_command Cmd
;
4885 Cmd
.cmd
= MachO::LC_DATA_IN_CODE
;
4886 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4892 MachO::linkedit_data_command
4893 MachOObjectFile::getLinkOptHintsLoadCommand() const {
4894 if (LinkOptHintsLoadCmd
)
4895 return getStruct
<MachO::linkedit_data_command
>(*this, LinkOptHintsLoadCmd
);
4897 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4899 MachO::linkedit_data_command Cmd
;
4900 Cmd
.cmd
= MachO::LC_LINKER_OPTIMIZATION_HINT
;
4901 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4907 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4908 if (!DyldInfoLoadCmd
)
4911 auto DyldInfoOrErr
=
4912 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4915 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4916 const uint8_t *Ptr
=
4917 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.rebase_off
));
4918 return ArrayRef(Ptr
, DyldInfo
.rebase_size
);
4921 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4922 if (!DyldInfoLoadCmd
)
4925 auto DyldInfoOrErr
=
4926 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4929 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4930 const uint8_t *Ptr
=
4931 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.bind_off
));
4932 return ArrayRef(Ptr
, DyldInfo
.bind_size
);
4935 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4936 if (!DyldInfoLoadCmd
)
4939 auto DyldInfoOrErr
=
4940 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4943 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4944 const uint8_t *Ptr
=
4945 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.weak_bind_off
));
4946 return ArrayRef(Ptr
, DyldInfo
.weak_bind_size
);
4949 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4950 if (!DyldInfoLoadCmd
)
4953 auto DyldInfoOrErr
=
4954 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4957 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4958 const uint8_t *Ptr
=
4959 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.lazy_bind_off
));
4960 return ArrayRef(Ptr
, DyldInfo
.lazy_bind_size
);
4963 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4964 if (!DyldInfoLoadCmd
)
4967 auto DyldInfoOrErr
=
4968 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4971 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4972 const uint8_t *Ptr
=
4973 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.export_off
));
4974 return ArrayRef(Ptr
, DyldInfo
.export_size
);
4977 Expected
<std::optional
<MachO::linkedit_data_command
>>
4978 MachOObjectFile::getChainedFixupsLoadCommand() const {
4979 // Load the dyld chained fixups load command.
4980 if (!DyldChainedFixupsLoadCmd
)
4981 return std::nullopt
;
4982 auto DyldChainedFixupsOrErr
= getStructOrErr
<MachO::linkedit_data_command
>(
4983 *this, DyldChainedFixupsLoadCmd
);
4984 if (!DyldChainedFixupsOrErr
)
4985 return DyldChainedFixupsOrErr
.takeError();
4986 const MachO::linkedit_data_command
&DyldChainedFixups
=
4987 *DyldChainedFixupsOrErr
;
4989 // If the load command is present but the data offset has been zeroed out,
4990 // as is the case for dylib stubs, return std::nullopt (no error).
4991 if (!DyldChainedFixups
.dataoff
)
4992 return std::nullopt
;
4993 return DyldChainedFixups
;
4996 Expected
<std::optional
<MachO::dyld_chained_fixups_header
>>
4997 MachOObjectFile::getChainedFixupsHeader() const {
4998 auto CFOrErr
= getChainedFixupsLoadCommand();
5000 return CFOrErr
.takeError();
5001 if (!CFOrErr
->has_value())
5002 return std::nullopt
;
5004 const MachO::linkedit_data_command
&DyldChainedFixups
= **CFOrErr
;
5006 uint64_t CFHeaderOffset
= DyldChainedFixups
.dataoff
;
5007 uint64_t CFSize
= DyldChainedFixups
.datasize
;
5009 // Load the dyld chained fixups header.
5010 const char *CFHeaderPtr
= getPtr(*this, CFHeaderOffset
);
5011 auto CFHeaderOrErr
=
5012 getStructOrErr
<MachO::dyld_chained_fixups_header
>(*this, CFHeaderPtr
);
5014 return CFHeaderOrErr
.takeError();
5015 MachO::dyld_chained_fixups_header CFHeader
= CFHeaderOrErr
.get();
5017 // Reject unknown chained fixup formats.
5018 if (CFHeader
.fixups_version
!= 0)
5019 return malformedError(Twine("bad chained fixups: unknown version: ") +
5020 Twine(CFHeader
.fixups_version
));
5021 if (CFHeader
.imports_format
< 1 || CFHeader
.imports_format
> 3)
5022 return malformedError(
5023 Twine("bad chained fixups: unknown imports format: ") +
5024 Twine(CFHeader
.imports_format
));
5026 // Validate the image format.
5028 // Load the image starts.
5029 uint64_t CFImageStartsOffset
= (CFHeaderOffset
+ CFHeader
.starts_offset
);
5030 if (CFHeader
.starts_offset
< sizeof(MachO::dyld_chained_fixups_header
)) {
5031 return malformedError(Twine("bad chained fixups: image starts offset ") +
5032 Twine(CFHeader
.starts_offset
) +
5033 " overlaps with chained fixups header");
5035 uint32_t EndOffset
= CFHeaderOffset
+ CFSize
;
5036 if (CFImageStartsOffset
+ sizeof(MachO::dyld_chained_starts_in_image
) >
5038 return malformedError(Twine("bad chained fixups: image starts end ") +
5039 Twine(CFImageStartsOffset
+
5040 sizeof(MachO::dyld_chained_starts_in_image
)) +
5041 " extends past end " + Twine(EndOffset
));
5047 Expected
<std::pair
<size_t, std::vector
<ChainedFixupsSegment
>>>
5048 MachOObjectFile::getChainedFixupsSegments() const {
5049 auto CFOrErr
= getChainedFixupsLoadCommand();
5051 return CFOrErr
.takeError();
5053 std::vector
<ChainedFixupsSegment
> Segments
;
5054 if (!CFOrErr
->has_value())
5055 return std::make_pair(0, Segments
);
5057 const MachO::linkedit_data_command
&DyldChainedFixups
= **CFOrErr
;
5059 auto HeaderOrErr
= getChainedFixupsHeader();
5061 return HeaderOrErr
.takeError();
5062 if (!HeaderOrErr
->has_value())
5063 return std::make_pair(0, Segments
);
5064 const MachO::dyld_chained_fixups_header
&Header
= **HeaderOrErr
;
5066 const char *Contents
= getPtr(*this, DyldChainedFixups
.dataoff
);
5068 auto ImageStartsOrErr
= getStructOrErr
<MachO::dyld_chained_starts_in_image
>(
5069 *this, Contents
+ Header
.starts_offset
);
5070 if (!ImageStartsOrErr
)
5071 return ImageStartsOrErr
.takeError();
5072 const MachO::dyld_chained_starts_in_image
&ImageStarts
= *ImageStartsOrErr
;
5074 const char *SegOffsPtr
=
5075 Contents
+ Header
.starts_offset
+
5076 offsetof(MachO::dyld_chained_starts_in_image
, seg_info_offset
);
5077 const char *SegOffsEnd
=
5078 SegOffsPtr
+ ImageStarts
.seg_count
* sizeof(uint32_t);
5079 if (SegOffsEnd
> Contents
+ DyldChainedFixups
.datasize
)
5080 return malformedError(
5081 "bad chained fixups: seg_info_offset extends past end");
5083 const char *LastSegEnd
= nullptr;
5084 for (size_t I
= 0, N
= ImageStarts
.seg_count
; I
< N
; ++I
) {
5086 getStructOrErr
<uint32_t>(*this, SegOffsPtr
+ I
* sizeof(uint32_t));
5088 return OffOrErr
.takeError();
5089 // seg_info_offset == 0 means there is no associated starts_in_segment
5094 auto Fail
= [&](Twine Message
) {
5095 return malformedError("bad chained fixups: segment info" + Twine(I
) +
5096 " at offset " + Twine(*OffOrErr
) + Message
);
5099 const char *SegPtr
= Contents
+ Header
.starts_offset
+ *OffOrErr
;
5100 if (LastSegEnd
&& SegPtr
< LastSegEnd
)
5101 return Fail(" overlaps with previous segment info");
5104 getStructOrErr
<MachO::dyld_chained_starts_in_segment
>(*this, SegPtr
);
5106 return SegOrErr
.takeError();
5107 const MachO::dyld_chained_starts_in_segment
&Seg
= *SegOrErr
;
5109 LastSegEnd
= SegPtr
+ Seg
.size
;
5110 if (Seg
.pointer_format
< 1 || Seg
.pointer_format
> 12)
5111 return Fail(" has unknown pointer format: " + Twine(Seg
.pointer_format
));
5113 const char *PageStart
=
5114 SegPtr
+ offsetof(MachO::dyld_chained_starts_in_segment
, page_start
);
5115 const char *PageEnd
= PageStart
+ Seg
.page_count
* sizeof(uint16_t);
5116 if (PageEnd
> SegPtr
+ Seg
.size
)
5117 return Fail(" : page_starts extend past seg_info size");
5119 // FIXME: This does not account for multiple offsets on a single page
5120 // (DYLD_CHAINED_PTR_START_MULTI; 32-bit only).
5121 std::vector
<uint16_t> PageStarts
;
5122 for (size_t PageIdx
= 0; PageIdx
< Seg
.page_count
; ++PageIdx
) {
5124 memcpy(&Start
, PageStart
+ PageIdx
* sizeof(uint16_t), sizeof(uint16_t));
5125 if (isLittleEndian() != sys::IsLittleEndianHost
)
5126 sys::swapByteOrder(Start
);
5127 PageStarts
.push_back(Start
);
5130 Segments
.emplace_back(I
, *OffOrErr
, Seg
, std::move(PageStarts
));
5133 return std::make_pair(ImageStarts
.seg_count
, Segments
);
5136 // The special library ordinals have a negative value, but they are encoded in
5137 // an unsigned bitfield, so we need to sign extend the value.
5138 template <typename T
> static int getEncodedOrdinal(T Value
) {
5139 if (Value
== static_cast<T
>(MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE
) ||
5140 Value
== static_cast<T
>(MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP
) ||
5141 Value
== static_cast<T
>(MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP
))
5142 return SignExtend32
<sizeof(T
) * CHAR_BIT
>(Value
);
5146 template <typename T
, unsigned N
>
5147 static std::array
<T
, N
> getArray(const MachOObjectFile
&O
, const void *Ptr
) {
5148 std::array
<T
, N
> RawValue
;
5149 memcpy(RawValue
.data(), Ptr
, N
* sizeof(T
));
5150 if (O
.isLittleEndian() != sys::IsLittleEndianHost
)
5151 for (auto &Element
: RawValue
)
5152 sys::swapByteOrder(Element
);
5156 Expected
<std::vector
<ChainedFixupTarget
>>
5157 MachOObjectFile::getDyldChainedFixupTargets() const {
5158 auto CFOrErr
= getChainedFixupsLoadCommand();
5160 return CFOrErr
.takeError();
5162 std::vector
<ChainedFixupTarget
> Targets
;
5163 if (!CFOrErr
->has_value())
5166 const MachO::linkedit_data_command
&DyldChainedFixups
= **CFOrErr
;
5168 auto CFHeaderOrErr
= getChainedFixupsHeader();
5170 return CFHeaderOrErr
.takeError();
5171 if (!(*CFHeaderOrErr
))
5173 const MachO::dyld_chained_fixups_header
&Header
= **CFHeaderOrErr
;
5175 size_t ImportSize
= 0;
5176 if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT
)
5177 ImportSize
= sizeof(MachO::dyld_chained_import
);
5178 else if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT_ADDEND
)
5179 ImportSize
= sizeof(MachO::dyld_chained_import_addend
);
5180 else if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT_ADDEND64
)
5181 ImportSize
= sizeof(MachO::dyld_chained_import_addend64
);
5183 return malformedError("bad chained fixups: unknown imports format: " +
5184 Twine(Header
.imports_format
));
5186 const char *Contents
= getPtr(*this, DyldChainedFixups
.dataoff
);
5187 const char *Imports
= Contents
+ Header
.imports_offset
;
5188 size_t ImportsEndOffset
=
5189 Header
.imports_offset
+ ImportSize
* Header
.imports_count
;
5190 const char *ImportsEnd
= Contents
+ ImportsEndOffset
;
5191 const char *Symbols
= Contents
+ Header
.symbols_offset
;
5192 const char *SymbolsEnd
= Contents
+ DyldChainedFixups
.datasize
;
5194 if (ImportsEnd
> Symbols
)
5195 return malformedError("bad chained fixups: imports end " +
5196 Twine(ImportsEndOffset
) + " overlaps with symbols");
5198 // We use bit manipulation to extract data from the bitfields. This is correct
5199 // for both LE and BE hosts, but we assume that the object is little-endian.
5200 if (!isLittleEndian())
5201 return createError("parsing big-endian chained fixups is not implemented");
5202 for (const char *ImportPtr
= Imports
; ImportPtr
< ImportsEnd
;
5203 ImportPtr
+= ImportSize
) {
5206 uint32_t NameOffset
;
5208 if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT
) {
5209 static_assert(sizeof(uint32_t) == sizeof(MachO::dyld_chained_import
));
5210 auto RawValue
= getArray
<uint32_t, 1>(*this, ImportPtr
);
5212 LibOrdinal
= getEncodedOrdinal
<uint8_t>(RawValue
[0] & 0xFF);
5213 WeakImport
= (RawValue
[0] >> 8) & 1;
5214 NameOffset
= RawValue
[0] >> 9;
5216 } else if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT_ADDEND
) {
5217 static_assert(sizeof(uint64_t) ==
5218 sizeof(MachO::dyld_chained_import_addend
));
5219 auto RawValue
= getArray
<uint32_t, 2>(*this, ImportPtr
);
5221 LibOrdinal
= getEncodedOrdinal
<uint8_t>(RawValue
[0] & 0xFF);
5222 WeakImport
= (RawValue
[0] >> 8) & 1;
5223 NameOffset
= RawValue
[0] >> 9;
5224 Addend
= bit_cast
<int32_t>(RawValue
[1]);
5225 } else if (Header
.imports_format
== MachO::DYLD_CHAINED_IMPORT_ADDEND64
) {
5226 static_assert(2 * sizeof(uint64_t) ==
5227 sizeof(MachO::dyld_chained_import_addend64
));
5228 auto RawValue
= getArray
<uint64_t, 2>(*this, ImportPtr
);
5230 LibOrdinal
= getEncodedOrdinal
<uint16_t>(RawValue
[0] & 0xFFFF);
5231 NameOffset
= (RawValue
[0] >> 16) & 1;
5232 WeakImport
= RawValue
[0] >> 17;
5233 Addend
= RawValue
[1];
5235 llvm_unreachable("Import format should have been checked");
5238 const char *Str
= Symbols
+ NameOffset
;
5239 if (Str
>= SymbolsEnd
)
5240 return malformedError("bad chained fixups: symbol offset " +
5241 Twine(NameOffset
) + " extends past end " +
5242 Twine(DyldChainedFixups
.datasize
));
5243 Targets
.emplace_back(LibOrdinal
, NameOffset
, Str
, Addend
, WeakImport
);
5246 return std::move(Targets
);
5249 ArrayRef
<uint8_t> MachOObjectFile::getDyldExportsTrie() const {
5250 if (!DyldExportsTrieLoadCmd
)
5253 auto DyldExportsTrieOrError
= getStructOrErr
<MachO::linkedit_data_command
>(
5254 *this, DyldExportsTrieLoadCmd
);
5255 if (!DyldExportsTrieOrError
)
5257 MachO::linkedit_data_command DyldExportsTrie
= DyldExportsTrieOrError
.get();
5258 const uint8_t *Ptr
=
5259 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldExportsTrie
.dataoff
));
5260 return ArrayRef(Ptr
, DyldExportsTrie
.datasize
);
5263 SmallVector
<uint64_t> MachOObjectFile::getFunctionStarts() const {
5264 if (!FuncStartsLoadCmd
)
5268 getStructOrErr
<MachO::linkedit_data_command
>(*this, FuncStartsLoadCmd
);
5272 MachO::linkedit_data_command Info
= InfoOrErr
.get();
5273 SmallVector
<uint64_t, 8> FunctionStarts
;
5274 this->ReadULEB128s(Info
.dataoff
, FunctionStarts
);
5275 return std::move(FunctionStarts
);
5278 ArrayRef
<uint8_t> MachOObjectFile::getUuid() const {
5281 // Returning a pointer is fine as uuid doesn't need endian swapping.
5282 const char *Ptr
= UuidLoadCmd
+ offsetof(MachO::uuid_command
, uuid
);
5283 return ArrayRef(reinterpret_cast<const uint8_t *>(Ptr
), 16);
5286 StringRef
MachOObjectFile::getStringTableData() const {
5287 MachO::symtab_command S
= getSymtabLoadCommand();
5288 return getData().substr(S
.stroff
, S
.strsize
);
5291 bool MachOObjectFile::is64Bit() const {
5292 return getType() == getMachOType(false, true) ||
5293 getType() == getMachOType(true, true);
5296 void MachOObjectFile::ReadULEB128s(uint64_t Index
,
5297 SmallVectorImpl
<uint64_t> &Out
) const {
5298 DataExtractor
extractor(ObjectFile::getData(), true, 0);
5300 uint64_t offset
= Index
;
5302 while (uint64_t delta
= extractor
.getULEB128(&offset
)) {
5304 Out
.push_back(data
);
5308 bool MachOObjectFile::isRelocatableObject() const {
5309 return getHeader().filetype
== MachO::MH_OBJECT
;
5312 /// Create a MachOObjectFile instance from a given buffer.
5314 /// \param Buffer Memory buffer containing the MachO binary data.
5315 /// \param UniversalCputype CPU type when the MachO part of a universal binary.
5316 /// \param UniversalIndex Index of the MachO within a universal binary.
5317 /// \param MachOFilesetEntryOffset Offset of the MachO entry in a fileset MachO.
5318 /// \returns A std::unique_ptr to a MachOObjectFile instance on success.
5319 Expected
<std::unique_ptr
<MachOObjectFile
>> ObjectFile::createMachOObjectFile(
5320 MemoryBufferRef Buffer
, uint32_t UniversalCputype
, uint32_t UniversalIndex
,
5321 size_t MachOFilesetEntryOffset
) {
5322 StringRef Magic
= Buffer
.getBuffer().slice(0, 4);
5323 if (Magic
== "\xFE\xED\xFA\xCE")
5324 return MachOObjectFile::create(Buffer
, false, false, UniversalCputype
,
5325 UniversalIndex
, MachOFilesetEntryOffset
);
5326 if (Magic
== "\xCE\xFA\xED\xFE")
5327 return MachOObjectFile::create(Buffer
, true, false, UniversalCputype
,
5328 UniversalIndex
, MachOFilesetEntryOffset
);
5329 if (Magic
== "\xFE\xED\xFA\xCF")
5330 return MachOObjectFile::create(Buffer
, false, true, UniversalCputype
,
5331 UniversalIndex
, MachOFilesetEntryOffset
);
5332 if (Magic
== "\xCF\xFA\xED\xFE")
5333 return MachOObjectFile::create(Buffer
, true, true, UniversalCputype
,
5334 UniversalIndex
, MachOFilesetEntryOffset
);
5335 return make_error
<GenericBinaryError
>("Unrecognized MachO magic number",
5336 object_error::invalid_file_type
);
5339 StringRef
MachOObjectFile::mapDebugSectionName(StringRef Name
) const {
5340 return StringSwitch
<StringRef
>(Name
)
5341 .Case("debug_str_offs", "debug_str_offsets")
5345 Expected
<std::vector
<std::string
>>
5346 MachOObjectFile::findDsymObjectMembers(StringRef Path
) {
5347 SmallString
<256> BundlePath(Path
);
5348 // Normalize input path. This is necessary to accept `bundle.dSYM/`.
5349 sys::path::remove_dots(BundlePath
);
5350 if (!sys::fs::is_directory(BundlePath
) ||
5351 sys::path::extension(BundlePath
) != ".dSYM")
5352 return std::vector
<std::string
>();
5353 sys::path::append(BundlePath
, "Contents", "Resources", "DWARF");
5355 auto EC
= sys::fs::is_directory(BundlePath
, IsDir
);
5356 if (EC
== errc::no_such_file_or_directory
|| (!EC
&& !IsDir
))
5357 return createStringError(
5358 EC
, "%s: expected directory 'Contents/Resources/DWARF' in dSYM bundle",
5359 Path
.str().c_str());
5361 return createFileError(BundlePath
, errorCodeToError(EC
));
5363 std::vector
<std::string
> ObjectPaths
;
5364 for (sys::fs::directory_iterator
Dir(BundlePath
, EC
), DirEnd
;
5365 Dir
!= DirEnd
&& !EC
; Dir
.increment(EC
)) {
5366 StringRef ObjectPath
= Dir
->path();
5367 sys::fs::file_status Status
;
5368 if (auto EC
= sys::fs::status(ObjectPath
, Status
))
5369 return createFileError(ObjectPath
, errorCodeToError(EC
));
5370 switch (Status
.type()) {
5371 case sys::fs::file_type::regular_file
:
5372 case sys::fs::file_type::symlink_file
:
5373 case sys::fs::file_type::type_unknown
:
5374 ObjectPaths
.push_back(ObjectPath
.str());
5376 default: /*ignore*/;
5380 return createFileError(BundlePath
, errorCodeToError(EC
));
5381 if (ObjectPaths
.empty())
5382 return createStringError(std::error_code(),
5383 "%s: no objects found in dSYM bundle",
5384 Path
.str().c_str());
5388 llvm::binaryformat::Swift5ReflectionSectionKind
5389 MachOObjectFile::mapReflectionSectionNameToEnumValue(
5390 StringRef SectionName
) const {
5391 #define HANDLE_SWIFT_SECTION(KIND, MACHO, ELF, COFF) \
5392 .Case(MACHO, llvm::binaryformat::Swift5ReflectionSectionKind::KIND)
5393 return StringSwitch
<llvm::binaryformat::Swift5ReflectionSectionKind
>(
5395 #include "llvm/BinaryFormat/Swift.def"
5396 .Default(llvm::binaryformat::Swift5ReflectionSectionKind::unknown
);
5397 #undef HANDLE_SWIFT_SECTION
5400 bool MachOObjectFile::isMachOPairedReloc(uint64_t RelocType
, uint64_t Arch
) {
5403 return RelocType
== MachO::GENERIC_RELOC_SECTDIFF
||
5404 RelocType
== MachO::GENERIC_RELOC_LOCAL_SECTDIFF
;
5405 case Triple::x86_64
:
5406 return RelocType
== MachO::X86_64_RELOC_SUBTRACTOR
;
5409 return RelocType
== MachO::ARM_RELOC_SECTDIFF
||
5410 RelocType
== MachO::ARM_RELOC_LOCAL_SECTDIFF
||
5411 RelocType
== MachO::ARM_RELOC_HALF
||
5412 RelocType
== MachO::ARM_RELOC_HALF_SECTDIFF
;
5413 case Triple::aarch64
:
5414 return RelocType
== MachO::ARM64_RELOC_SUBTRACTOR
;