1 //===- MachO.h - MachO object file implementation ---------------*- C++ -*-===//
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 declares the MachOObjectFile class, which implement the ObjectFile
10 // interface for MachO files.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_OBJECT_MACHO_H
15 #define LLVM_OBJECT_MACHO_H
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/Triple.h"
23 #include "llvm/ADT/iterator_range.h"
24 #include "llvm/BinaryFormat/MachO.h"
25 #include "llvm/MC/SubtargetFeature.h"
26 #include "llvm/Object/Binary.h"
27 #include "llvm/Object/ObjectFile.h"
28 #include "llvm/Object/SymbolicFile.h"
29 #include "llvm/Support/Error.h"
30 #include "llvm/Support/Format.h"
31 #include "llvm/Support/MemoryBuffer.h"
32 #include "llvm/Support/raw_ostream.h"
36 #include <system_error>
41 /// DiceRef - This is a value type class that represents a single
42 /// data in code entry in the table in a Mach-O object file.
44 DataRefImpl DicePimpl
;
45 const ObjectFile
*OwningObject
= nullptr;
49 DiceRef(DataRefImpl DiceP
, const ObjectFile
*Owner
);
51 bool operator==(const DiceRef
&Other
) const;
52 bool operator<(const DiceRef
&Other
) const;
56 std::error_code
getOffset(uint32_t &Result
) const;
57 std::error_code
getLength(uint16_t &Result
) const;
58 std::error_code
getKind(uint16_t &Result
) const;
60 DataRefImpl
getRawDataRefImpl() const;
61 const ObjectFile
*getObjectFile() const;
63 using dice_iterator
= content_iterator
<DiceRef
>;
65 /// ExportEntry encapsulates the current-state-of-the-walk used when doing a
66 /// non-recursive walk of the trie data structure. This allows you to iterate
67 /// across all exported symbols using:
69 /// for (const llvm::object::ExportEntry &AnExport : Obj->exports(&Err)) {
71 /// if (Err) { report error ...
74 ExportEntry(Error
*Err
, const MachOObjectFile
*O
, ArrayRef
<uint8_t> Trie
);
76 StringRef
name() const;
77 uint64_t flags() const;
78 uint64_t address() const;
79 uint64_t other() const;
80 StringRef
otherName() const;
81 uint32_t nodeOffset() const;
83 bool operator==(const ExportEntry
&) const;
88 friend class MachOObjectFile
;
92 uint64_t readULEB128(const uint8_t *&p
, const char **error
);
93 void pushDownUntilBottom();
94 void pushNode(uint64_t Offset
);
96 // Represents a node in the mach-o exports trie.
98 NodeState(const uint8_t *Ptr
);
100 const uint8_t *Start
;
101 const uint8_t *Current
;
103 uint64_t Address
= 0;
105 const char *ImportName
= nullptr;
106 unsigned ChildCount
= 0;
107 unsigned NextChildIndex
= 0;
108 unsigned ParentStringLength
= 0;
109 bool IsExportNode
= false;
111 using NodeList
= SmallVector
<NodeState
, 16>;
112 using node_iterator
= NodeList::const_iterator
;
115 const MachOObjectFile
*O
;
116 ArrayRef
<uint8_t> Trie
;
117 SmallString
<256> CumulativeString
;
121 iterator_range
<node_iterator
> nodes() const {
122 return make_range(Stack
.begin(), Stack
.end());
125 using export_iterator
= content_iterator
<ExportEntry
>;
127 // Segment info so SegIndex/SegOffset pairs in a Mach-O Bind or Rebase entry
128 // can be checked and translated. Only the SegIndex/SegOffset pairs from
129 // checked entries are to be used with the segmentName(), sectionName() and
130 // address() methods below.
131 class BindRebaseSegInfo
{
133 BindRebaseSegInfo(const MachOObjectFile
*Obj
);
135 // Used to check a Mach-O Bind or Rebase entry for errors when iterating.
136 const char* checkSegAndOffsets(int32_t SegIndex
, uint64_t SegOffset
,
137 uint8_t PointerSize
, uint32_t Count
=1,
139 // Used with valid SegIndex/SegOffset values from checked entries.
140 StringRef
segmentName(int32_t SegIndex
);
141 StringRef
sectionName(int32_t SegIndex
, uint64_t SegOffset
);
142 uint64_t address(uint32_t SegIndex
, uint64_t SegOffset
);
148 StringRef SectionName
;
149 StringRef SegmentName
;
150 uint64_t OffsetInSegment
;
151 uint64_t SegmentStartAddress
;
152 int32_t SegmentIndex
;
154 const SectionInfo
&findSection(int32_t SegIndex
, uint64_t SegOffset
);
156 SmallVector
<SectionInfo
, 32> Sections
;
160 /// MachORebaseEntry encapsulates the current state in the decompression of
161 /// rebasing opcodes. This allows you to iterate through the compressed table of
164 /// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) {
166 /// if (Err) { report error ...
167 class MachORebaseEntry
{
169 MachORebaseEntry(Error
*Err
, const MachOObjectFile
*O
,
170 ArrayRef
<uint8_t> opcodes
, bool is64Bit
);
172 int32_t segmentIndex() const;
173 uint64_t segmentOffset() const;
174 StringRef
typeName() const;
175 StringRef
segmentName() const;
176 StringRef
sectionName() const;
177 uint64_t address() const;
179 bool operator==(const MachORebaseEntry
&) const;
184 friend class MachOObjectFile
;
188 uint64_t readULEB128(const char **error
);
191 const MachOObjectFile
*O
;
192 ArrayRef
<uint8_t> Opcodes
;
194 uint64_t SegmentOffset
= 0;
195 int32_t SegmentIndex
= -1;
196 uint64_t RemainingLoopCount
= 0;
197 uint64_t AdvanceAmount
= 0;
198 uint8_t RebaseType
= 0;
202 using rebase_iterator
= content_iterator
<MachORebaseEntry
>;
204 /// MachOBindEntry encapsulates the current state in the decompression of
205 /// binding opcodes. This allows you to iterate through the compressed table of
208 /// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) {
210 /// if (Err) { report error ...
211 class MachOBindEntry
{
213 enum class Kind
{ Regular
, Lazy
, Weak
};
215 MachOBindEntry(Error
*Err
, const MachOObjectFile
*O
,
216 ArrayRef
<uint8_t> Opcodes
, bool is64Bit
, MachOBindEntry::Kind
);
218 int32_t segmentIndex() const;
219 uint64_t segmentOffset() const;
220 StringRef
typeName() const;
221 StringRef
symbolName() const;
222 uint32_t flags() const;
223 int64_t addend() const;
226 StringRef
segmentName() const;
227 StringRef
sectionName() const;
228 uint64_t address() const;
230 bool operator==(const MachOBindEntry
&) const;
235 friend class MachOObjectFile
;
239 uint64_t readULEB128(const char **error
);
240 int64_t readSLEB128(const char **error
);
243 const MachOObjectFile
*O
;
244 ArrayRef
<uint8_t> Opcodes
;
246 uint64_t SegmentOffset
= 0;
247 int32_t SegmentIndex
= -1;
248 StringRef SymbolName
;
249 bool LibraryOrdinalSet
= false;
253 uint64_t RemainingLoopCount
= 0;
254 uint64_t AdvanceAmount
= 0;
255 uint8_t BindType
= 0;
260 using bind_iterator
= content_iterator
<MachOBindEntry
>;
262 class MachOObjectFile
: public ObjectFile
{
264 struct LoadCommandInfo
{
265 const char *Ptr
; // Where in memory the load command is.
266 MachO::load_command C
; // The command itself.
268 using LoadCommandList
= SmallVector
<LoadCommandInfo
, 4>;
269 using load_command_iterator
= LoadCommandList::const_iterator
;
271 static Expected
<std::unique_ptr
<MachOObjectFile
>>
272 create(MemoryBufferRef Object
, bool IsLittleEndian
, bool Is64Bits
,
273 uint32_t UniversalCputype
= 0, uint32_t UniversalIndex
= 0);
275 void moveSymbolNext(DataRefImpl
&Symb
) const override
;
277 uint64_t getNValue(DataRefImpl Sym
) const;
278 Expected
<StringRef
> getSymbolName(DataRefImpl Symb
) const override
;
281 Error
checkSymbolTable() const;
283 std::error_code
getIndirectName(DataRefImpl Symb
, StringRef
&Res
) const;
284 unsigned getSectionType(SectionRef Sec
) const;
286 Expected
<uint64_t> getSymbolAddress(DataRefImpl Symb
) const override
;
287 uint32_t getSymbolAlignment(DataRefImpl Symb
) const override
;
288 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb
) const override
;
289 Expected
<SymbolRef::Type
> getSymbolType(DataRefImpl Symb
) const override
;
290 uint32_t getSymbolFlags(DataRefImpl Symb
) const override
;
291 Expected
<section_iterator
> getSymbolSection(DataRefImpl Symb
) const override
;
292 unsigned getSymbolSectionID(SymbolRef Symb
) const;
293 unsigned getSectionID(SectionRef Sec
) const;
295 void moveSectionNext(DataRefImpl
&Sec
) const override
;
296 Expected
<StringRef
> getSectionName(DataRefImpl Sec
) const override
;
297 uint64_t getSectionAddress(DataRefImpl Sec
) const override
;
298 uint64_t getSectionIndex(DataRefImpl Sec
) const override
;
299 uint64_t getSectionSize(DataRefImpl Sec
) const override
;
300 ArrayRef
<uint8_t> getSectionContents(uint32_t Offset
, uint64_t Size
) const;
301 Expected
<ArrayRef
<uint8_t>>
302 getSectionContents(DataRefImpl Sec
) const override
;
303 uint64_t getSectionAlignment(DataRefImpl Sec
) const override
;
304 Expected
<SectionRef
> getSection(unsigned SectionIndex
) const;
305 Expected
<SectionRef
> getSection(StringRef SectionName
) const;
306 bool isSectionCompressed(DataRefImpl Sec
) const override
;
307 bool isSectionText(DataRefImpl Sec
) const override
;
308 bool isSectionData(DataRefImpl Sec
) const override
;
309 bool isSectionBSS(DataRefImpl Sec
) const override
;
310 bool isSectionVirtual(DataRefImpl Sec
) const override
;
311 bool isSectionBitcode(DataRefImpl Sec
) const override
;
313 /// When dsymutil generates the companion file, it strips all unnecessary
314 /// sections (e.g. everything in the _TEXT segment) by omitting their body
315 /// and setting the offset in their corresponding load command to zero.
317 /// While the load command itself is valid, reading the section corresponds
318 /// to reading the number of bytes specified in the load command, starting
319 /// from offset 0 (i.e. the Mach-O header at the beginning of the file).
320 bool isSectionStripped(DataRefImpl Sec
) const override
;
322 relocation_iterator
section_rel_begin(DataRefImpl Sec
) const override
;
323 relocation_iterator
section_rel_end(DataRefImpl Sec
) const override
;
325 relocation_iterator
extrel_begin() const;
326 relocation_iterator
extrel_end() const;
327 iterator_range
<relocation_iterator
> external_relocations() const {
328 return make_range(extrel_begin(), extrel_end());
331 relocation_iterator
locrel_begin() const;
332 relocation_iterator
locrel_end() const;
334 void moveRelocationNext(DataRefImpl
&Rel
) const override
;
335 uint64_t getRelocationOffset(DataRefImpl Rel
) const override
;
336 symbol_iterator
getRelocationSymbol(DataRefImpl Rel
) const override
;
337 section_iterator
getRelocationSection(DataRefImpl Rel
) const;
338 uint64_t getRelocationType(DataRefImpl Rel
) const override
;
339 void getRelocationTypeName(DataRefImpl Rel
,
340 SmallVectorImpl
<char> &Result
) const override
;
341 uint8_t getRelocationLength(DataRefImpl Rel
) const;
344 std::error_code
getLibraryShortNameByIndex(unsigned Index
, StringRef
&) const;
345 uint32_t getLibraryCount() const;
347 section_iterator
getRelocationRelocatedSection(relocation_iterator Rel
) const;
349 // TODO: Would be useful to have an iterator based version
350 // of the load command interface too.
352 basic_symbol_iterator
symbol_begin() const override
;
353 basic_symbol_iterator
symbol_end() const override
;
356 symbol_iterator
getSymbolByIndex(unsigned Index
) const;
357 uint64_t getSymbolIndex(DataRefImpl Symb
) const;
359 section_iterator
section_begin() const override
;
360 section_iterator
section_end() const override
;
362 uint8_t getBytesInAddress() const override
;
364 StringRef
getFileFormatName() const override
;
365 Triple::ArchType
getArch() const override
;
366 SubtargetFeatures
getFeatures() const override
{ return SubtargetFeatures(); }
367 Triple
getArchTriple(const char **McpuDefault
= nullptr) const;
369 relocation_iterator
section_rel_begin(unsigned Index
) const;
370 relocation_iterator
section_rel_end(unsigned Index
) const;
372 dice_iterator
begin_dices() const;
373 dice_iterator
end_dices() const;
375 load_command_iterator
begin_load_commands() const;
376 load_command_iterator
end_load_commands() const;
377 iterator_range
<load_command_iterator
> load_commands() const;
379 /// For use iterating over all exported symbols.
380 iterator_range
<export_iterator
> exports(Error
&Err
) const;
382 /// For use examining a trie not in a MachOObjectFile.
383 static iterator_range
<export_iterator
> exports(Error
&Err
,
384 ArrayRef
<uint8_t> Trie
,
385 const MachOObjectFile
*O
=
388 /// For use iterating over all rebase table entries.
389 iterator_range
<rebase_iterator
> rebaseTable(Error
&Err
);
391 /// For use examining rebase opcodes in a MachOObjectFile.
392 static iterator_range
<rebase_iterator
> rebaseTable(Error
&Err
,
394 ArrayRef
<uint8_t> Opcodes
,
397 /// For use iterating over all bind table entries.
398 iterator_range
<bind_iterator
> bindTable(Error
&Err
);
400 /// For use iterating over all lazy bind table entries.
401 iterator_range
<bind_iterator
> lazyBindTable(Error
&Err
);
403 /// For use iterating over all weak bind table entries.
404 iterator_range
<bind_iterator
> weakBindTable(Error
&Err
);
406 /// For use examining bind opcodes in a MachOObjectFile.
407 static iterator_range
<bind_iterator
> bindTable(Error
&Err
,
409 ArrayRef
<uint8_t> Opcodes
,
411 MachOBindEntry::Kind
);
413 // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
414 // that fully contains a pointer at that location. Multiple fixups in a bind
415 // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
416 // be tested via the Count and Skip parameters.
418 // This is used by MachOBindEntry::moveNext() to validate a MachOBindEntry.
419 const char *BindEntryCheckSegAndOffsets(int32_t SegIndex
, uint64_t SegOffset
,
420 uint8_t PointerSize
, uint32_t Count
=1,
421 uint32_t Skip
=0) const {
422 return BindRebaseSectionTable
->checkSegAndOffsets(SegIndex
, SegOffset
,
423 PointerSize
, Count
, Skip
);
426 // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
427 // that fully contains a pointer at that location. Multiple fixups in a rebase
428 // (such as with the REBASE_OPCODE_DO_*_TIMES* opcodes) can be tested via the
429 // Count and Skip parameters.
431 // This is used by MachORebaseEntry::moveNext() to validate a MachORebaseEntry
432 const char *RebaseEntryCheckSegAndOffsets(int32_t SegIndex
,
436 uint32_t Skip
=0) const {
437 return BindRebaseSectionTable
->checkSegAndOffsets(SegIndex
, SegOffset
,
438 PointerSize
, Count
, Skip
);
441 /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to
442 /// get the segment name.
443 StringRef
BindRebaseSegmentName(int32_t SegIndex
) const {
444 return BindRebaseSectionTable
->segmentName(SegIndex
);
447 /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
448 /// Rebase entry to get the section name.
449 StringRef
BindRebaseSectionName(uint32_t SegIndex
, uint64_t SegOffset
) const {
450 return BindRebaseSectionTable
->sectionName(SegIndex
, SegOffset
);
453 /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
454 /// Rebase entry to get the address.
455 uint64_t BindRebaseAddress(uint32_t SegIndex
, uint64_t SegOffset
) const {
456 return BindRebaseSectionTable
->address(SegIndex
, SegOffset
);
459 // In a MachO file, sections have a segment name. This is used in the .o
460 // files. They have a single segment, but this field specifies which segment
461 // a section should be put in the final object.
462 StringRef
getSectionFinalSegmentName(DataRefImpl Sec
) const;
464 // Names are stored as 16 bytes. These returns the raw 16 bytes without
465 // interpreting them as a C string.
466 ArrayRef
<char> getSectionRawName(DataRefImpl Sec
) const;
467 ArrayRef
<char> getSectionRawFinalSegmentName(DataRefImpl Sec
) const;
469 // MachO specific Info about relocations.
470 bool isRelocationScattered(const MachO::any_relocation_info
&RE
) const;
471 unsigned getPlainRelocationSymbolNum(
472 const MachO::any_relocation_info
&RE
) const;
473 bool getPlainRelocationExternal(const MachO::any_relocation_info
&RE
) const;
474 bool getScatteredRelocationScattered(
475 const MachO::any_relocation_info
&RE
) const;
476 uint32_t getScatteredRelocationValue(
477 const MachO::any_relocation_info
&RE
) const;
478 uint32_t getScatteredRelocationType(
479 const MachO::any_relocation_info
&RE
) const;
480 unsigned getAnyRelocationAddress(const MachO::any_relocation_info
&RE
) const;
481 unsigned getAnyRelocationPCRel(const MachO::any_relocation_info
&RE
) const;
482 unsigned getAnyRelocationLength(const MachO::any_relocation_info
&RE
) const;
483 unsigned getAnyRelocationType(const MachO::any_relocation_info
&RE
) const;
484 SectionRef
getAnyRelocationSection(const MachO::any_relocation_info
&RE
) const;
486 // MachO specific structures.
487 MachO::section
getSection(DataRefImpl DRI
) const;
488 MachO::section_64
getSection64(DataRefImpl DRI
) const;
489 MachO::section
getSection(const LoadCommandInfo
&L
, unsigned Index
) const;
490 MachO::section_64
getSection64(const LoadCommandInfo
&L
,unsigned Index
) const;
491 MachO::nlist
getSymbolTableEntry(DataRefImpl DRI
) const;
492 MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI
) const;
494 MachO::linkedit_data_command
495 getLinkeditDataLoadCommand(const LoadCommandInfo
&L
) const;
496 MachO::segment_command
497 getSegmentLoadCommand(const LoadCommandInfo
&L
) const;
498 MachO::segment_command_64
499 getSegment64LoadCommand(const LoadCommandInfo
&L
) const;
500 MachO::linker_option_command
501 getLinkerOptionLoadCommand(const LoadCommandInfo
&L
) const;
502 MachO::version_min_command
503 getVersionMinLoadCommand(const LoadCommandInfo
&L
) const;
505 getNoteLoadCommand(const LoadCommandInfo
&L
) const;
506 MachO::build_version_command
507 getBuildVersionLoadCommand(const LoadCommandInfo
&L
) const;
508 MachO::build_tool_version
509 getBuildToolVersion(unsigned index
) const;
511 getDylibIDLoadCommand(const LoadCommandInfo
&L
) const;
512 MachO::dyld_info_command
513 getDyldInfoLoadCommand(const LoadCommandInfo
&L
) const;
514 MachO::dylinker_command
515 getDylinkerCommand(const LoadCommandInfo
&L
) const;
517 getUuidCommand(const LoadCommandInfo
&L
) const;
519 getRpathCommand(const LoadCommandInfo
&L
) const;
520 MachO::source_version_command
521 getSourceVersionCommand(const LoadCommandInfo
&L
) const;
522 MachO::entry_point_command
523 getEntryPointCommand(const LoadCommandInfo
&L
) const;
524 MachO::encryption_info_command
525 getEncryptionInfoCommand(const LoadCommandInfo
&L
) const;
526 MachO::encryption_info_command_64
527 getEncryptionInfoCommand64(const LoadCommandInfo
&L
) const;
528 MachO::sub_framework_command
529 getSubFrameworkCommand(const LoadCommandInfo
&L
) const;
530 MachO::sub_umbrella_command
531 getSubUmbrellaCommand(const LoadCommandInfo
&L
) const;
532 MachO::sub_library_command
533 getSubLibraryCommand(const LoadCommandInfo
&L
) const;
534 MachO::sub_client_command
535 getSubClientCommand(const LoadCommandInfo
&L
) const;
536 MachO::routines_command
537 getRoutinesCommand(const LoadCommandInfo
&L
) const;
538 MachO::routines_command_64
539 getRoutinesCommand64(const LoadCommandInfo
&L
) const;
540 MachO::thread_command
541 getThreadCommand(const LoadCommandInfo
&L
) const;
543 MachO::any_relocation_info
getRelocation(DataRefImpl Rel
) const;
544 MachO::data_in_code_entry
getDice(DataRefImpl Rel
) const;
545 const MachO::mach_header
&getHeader() const;
546 const MachO::mach_header_64
&getHeader64() const;
548 getIndirectSymbolTableEntry(const MachO::dysymtab_command
&DLC
,
549 unsigned Index
) const;
550 MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset
,
551 unsigned Index
) const;
552 MachO::symtab_command
getSymtabLoadCommand() const;
553 MachO::dysymtab_command
getDysymtabLoadCommand() const;
554 MachO::linkedit_data_command
getDataInCodeLoadCommand() const;
555 MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const;
556 ArrayRef
<uint8_t> getDyldInfoRebaseOpcodes() const;
557 ArrayRef
<uint8_t> getDyldInfoBindOpcodes() const;
558 ArrayRef
<uint8_t> getDyldInfoWeakBindOpcodes() const;
559 ArrayRef
<uint8_t> getDyldInfoLazyBindOpcodes() const;
560 ArrayRef
<uint8_t> getDyldInfoExportsTrie() const;
561 ArrayRef
<uint8_t> getUuid() const;
563 StringRef
getStringTableData() const;
564 bool is64Bit() const;
565 void ReadULEB128s(uint64_t Index
, SmallVectorImpl
<uint64_t> &Out
) const;
567 static StringRef
guessLibraryShortName(StringRef Name
, bool &isFramework
,
570 static Triple::ArchType
getArch(uint32_t CPUType
);
571 static Triple
getArchTriple(uint32_t CPUType
, uint32_t CPUSubType
,
572 const char **McpuDefault
= nullptr,
573 const char **ArchFlag
= nullptr);
574 static bool isValidArch(StringRef ArchFlag
);
575 static ArrayRef
<StringRef
> getValidArchs();
576 static Triple
getHostArch();
578 bool isRelocatableObject() const override
;
580 StringRef
mapDebugSectionName(StringRef Name
) const override
;
582 bool hasPageZeroSegment() const { return HasPageZeroSegment
; }
584 static bool classof(const Binary
*v
) {
589 getVersionMinMajor(MachO::version_min_command
&C
, bool SDK
) {
590 uint32_t VersionOrSDK
= (SDK
) ? C
.sdk
: C
.version
;
591 return (VersionOrSDK
>> 16) & 0xffff;
595 getVersionMinMinor(MachO::version_min_command
&C
, bool SDK
) {
596 uint32_t VersionOrSDK
= (SDK
) ? C
.sdk
: C
.version
;
597 return (VersionOrSDK
>> 8) & 0xff;
601 getVersionMinUpdate(MachO::version_min_command
&C
, bool SDK
) {
602 uint32_t VersionOrSDK
= (SDK
) ? C
.sdk
: C
.version
;
603 return VersionOrSDK
& 0xff;
606 static std::string
getBuildPlatform(uint32_t platform
) {
608 case MachO::PLATFORM_MACOS
: return "macos";
609 case MachO::PLATFORM_IOS
: return "ios";
610 case MachO::PLATFORM_TVOS
: return "tvos";
611 case MachO::PLATFORM_WATCHOS
: return "watchos";
612 case MachO::PLATFORM_BRIDGEOS
: return "bridgeos";
613 case MachO::PLATFORM_MACCATALYST
: return "macCatalyst";
614 case MachO::PLATFORM_IOSSIMULATOR
: return "iossimulator";
615 case MachO::PLATFORM_TVOSSIMULATOR
: return "tvossimulator";
616 case MachO::PLATFORM_WATCHOSSIMULATOR
: return "watchossimulator";
619 raw_string_ostream
ss(ret
);
620 ss
<< format_hex(platform
, 8, true);
625 static std::string
getBuildTool(uint32_t tools
) {
627 case MachO::TOOL_CLANG
: return "clang";
628 case MachO::TOOL_SWIFT
: return "swift";
629 case MachO::TOOL_LD
: return "ld";
632 raw_string_ostream
ss(ret
);
633 ss
<< format_hex(tools
, 8, true);
638 static std::string
getVersionString(uint32_t version
) {
639 uint32_t major
= (version
>> 16) & 0xffff;
640 uint32_t minor
= (version
>> 8) & 0xff;
641 uint32_t update
= version
& 0xff;
643 SmallString
<32> Version
;
644 Version
= utostr(major
) + "." + utostr(minor
);
646 Version
+= "." + utostr(update
);
647 return Version
.str();
651 MachOObjectFile(MemoryBufferRef Object
, bool IsLittleEndian
, bool Is64Bits
,
652 Error
&Err
, uint32_t UniversalCputype
= 0,
653 uint32_t UniversalIndex
= 0);
655 uint64_t getSymbolValueImpl(DataRefImpl Symb
) const override
;
658 MachO::mach_header_64 Header64
;
659 MachO::mach_header Header
;
661 using SectionList
= SmallVector
<const char*, 1>;
662 SectionList Sections
;
663 using LibraryList
= SmallVector
<const char*, 1>;
664 LibraryList Libraries
;
665 LoadCommandList LoadCommands
;
666 using LibraryShortName
= SmallVector
<StringRef
, 1>;
667 using BuildToolList
= SmallVector
<const char*, 1>;
668 BuildToolList BuildTools
;
669 mutable LibraryShortName LibrariesShortNames
;
670 std::unique_ptr
<BindRebaseSegInfo
> BindRebaseSectionTable
;
671 const char *SymtabLoadCmd
= nullptr;
672 const char *DysymtabLoadCmd
= nullptr;
673 const char *DataInCodeLoadCmd
= nullptr;
674 const char *LinkOptHintsLoadCmd
= nullptr;
675 const char *DyldInfoLoadCmd
= nullptr;
676 const char *UuidLoadCmd
= nullptr;
677 bool HasPageZeroSegment
= false;
681 inline DiceRef::DiceRef(DataRefImpl DiceP
, const ObjectFile
*Owner
)
682 : DicePimpl(DiceP
) , OwningObject(Owner
) {}
684 inline bool DiceRef::operator==(const DiceRef
&Other
) const {
685 return DicePimpl
== Other
.DicePimpl
;
688 inline bool DiceRef::operator<(const DiceRef
&Other
) const {
689 return DicePimpl
< Other
.DicePimpl
;
692 inline void DiceRef::moveNext() {
693 const MachO::data_in_code_entry
*P
=
694 reinterpret_cast<const MachO::data_in_code_entry
*>(DicePimpl
.p
);
695 DicePimpl
.p
= reinterpret_cast<uintptr_t>(P
+ 1);
698 // Since a Mach-O data in code reference, a DiceRef, can only be created when
699 // the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for
700 // the methods that get the values of the fields of the reference.
702 inline std::error_code
DiceRef::getOffset(uint32_t &Result
) const {
703 const MachOObjectFile
*MachOOF
=
704 static_cast<const MachOObjectFile
*>(OwningObject
);
705 MachO::data_in_code_entry Dice
= MachOOF
->getDice(DicePimpl
);
706 Result
= Dice
.offset
;
707 return std::error_code();
710 inline std::error_code
DiceRef::getLength(uint16_t &Result
) const {
711 const MachOObjectFile
*MachOOF
=
712 static_cast<const MachOObjectFile
*>(OwningObject
);
713 MachO::data_in_code_entry Dice
= MachOOF
->getDice(DicePimpl
);
714 Result
= Dice
.length
;
715 return std::error_code();
718 inline std::error_code
DiceRef::getKind(uint16_t &Result
) const {
719 const MachOObjectFile
*MachOOF
=
720 static_cast<const MachOObjectFile
*>(OwningObject
);
721 MachO::data_in_code_entry Dice
= MachOOF
->getDice(DicePimpl
);
723 return std::error_code();
726 inline DataRefImpl
DiceRef::getRawDataRefImpl() const {
730 inline const ObjectFile
*DiceRef::getObjectFile() const {
734 } // end namespace object
735 } // end namespace llvm
737 #endif // LLVM_OBJECT_MACHO_H