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 *checkSegAndOffset(int32_t SegIndex
, uint64_t SegOffset
,
138 const char *checkCountAndSkip(uint32_t Count
, uint32_t Skip
,
139 uint8_t PointerSize
, int32_t SegIndex
,
141 // Used with valid SegIndex/SegOffset values from checked entries.
142 StringRef
segmentName(int32_t SegIndex
);
143 StringRef
sectionName(int32_t SegIndex
, uint64_t SegOffset
);
144 uint64_t address(uint32_t SegIndex
, uint64_t SegOffset
);
150 StringRef SectionName
;
151 StringRef SegmentName
;
152 uint64_t OffsetInSegment
;
153 uint64_t SegmentStartAddress
;
154 int32_t SegmentIndex
;
156 const SectionInfo
&findSection(int32_t SegIndex
, uint64_t SegOffset
);
158 SmallVector
<SectionInfo
, 32> Sections
;
162 /// MachORebaseEntry encapsulates the current state in the decompression of
163 /// rebasing opcodes. This allows you to iterate through the compressed table of
166 /// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) {
168 /// if (Err) { report error ...
169 class MachORebaseEntry
{
171 MachORebaseEntry(Error
*Err
, const MachOObjectFile
*O
,
172 ArrayRef
<uint8_t> opcodes
, bool is64Bit
);
174 int32_t segmentIndex() const;
175 uint64_t segmentOffset() const;
176 StringRef
typeName() const;
177 StringRef
segmentName() const;
178 StringRef
sectionName() const;
179 uint64_t address() const;
181 bool operator==(const MachORebaseEntry
&) const;
186 friend class MachOObjectFile
;
190 uint64_t readULEB128(const char **error
);
193 const MachOObjectFile
*O
;
194 ArrayRef
<uint8_t> Opcodes
;
196 uint64_t SegmentOffset
= 0;
197 int32_t SegmentIndex
= -1;
198 uint64_t RemainingLoopCount
= 0;
199 uint64_t AdvanceAmount
= 0;
200 uint8_t RebaseType
= 0;
204 using rebase_iterator
= content_iterator
<MachORebaseEntry
>;
206 /// MachOBindEntry encapsulates the current state in the decompression of
207 /// binding opcodes. This allows you to iterate through the compressed table of
210 /// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) {
212 /// if (Err) { report error ...
213 class MachOBindEntry
{
215 enum class Kind
{ Regular
, Lazy
, Weak
};
217 MachOBindEntry(Error
*Err
, const MachOObjectFile
*O
,
218 ArrayRef
<uint8_t> Opcodes
, bool is64Bit
, MachOBindEntry::Kind
);
220 int32_t segmentIndex() const;
221 uint64_t segmentOffset() const;
222 StringRef
typeName() const;
223 StringRef
symbolName() const;
224 uint32_t flags() const;
225 int64_t addend() const;
228 StringRef
segmentName() const;
229 StringRef
sectionName() const;
230 uint64_t address() const;
232 bool operator==(const MachOBindEntry
&) const;
237 friend class MachOObjectFile
;
241 uint64_t readULEB128(const char **error
);
242 int64_t readSLEB128(const char **error
);
245 const MachOObjectFile
*O
;
246 ArrayRef
<uint8_t> Opcodes
;
248 uint64_t SegmentOffset
= 0;
249 int32_t SegmentIndex
= -1;
250 StringRef SymbolName
;
251 bool LibraryOrdinalSet
= false;
255 uint64_t RemainingLoopCount
= 0;
256 uint64_t AdvanceAmount
= 0;
257 uint8_t BindType
= 0;
262 using bind_iterator
= content_iterator
<MachOBindEntry
>;
264 class MachOObjectFile
: public ObjectFile
{
266 struct LoadCommandInfo
{
267 const char *Ptr
; // Where in memory the load command is.
268 MachO::load_command C
; // The command itself.
270 using LoadCommandList
= SmallVector
<LoadCommandInfo
, 4>;
271 using load_command_iterator
= LoadCommandList::const_iterator
;
273 static Expected
<std::unique_ptr
<MachOObjectFile
>>
274 create(MemoryBufferRef Object
, bool IsLittleEndian
, bool Is64Bits
,
275 uint32_t UniversalCputype
= 0, uint32_t UniversalIndex
= 0);
277 void moveSymbolNext(DataRefImpl
&Symb
) const override
;
279 uint64_t getNValue(DataRefImpl Sym
) const;
280 Expected
<StringRef
> getSymbolName(DataRefImpl Symb
) const override
;
283 Error
checkSymbolTable() const;
285 std::error_code
getIndirectName(DataRefImpl Symb
, StringRef
&Res
) const;
286 unsigned getSectionType(SectionRef Sec
) const;
288 Expected
<uint64_t> getSymbolAddress(DataRefImpl Symb
) const override
;
289 uint32_t getSymbolAlignment(DataRefImpl Symb
) const override
;
290 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb
) const override
;
291 Expected
<SymbolRef::Type
> getSymbolType(DataRefImpl Symb
) const override
;
292 uint32_t getSymbolFlags(DataRefImpl Symb
) const override
;
293 Expected
<section_iterator
> getSymbolSection(DataRefImpl Symb
) const override
;
294 unsigned getSymbolSectionID(SymbolRef Symb
) const;
295 unsigned getSectionID(SectionRef Sec
) const;
297 void moveSectionNext(DataRefImpl
&Sec
) const override
;
298 std::error_code
getSectionName(DataRefImpl Sec
,
299 StringRef
&Res
) const override
;
300 uint64_t getSectionAddress(DataRefImpl Sec
) const override
;
301 uint64_t getSectionIndex(DataRefImpl Sec
) const override
;
302 uint64_t getSectionSize(DataRefImpl Sec
) const override
;
303 std::error_code
getSectionContents(DataRefImpl Sec
,
304 StringRef
&Res
) const override
;
305 uint64_t getSectionAlignment(DataRefImpl Sec
) const override
;
306 Expected
<SectionRef
> getSection(unsigned SectionIndex
) const;
307 Expected
<SectionRef
> getSection(StringRef SectionName
) const;
308 bool isSectionCompressed(DataRefImpl Sec
) const override
;
309 bool isSectionText(DataRefImpl Sec
) const override
;
310 bool isSectionData(DataRefImpl Sec
) const override
;
311 bool isSectionBSS(DataRefImpl Sec
) const override
;
312 bool isSectionVirtual(DataRefImpl Sec
) const override
;
313 bool isSectionBitcode(DataRefImpl Sec
) const override
;
315 /// When dsymutil generates the companion file, it strips all unnecessary
316 /// sections (e.g. everything in the _TEXT segment) by omitting their body
317 /// and setting the offset in their corresponding load command to zero.
319 /// While the load command itself is valid, reading the section corresponds
320 /// to reading the number of bytes specified in the load command, starting
321 /// from offset 0 (i.e. the Mach-O header at the beginning of the file).
322 bool isSectionStripped(DataRefImpl Sec
) const override
;
324 relocation_iterator
section_rel_begin(DataRefImpl Sec
) const override
;
325 relocation_iterator
section_rel_end(DataRefImpl Sec
) const override
;
327 relocation_iterator
extrel_begin() const;
328 relocation_iterator
extrel_end() const;
329 iterator_range
<relocation_iterator
> external_relocations() const {
330 return make_range(extrel_begin(), extrel_end());
333 relocation_iterator
locrel_begin() const;
334 relocation_iterator
locrel_end() const;
336 void moveRelocationNext(DataRefImpl
&Rel
) const override
;
337 uint64_t getRelocationOffset(DataRefImpl Rel
) const override
;
338 symbol_iterator
getRelocationSymbol(DataRefImpl Rel
) const override
;
339 section_iterator
getRelocationSection(DataRefImpl Rel
) const;
340 uint64_t getRelocationType(DataRefImpl Rel
) const override
;
341 void getRelocationTypeName(DataRefImpl Rel
,
342 SmallVectorImpl
<char> &Result
) const override
;
343 uint8_t getRelocationLength(DataRefImpl Rel
) const;
346 std::error_code
getLibraryShortNameByIndex(unsigned Index
, StringRef
&) const;
347 uint32_t getLibraryCount() const;
349 section_iterator
getRelocationRelocatedSection(relocation_iterator Rel
) const;
351 // TODO: Would be useful to have an iterator based version
352 // of the load command interface too.
354 basic_symbol_iterator
symbol_begin() const override
;
355 basic_symbol_iterator
symbol_end() const override
;
358 symbol_iterator
getSymbolByIndex(unsigned Index
) const;
359 uint64_t getSymbolIndex(DataRefImpl Symb
) const;
361 section_iterator
section_begin() const override
;
362 section_iterator
section_end() const override
;
364 uint8_t getBytesInAddress() const override
;
366 StringRef
getFileFormatName() const override
;
367 Triple::ArchType
getArch() const override
;
368 SubtargetFeatures
getFeatures() const override
{ return SubtargetFeatures(); }
369 Triple
getArchTriple(const char **McpuDefault
= nullptr) const;
371 relocation_iterator
section_rel_begin(unsigned Index
) const;
372 relocation_iterator
section_rel_end(unsigned Index
) const;
374 dice_iterator
begin_dices() const;
375 dice_iterator
end_dices() const;
377 load_command_iterator
begin_load_commands() const;
378 load_command_iterator
end_load_commands() const;
379 iterator_range
<load_command_iterator
> load_commands() const;
381 /// For use iterating over all exported symbols.
382 iterator_range
<export_iterator
> exports(Error
&Err
) const;
384 /// For use examining a trie not in a MachOObjectFile.
385 static iterator_range
<export_iterator
> exports(Error
&Err
,
386 ArrayRef
<uint8_t> Trie
,
387 const MachOObjectFile
*O
=
390 /// For use iterating over all rebase table entries.
391 iterator_range
<rebase_iterator
> rebaseTable(Error
&Err
);
393 /// For use examining rebase opcodes in a MachOObjectFile.
394 static iterator_range
<rebase_iterator
> rebaseTable(Error
&Err
,
396 ArrayRef
<uint8_t> Opcodes
,
399 /// For use iterating over all bind table entries.
400 iterator_range
<bind_iterator
> bindTable(Error
&Err
);
402 /// For use iterating over all lazy bind table entries.
403 iterator_range
<bind_iterator
> lazyBindTable(Error
&Err
);
405 /// For use iterating over all weak bind table entries.
406 iterator_range
<bind_iterator
> weakBindTable(Error
&Err
);
408 /// For use examining bind opcodes in a MachOObjectFile.
409 static iterator_range
<bind_iterator
> bindTable(Error
&Err
,
411 ArrayRef
<uint8_t> Opcodes
,
413 MachOBindEntry::Kind
);
415 /// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
416 /// validate a MachOBindEntry.
417 const char *BindEntryCheckSegAndOffset(int32_t SegIndex
, uint64_t SegOffset
,
418 bool endInvalid
) const {
419 return BindRebaseSectionTable
->checkSegAndOffset(SegIndex
, SegOffset
,
422 /// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
423 /// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode.
424 const char *BindEntryCheckCountAndSkip(uint32_t Count
, uint32_t Skip
,
425 uint8_t PointerSize
, int32_t SegIndex
,
426 uint64_t SegOffset
) const {
427 return BindRebaseSectionTable
->checkCountAndSkip(Count
, Skip
, PointerSize
,
428 SegIndex
, SegOffset
);
431 /// For use with a SegIndex,SegOffset pair in MachORebaseEntry::moveNext() to
432 /// validate a MachORebaseEntry.
433 const char *RebaseEntryCheckSegAndOffset(int32_t SegIndex
, uint64_t SegOffset
,
434 bool endInvalid
) const {
435 return BindRebaseSectionTable
->checkSegAndOffset(SegIndex
, SegOffset
,
438 /// For use in MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
439 /// the REBASE_OPCODE_DO_*_TIMES* opcodes.
440 const char *RebaseEntryCheckCountAndSkip(uint32_t Count
, uint32_t Skip
,
441 uint8_t PointerSize
, int32_t SegIndex
,
442 uint64_t SegOffset
) const {
443 return BindRebaseSectionTable
->checkCountAndSkip(Count
, Skip
, PointerSize
,
444 SegIndex
, SegOffset
);
447 /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to
448 /// get the segment name.
449 StringRef
BindRebaseSegmentName(int32_t SegIndex
) const {
450 return BindRebaseSectionTable
->segmentName(SegIndex
);
453 /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
454 /// Rebase entry to get the section name.
455 StringRef
BindRebaseSectionName(uint32_t SegIndex
, uint64_t SegOffset
) const {
456 return BindRebaseSectionTable
->sectionName(SegIndex
, SegOffset
);
459 /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
460 /// Rebase entry to get the address.
461 uint64_t BindRebaseAddress(uint32_t SegIndex
, uint64_t SegOffset
) const {
462 return BindRebaseSectionTable
->address(SegIndex
, SegOffset
);
465 // In a MachO file, sections have a segment name. This is used in the .o
466 // files. They have a single segment, but this field specifies which segment
467 // a section should be put in the final object.
468 StringRef
getSectionFinalSegmentName(DataRefImpl Sec
) const;
470 // Names are stored as 16 bytes. These returns the raw 16 bytes without
471 // interpreting them as a C string.
472 ArrayRef
<char> getSectionRawName(DataRefImpl Sec
) const;
473 ArrayRef
<char> getSectionRawFinalSegmentName(DataRefImpl Sec
) const;
475 // MachO specific Info about relocations.
476 bool isRelocationScattered(const MachO::any_relocation_info
&RE
) const;
477 unsigned getPlainRelocationSymbolNum(
478 const MachO::any_relocation_info
&RE
) const;
479 bool getPlainRelocationExternal(const MachO::any_relocation_info
&RE
) const;
480 bool getScatteredRelocationScattered(
481 const MachO::any_relocation_info
&RE
) const;
482 uint32_t getScatteredRelocationValue(
483 const MachO::any_relocation_info
&RE
) const;
484 uint32_t getScatteredRelocationType(
485 const MachO::any_relocation_info
&RE
) const;
486 unsigned getAnyRelocationAddress(const MachO::any_relocation_info
&RE
) const;
487 unsigned getAnyRelocationPCRel(const MachO::any_relocation_info
&RE
) const;
488 unsigned getAnyRelocationLength(const MachO::any_relocation_info
&RE
) const;
489 unsigned getAnyRelocationType(const MachO::any_relocation_info
&RE
) const;
490 SectionRef
getAnyRelocationSection(const MachO::any_relocation_info
&RE
) const;
492 // MachO specific structures.
493 MachO::section
getSection(DataRefImpl DRI
) const;
494 MachO::section_64
getSection64(DataRefImpl DRI
) const;
495 MachO::section
getSection(const LoadCommandInfo
&L
, unsigned Index
) const;
496 MachO::section_64
getSection64(const LoadCommandInfo
&L
,unsigned Index
) const;
497 MachO::nlist
getSymbolTableEntry(DataRefImpl DRI
) const;
498 MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI
) const;
500 MachO::linkedit_data_command
501 getLinkeditDataLoadCommand(const LoadCommandInfo
&L
) const;
502 MachO::segment_command
503 getSegmentLoadCommand(const LoadCommandInfo
&L
) const;
504 MachO::segment_command_64
505 getSegment64LoadCommand(const LoadCommandInfo
&L
) const;
506 MachO::linker_option_command
507 getLinkerOptionLoadCommand(const LoadCommandInfo
&L
) const;
508 MachO::version_min_command
509 getVersionMinLoadCommand(const LoadCommandInfo
&L
) const;
511 getNoteLoadCommand(const LoadCommandInfo
&L
) const;
512 MachO::build_version_command
513 getBuildVersionLoadCommand(const LoadCommandInfo
&L
) const;
514 MachO::build_tool_version
515 getBuildToolVersion(unsigned index
) const;
517 getDylibIDLoadCommand(const LoadCommandInfo
&L
) const;
518 MachO::dyld_info_command
519 getDyldInfoLoadCommand(const LoadCommandInfo
&L
) const;
520 MachO::dylinker_command
521 getDylinkerCommand(const LoadCommandInfo
&L
) const;
523 getUuidCommand(const LoadCommandInfo
&L
) const;
525 getRpathCommand(const LoadCommandInfo
&L
) const;
526 MachO::source_version_command
527 getSourceVersionCommand(const LoadCommandInfo
&L
) const;
528 MachO::entry_point_command
529 getEntryPointCommand(const LoadCommandInfo
&L
) const;
530 MachO::encryption_info_command
531 getEncryptionInfoCommand(const LoadCommandInfo
&L
) const;
532 MachO::encryption_info_command_64
533 getEncryptionInfoCommand64(const LoadCommandInfo
&L
) const;
534 MachO::sub_framework_command
535 getSubFrameworkCommand(const LoadCommandInfo
&L
) const;
536 MachO::sub_umbrella_command
537 getSubUmbrellaCommand(const LoadCommandInfo
&L
) const;
538 MachO::sub_library_command
539 getSubLibraryCommand(const LoadCommandInfo
&L
) const;
540 MachO::sub_client_command
541 getSubClientCommand(const LoadCommandInfo
&L
) const;
542 MachO::routines_command
543 getRoutinesCommand(const LoadCommandInfo
&L
) const;
544 MachO::routines_command_64
545 getRoutinesCommand64(const LoadCommandInfo
&L
) const;
546 MachO::thread_command
547 getThreadCommand(const LoadCommandInfo
&L
) const;
549 MachO::any_relocation_info
getRelocation(DataRefImpl Rel
) const;
550 MachO::data_in_code_entry
getDice(DataRefImpl Rel
) const;
551 const MachO::mach_header
&getHeader() const;
552 const MachO::mach_header_64
&getHeader64() const;
554 getIndirectSymbolTableEntry(const MachO::dysymtab_command
&DLC
,
555 unsigned Index
) const;
556 MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset
,
557 unsigned Index
) const;
558 MachO::symtab_command
getSymtabLoadCommand() const;
559 MachO::dysymtab_command
getDysymtabLoadCommand() const;
560 MachO::linkedit_data_command
getDataInCodeLoadCommand() const;
561 MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const;
562 ArrayRef
<uint8_t> getDyldInfoRebaseOpcodes() const;
563 ArrayRef
<uint8_t> getDyldInfoBindOpcodes() const;
564 ArrayRef
<uint8_t> getDyldInfoWeakBindOpcodes() const;
565 ArrayRef
<uint8_t> getDyldInfoLazyBindOpcodes() const;
566 ArrayRef
<uint8_t> getDyldInfoExportsTrie() const;
567 ArrayRef
<uint8_t> getUuid() const;
569 StringRef
getStringTableData() const;
570 bool is64Bit() const;
571 void ReadULEB128s(uint64_t Index
, SmallVectorImpl
<uint64_t> &Out
) const;
573 static StringRef
guessLibraryShortName(StringRef Name
, bool &isFramework
,
576 static Triple::ArchType
getArch(uint32_t CPUType
);
577 static Triple
getArchTriple(uint32_t CPUType
, uint32_t CPUSubType
,
578 const char **McpuDefault
= nullptr,
579 const char **ArchFlag
= nullptr);
580 static bool isValidArch(StringRef ArchFlag
);
581 static Triple
getHostArch();
583 bool isRelocatableObject() const override
;
585 StringRef
mapDebugSectionName(StringRef Name
) const override
;
587 bool hasPageZeroSegment() const { return HasPageZeroSegment
; }
589 static bool classof(const Binary
*v
) {
594 getVersionMinMajor(MachO::version_min_command
&C
, bool SDK
) {
595 uint32_t VersionOrSDK
= (SDK
) ? C
.sdk
: C
.version
;
596 return (VersionOrSDK
>> 16) & 0xffff;
600 getVersionMinMinor(MachO::version_min_command
&C
, bool SDK
) {
601 uint32_t VersionOrSDK
= (SDK
) ? C
.sdk
: C
.version
;
602 return (VersionOrSDK
>> 8) & 0xff;
606 getVersionMinUpdate(MachO::version_min_command
&C
, bool SDK
) {
607 uint32_t VersionOrSDK
= (SDK
) ? C
.sdk
: C
.version
;
608 return VersionOrSDK
& 0xff;
611 static std::string
getBuildPlatform(uint32_t platform
) {
613 case MachO::PLATFORM_MACOS
: return "macos";
614 case MachO::PLATFORM_IOS
: return "ios";
615 case MachO::PLATFORM_TVOS
: return "tvos";
616 case MachO::PLATFORM_WATCHOS
: return "watchos";
617 case MachO::PLATFORM_BRIDGEOS
: return "bridgeos";
618 case MachO::PLATFORM_IOSSIMULATOR
: return "iossimulator";
619 case MachO::PLATFORM_TVOSSIMULATOR
: return "tvossimulator";
620 case MachO::PLATFORM_WATCHOSSIMULATOR
: return "watchossimulator";
623 raw_string_ostream
ss(ret
);
624 ss
<< format_hex(platform
, 8, true);
629 static std::string
getBuildTool(uint32_t tools
) {
631 case MachO::TOOL_CLANG
: return "clang";
632 case MachO::TOOL_SWIFT
: return "swift";
633 case MachO::TOOL_LD
: return "ld";
636 raw_string_ostream
ss(ret
);
637 ss
<< format_hex(tools
, 8, true);
642 static std::string
getVersionString(uint32_t version
) {
643 uint32_t major
= (version
>> 16) & 0xffff;
644 uint32_t minor
= (version
>> 8) & 0xff;
645 uint32_t update
= version
& 0xff;
647 SmallString
<32> Version
;
648 Version
= utostr(major
) + "." + utostr(minor
);
650 Version
+= "." + utostr(update
);
651 return Version
.str();
655 MachOObjectFile(MemoryBufferRef Object
, bool IsLittleEndian
, bool Is64Bits
,
656 Error
&Err
, uint32_t UniversalCputype
= 0,
657 uint32_t UniversalIndex
= 0);
659 uint64_t getSymbolValueImpl(DataRefImpl Symb
) const override
;
662 MachO::mach_header_64 Header64
;
663 MachO::mach_header Header
;
665 using SectionList
= SmallVector
<const char*, 1>;
666 SectionList Sections
;
667 using LibraryList
= SmallVector
<const char*, 1>;
668 LibraryList Libraries
;
669 LoadCommandList LoadCommands
;
670 using LibraryShortName
= SmallVector
<StringRef
, 1>;
671 using BuildToolList
= SmallVector
<const char*, 1>;
672 BuildToolList BuildTools
;
673 mutable LibraryShortName LibrariesShortNames
;
674 std::unique_ptr
<BindRebaseSegInfo
> BindRebaseSectionTable
;
675 const char *SymtabLoadCmd
= nullptr;
676 const char *DysymtabLoadCmd
= nullptr;
677 const char *DataInCodeLoadCmd
= nullptr;
678 const char *LinkOptHintsLoadCmd
= nullptr;
679 const char *DyldInfoLoadCmd
= nullptr;
680 const char *UuidLoadCmd
= nullptr;
681 bool HasPageZeroSegment
= false;
685 inline DiceRef::DiceRef(DataRefImpl DiceP
, const ObjectFile
*Owner
)
686 : DicePimpl(DiceP
) , OwningObject(Owner
) {}
688 inline bool DiceRef::operator==(const DiceRef
&Other
) const {
689 return DicePimpl
== Other
.DicePimpl
;
692 inline bool DiceRef::operator<(const DiceRef
&Other
) const {
693 return DicePimpl
< Other
.DicePimpl
;
696 inline void DiceRef::moveNext() {
697 const MachO::data_in_code_entry
*P
=
698 reinterpret_cast<const MachO::data_in_code_entry
*>(DicePimpl
.p
);
699 DicePimpl
.p
= reinterpret_cast<uintptr_t>(P
+ 1);
702 // Since a Mach-O data in code reference, a DiceRef, can only be created when
703 // the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for
704 // the methods that get the values of the fields of the reference.
706 inline std::error_code
DiceRef::getOffset(uint32_t &Result
) const {
707 const MachOObjectFile
*MachOOF
=
708 static_cast<const MachOObjectFile
*>(OwningObject
);
709 MachO::data_in_code_entry Dice
= MachOOF
->getDice(DicePimpl
);
710 Result
= Dice
.offset
;
711 return std::error_code();
714 inline std::error_code
DiceRef::getLength(uint16_t &Result
) const {
715 const MachOObjectFile
*MachOOF
=
716 static_cast<const MachOObjectFile
*>(OwningObject
);
717 MachO::data_in_code_entry Dice
= MachOOF
->getDice(DicePimpl
);
718 Result
= Dice
.length
;
719 return std::error_code();
722 inline std::error_code
DiceRef::getKind(uint16_t &Result
) const {
723 const MachOObjectFile
*MachOOF
=
724 static_cast<const MachOObjectFile
*>(OwningObject
);
725 MachO::data_in_code_entry Dice
= MachOOF
->getDice(DicePimpl
);
727 return std::error_code();
730 inline DataRefImpl
DiceRef::getRawDataRefImpl() const {
734 inline const ObjectFile
*DiceRef::getObjectFile() const {
738 } // end namespace object
739 } // end namespace llvm
741 #endif // LLVM_OBJECT_MACHO_H