xref: /freebsd-src/contrib/llvm-project/llvm/lib/ObjCopy/MachO/MachOObject.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
181ad6265SDimitry Andric //===- MachOObject.h - Mach-O object file model -----------------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #ifndef LLVM_LIB_OBJCOPY_MACHO_MACHOOBJECT_H
1081ad6265SDimitry Andric #define LLVM_LIB_OBJCOPY_MACHO_MACHOOBJECT_H
1181ad6265SDimitry Andric 
1281ad6265SDimitry Andric #include "llvm/ADT/StringRef.h"
1381ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
1481ad6265SDimitry Andric #include "llvm/MC/StringTableBuilder.h"
1581ad6265SDimitry Andric #include "llvm/ObjectYAML/DWARFYAML.h"
1681ad6265SDimitry Andric #include "llvm/Support/StringSaver.h"
1781ad6265SDimitry Andric #include "llvm/Support/YAMLTraits.h"
1881ad6265SDimitry Andric #include <cstdint>
1981ad6265SDimitry Andric #include <string>
2081ad6265SDimitry Andric #include <vector>
2181ad6265SDimitry Andric 
2281ad6265SDimitry Andric namespace llvm {
2381ad6265SDimitry Andric namespace objcopy {
2481ad6265SDimitry Andric namespace macho {
2581ad6265SDimitry Andric 
2681ad6265SDimitry Andric struct MachHeader {
2781ad6265SDimitry Andric   uint32_t Magic;
2881ad6265SDimitry Andric   uint32_t CPUType;
2981ad6265SDimitry Andric   uint32_t CPUSubType;
3081ad6265SDimitry Andric   uint32_t FileType;
3181ad6265SDimitry Andric   uint32_t NCmds;
3281ad6265SDimitry Andric   uint32_t SizeOfCmds;
3381ad6265SDimitry Andric   uint32_t Flags;
3481ad6265SDimitry Andric   uint32_t Reserved = 0;
3581ad6265SDimitry Andric };
3681ad6265SDimitry Andric 
3781ad6265SDimitry Andric struct RelocationInfo;
3881ad6265SDimitry Andric struct Section {
3981ad6265SDimitry Andric   uint32_t Index;
4081ad6265SDimitry Andric   std::string Segname;
4181ad6265SDimitry Andric   std::string Sectname;
4281ad6265SDimitry Andric   // CanonicalName is a string formatted as “<Segname>,<Sectname>".
4381ad6265SDimitry Andric   std::string CanonicalName;
4481ad6265SDimitry Andric   uint64_t Addr = 0;
4581ad6265SDimitry Andric   uint64_t Size = 0;
4681ad6265SDimitry Andric   // Offset in the input file.
47bdd1243dSDimitry Andric   std::optional<uint32_t> OriginalOffset;
4881ad6265SDimitry Andric   uint32_t Offset = 0;
4981ad6265SDimitry Andric   uint32_t Align = 0;
5081ad6265SDimitry Andric   uint32_t RelOff = 0;
5181ad6265SDimitry Andric   uint32_t NReloc = 0;
5281ad6265SDimitry Andric   uint32_t Flags = 0;
5381ad6265SDimitry Andric   uint32_t Reserved1 = 0;
5481ad6265SDimitry Andric   uint32_t Reserved2 = 0;
5581ad6265SDimitry Andric   uint32_t Reserved3 = 0;
5681ad6265SDimitry Andric   StringRef Content;
5781ad6265SDimitry Andric   std::vector<RelocationInfo> Relocations;
5881ad6265SDimitry Andric 
59bdd1243dSDimitry Andric   Section(StringRef SegName, StringRef SectName);
6081ad6265SDimitry Andric 
61bdd1243dSDimitry Andric   Section(StringRef SegName, StringRef SectName, StringRef Content);
6281ad6265SDimitry Andric 
getTypeSection6381ad6265SDimitry Andric   MachO::SectionType getType() const {
6481ad6265SDimitry Andric     return static_cast<MachO::SectionType>(Flags & MachO::SECTION_TYPE);
6581ad6265SDimitry Andric   }
6681ad6265SDimitry Andric 
isVirtualSectionSection6781ad6265SDimitry Andric   bool isVirtualSection() const {
6881ad6265SDimitry Andric     return (getType() == MachO::S_ZEROFILL ||
6981ad6265SDimitry Andric             getType() == MachO::S_GB_ZEROFILL ||
7081ad6265SDimitry Andric             getType() == MachO::S_THREAD_LOCAL_ZEROFILL);
7181ad6265SDimitry Andric   }
7281ad6265SDimitry Andric 
hasValidOffsetSection7381ad6265SDimitry Andric   bool hasValidOffset() const {
7481ad6265SDimitry Andric     return !(isVirtualSection() || (OriginalOffset && *OriginalOffset == 0));
7581ad6265SDimitry Andric   }
7681ad6265SDimitry Andric };
7781ad6265SDimitry Andric 
7881ad6265SDimitry Andric struct LoadCommand {
7981ad6265SDimitry Andric   // The type MachO::macho_load_command is defined in llvm/BinaryFormat/MachO.h
8081ad6265SDimitry Andric   // and it is a union of all the structs corresponding to various load
8181ad6265SDimitry Andric   // commands.
8281ad6265SDimitry Andric   MachO::macho_load_command MachOLoadCommand;
8381ad6265SDimitry Andric 
8481ad6265SDimitry Andric   // The raw content of the payload of the load command (located right after the
8581ad6265SDimitry Andric   // corresponding struct). In some cases it is either empty or can be
8681ad6265SDimitry Andric   // copied-over without digging into its structure.
8781ad6265SDimitry Andric   std::vector<uint8_t> Payload;
8881ad6265SDimitry Andric 
8981ad6265SDimitry Andric   // Some load commands can contain (inside the payload) an array of sections,
9081ad6265SDimitry Andric   // though the contents of the sections are stored separately. The struct
9181ad6265SDimitry Andric   // Section describes only sections' metadata and where to find the
9281ad6265SDimitry Andric   // corresponding content inside the binary.
9381ad6265SDimitry Andric   std::vector<std::unique_ptr<Section>> Sections;
9481ad6265SDimitry Andric 
9581ad6265SDimitry Andric   // Returns the segment name if the load command is a segment command.
96bdd1243dSDimitry Andric   std::optional<StringRef> getSegmentName() const;
9781ad6265SDimitry Andric 
9881ad6265SDimitry Andric   // Returns the segment vm address if the load command is a segment command.
99bdd1243dSDimitry Andric   std::optional<uint64_t> getSegmentVMAddr() const;
10081ad6265SDimitry Andric };
10181ad6265SDimitry Andric 
10281ad6265SDimitry Andric // A symbol information. Fields which starts with "n_" are same as them in the
10381ad6265SDimitry Andric // nlist.
10481ad6265SDimitry Andric struct SymbolEntry {
10581ad6265SDimitry Andric   std::string Name;
10681ad6265SDimitry Andric   bool Referenced = false;
10781ad6265SDimitry Andric   uint32_t Index;
10881ad6265SDimitry Andric   uint8_t n_type;
10981ad6265SDimitry Andric   uint8_t n_sect;
11081ad6265SDimitry Andric   uint16_t n_desc;
11181ad6265SDimitry Andric   uint64_t n_value;
11281ad6265SDimitry Andric 
isExternalSymbolSymbolEntry11381ad6265SDimitry Andric   bool isExternalSymbol() const { return n_type & MachO::N_EXT; }
11481ad6265SDimitry Andric 
isLocalSymbolSymbolEntry11581ad6265SDimitry Andric   bool isLocalSymbol() const { return !isExternalSymbol(); }
11681ad6265SDimitry Andric 
isUndefinedSymbolSymbolEntry11781ad6265SDimitry Andric   bool isUndefinedSymbol() const {
11881ad6265SDimitry Andric     return (n_type & MachO::N_TYPE) == MachO::N_UNDF;
11981ad6265SDimitry Andric   }
12081ad6265SDimitry Andric 
isSwiftSymbolSymbolEntry12181ad6265SDimitry Andric   bool isSwiftSymbol() const {
122*5f757f3fSDimitry Andric     return StringRef(Name).starts_with("_$s") ||
123*5f757f3fSDimitry Andric            StringRef(Name).starts_with("_$S");
12481ad6265SDimitry Andric   }
12581ad6265SDimitry Andric 
sectionSymbolEntry126bdd1243dSDimitry Andric   std::optional<uint32_t> section() const {
127bdd1243dSDimitry Andric     return n_sect == MachO::NO_SECT ? std::nullopt
128bdd1243dSDimitry Andric                                     : std::optional<uint32_t>(n_sect);
12981ad6265SDimitry Andric   }
13081ad6265SDimitry Andric };
13181ad6265SDimitry Andric 
13281ad6265SDimitry Andric /// The location of the symbol table inside the binary is described by LC_SYMTAB
13381ad6265SDimitry Andric /// load command.
13481ad6265SDimitry Andric struct SymbolTable {
13581ad6265SDimitry Andric   std::vector<std::unique_ptr<SymbolEntry>> Symbols;
13681ad6265SDimitry Andric 
13781ad6265SDimitry Andric   using iterator = pointee_iterator<
13881ad6265SDimitry Andric       std::vector<std::unique_ptr<SymbolEntry>>::const_iterator>;
13981ad6265SDimitry Andric 
beginSymbolTable14081ad6265SDimitry Andric   iterator begin() const { return iterator(Symbols.begin()); }
endSymbolTable14181ad6265SDimitry Andric   iterator end() const { return iterator(Symbols.end()); }
14281ad6265SDimitry Andric 
14381ad6265SDimitry Andric   const SymbolEntry *getSymbolByIndex(uint32_t Index) const;
14481ad6265SDimitry Andric   SymbolEntry *getSymbolByIndex(uint32_t Index);
14581ad6265SDimitry Andric   void removeSymbols(
14681ad6265SDimitry Andric       function_ref<bool(const std::unique_ptr<SymbolEntry> &)> ToRemove);
14781ad6265SDimitry Andric };
14881ad6265SDimitry Andric 
14981ad6265SDimitry Andric struct IndirectSymbolEntry {
15081ad6265SDimitry Andric   // The original value in an indirect symbol table. Higher bits encode extra
15181ad6265SDimitry Andric   // information (INDIRECT_SYMBOL_LOCAL and INDIRECT_SYMBOL_ABS).
15281ad6265SDimitry Andric   uint32_t OriginalIndex;
153bdd1243dSDimitry Andric   /// The Symbol referenced by this entry. It's std::nullopt if the index is
15481ad6265SDimitry Andric   /// INDIRECT_SYMBOL_LOCAL or INDIRECT_SYMBOL_ABS.
155bdd1243dSDimitry Andric   std::optional<SymbolEntry *> Symbol;
15681ad6265SDimitry Andric 
IndirectSymbolEntryIndirectSymbolEntry157bdd1243dSDimitry Andric   IndirectSymbolEntry(uint32_t OriginalIndex,
158bdd1243dSDimitry Andric                       std::optional<SymbolEntry *> Symbol)
15981ad6265SDimitry Andric       : OriginalIndex(OriginalIndex), Symbol(Symbol) {}
16081ad6265SDimitry Andric };
16181ad6265SDimitry Andric 
16281ad6265SDimitry Andric struct IndirectSymbolTable {
16381ad6265SDimitry Andric   std::vector<IndirectSymbolEntry> Symbols;
16481ad6265SDimitry Andric };
16581ad6265SDimitry Andric 
16681ad6265SDimitry Andric /// The location of the string table inside the binary is described by LC_SYMTAB
16781ad6265SDimitry Andric /// load command.
16881ad6265SDimitry Andric struct StringTable {
16981ad6265SDimitry Andric   std::vector<std::string> Strings;
17081ad6265SDimitry Andric };
17181ad6265SDimitry Andric 
17281ad6265SDimitry Andric struct RelocationInfo {
17381ad6265SDimitry Andric   // The referenced symbol entry. Set if !Scattered && Extern.
174bdd1243dSDimitry Andric   std::optional<const SymbolEntry *> Symbol;
17581ad6265SDimitry Andric   // The referenced section. Set if !Scattered && !Extern.
176bdd1243dSDimitry Andric   std::optional<const Section *> Sec;
17781ad6265SDimitry Andric   // True if Info is a scattered_relocation_info.
17881ad6265SDimitry Andric   bool Scattered;
17981ad6265SDimitry Andric   // True if the type is an ADDEND. r_symbolnum holds the addend instead of a
18081ad6265SDimitry Andric   // symbol index.
18181ad6265SDimitry Andric   bool IsAddend;
18281ad6265SDimitry Andric   // True if the r_symbolnum points to a section number (i.e. r_extern=0).
18381ad6265SDimitry Andric   bool Extern;
18481ad6265SDimitry Andric   MachO::any_relocation_info Info;
18581ad6265SDimitry Andric 
getPlainRelocationSymbolNumRelocationInfo18681ad6265SDimitry Andric   unsigned getPlainRelocationSymbolNum(bool IsLittleEndian) {
18781ad6265SDimitry Andric     if (IsLittleEndian)
18881ad6265SDimitry Andric       return Info.r_word1 & 0xffffff;
18981ad6265SDimitry Andric     return Info.r_word1 >> 8;
19081ad6265SDimitry Andric   }
19181ad6265SDimitry Andric 
setPlainRelocationSymbolNumRelocationInfo19281ad6265SDimitry Andric   void setPlainRelocationSymbolNum(unsigned SymbolNum, bool IsLittleEndian) {
19381ad6265SDimitry Andric     assert(SymbolNum < (1 << 24) && "SymbolNum out of range");
19481ad6265SDimitry Andric     if (IsLittleEndian)
19581ad6265SDimitry Andric       Info.r_word1 = (Info.r_word1 & ~0x00ffffff) | SymbolNum;
19681ad6265SDimitry Andric     else
19781ad6265SDimitry Andric       Info.r_word1 = (Info.r_word1 & ~0xffffff00) | (SymbolNum << 8);
19881ad6265SDimitry Andric   }
19981ad6265SDimitry Andric };
20081ad6265SDimitry Andric 
20181ad6265SDimitry Andric /// The location of the rebase info inside the binary is described by
20281ad6265SDimitry Andric /// LC_DYLD_INFO load command. Dyld rebases an image whenever dyld loads it at
20381ad6265SDimitry Andric /// an address different from its preferred address.  The rebase information is
20481ad6265SDimitry Andric /// a stream of byte sized opcodes whose symbolic names start with
20581ad6265SDimitry Andric /// REBASE_OPCODE_. Conceptually the rebase information is a table of tuples:
20681ad6265SDimitry Andric ///   <seg-index, seg-offset, type>
20781ad6265SDimitry Andric /// The opcodes are a compressed way to encode the table by only
20881ad6265SDimitry Andric /// encoding when a column changes.  In addition simple patterns
20981ad6265SDimitry Andric /// like "every n'th offset for m times" can be encoded in a few
21081ad6265SDimitry Andric /// bytes.
21181ad6265SDimitry Andric struct RebaseInfo {
21281ad6265SDimitry Andric   // At the moment we do not parse this info (and it is simply copied over),
21381ad6265SDimitry Andric   // but the proper support will be added later.
21481ad6265SDimitry Andric   ArrayRef<uint8_t> Opcodes;
21581ad6265SDimitry Andric };
21681ad6265SDimitry Andric 
21781ad6265SDimitry Andric /// The location of the bind info inside the binary is described by
21881ad6265SDimitry Andric /// LC_DYLD_INFO load command. Dyld binds an image during the loading process,
21981ad6265SDimitry Andric /// if the image requires any pointers to be initialized to symbols in other
22081ad6265SDimitry Andric /// images. The bind information is a stream of byte sized opcodes whose
22181ad6265SDimitry Andric /// symbolic names start with BIND_OPCODE_. Conceptually the bind information is
22281ad6265SDimitry Andric /// a table of tuples: <seg-index, seg-offset, type, symbol-library-ordinal,
22381ad6265SDimitry Andric /// symbol-name, addend> The opcodes are a compressed way to encode the table by
22481ad6265SDimitry Andric /// only encoding when a column changes.  In addition simple patterns like for
22581ad6265SDimitry Andric /// runs of pointers initialized to the same value can be encoded in a few
22681ad6265SDimitry Andric /// bytes.
22781ad6265SDimitry Andric struct BindInfo {
22881ad6265SDimitry Andric   // At the moment we do not parse this info (and it is simply copied over),
22981ad6265SDimitry Andric   // but the proper support will be added later.
23081ad6265SDimitry Andric   ArrayRef<uint8_t> Opcodes;
23181ad6265SDimitry Andric };
23281ad6265SDimitry Andric 
23381ad6265SDimitry Andric /// The location of the weak bind info inside the binary is described by
23481ad6265SDimitry Andric /// LC_DYLD_INFO load command. Some C++ programs require dyld to unique symbols
23581ad6265SDimitry Andric /// so that all images in the process use the same copy of some code/data. This
23681ad6265SDimitry Andric /// step is done after binding. The content of the weak_bind info is an opcode
23781ad6265SDimitry Andric /// stream like the bind_info.  But it is sorted alphabetically by symbol name.
23881ad6265SDimitry Andric /// This enable dyld to walk all images with weak binding information in order
23981ad6265SDimitry Andric /// and look for collisions.  If there are no collisions, dyld does no updating.
24081ad6265SDimitry Andric /// That means that some fixups are also encoded in the bind_info.  For
24181ad6265SDimitry Andric /// instance, all calls to "operator new" are first bound to libstdc++.dylib
24281ad6265SDimitry Andric /// using the information in bind_info.  Then if some image overrides operator
24381ad6265SDimitry Andric /// new that is detected when the weak_bind information is processed and the
24481ad6265SDimitry Andric /// call to operator new is then rebound.
24581ad6265SDimitry Andric struct WeakBindInfo {
24681ad6265SDimitry Andric   // At the moment we do not parse this info (and it is simply copied over),
24781ad6265SDimitry Andric   // but the proper support will be added later.
24881ad6265SDimitry Andric   ArrayRef<uint8_t> Opcodes;
24981ad6265SDimitry Andric };
25081ad6265SDimitry Andric 
25181ad6265SDimitry Andric /// The location of the lazy bind info inside the binary is described by
25281ad6265SDimitry Andric /// LC_DYLD_INFO load command. Some uses of external symbols do not need to be
25381ad6265SDimitry Andric /// bound immediately. Instead they can be lazily bound on first use.  The
25481ad6265SDimitry Andric /// lazy_bind contains a stream of BIND opcodes to bind all lazy symbols. Normal
25581ad6265SDimitry Andric /// use is that dyld ignores the lazy_bind section when loading an image.
25681ad6265SDimitry Andric /// Instead the static linker arranged for the lazy pointer to initially point
25781ad6265SDimitry Andric /// to a helper function which pushes the offset into the lazy_bind area for the
25881ad6265SDimitry Andric /// symbol needing to be bound, then jumps to dyld which simply adds the offset
25981ad6265SDimitry Andric /// to lazy_bind_off to get the information on what to bind.
26081ad6265SDimitry Andric struct LazyBindInfo {
26181ad6265SDimitry Andric   ArrayRef<uint8_t> Opcodes;
26281ad6265SDimitry Andric };
26381ad6265SDimitry Andric 
26481ad6265SDimitry Andric /// The location of the export info inside the binary is described by
26581ad6265SDimitry Andric /// LC_DYLD_INFO load command. The symbols exported by a dylib are encoded in a
26681ad6265SDimitry Andric /// trie.  This is a compact representation that factors out common prefixes. It
26781ad6265SDimitry Andric /// also reduces LINKEDIT pages in RAM because it encodes all information (name,
26881ad6265SDimitry Andric /// address, flags) in one small, contiguous range. The export area is a stream
26981ad6265SDimitry Andric /// of nodes.  The first node sequentially is the start node for the trie. Nodes
27081ad6265SDimitry Andric /// for a symbol start with a uleb128 that is the length of the exported symbol
27181ad6265SDimitry Andric /// information for the string so far. If there is no exported symbol, the node
27281ad6265SDimitry Andric /// starts with a zero byte. If there is exported info, it follows the length.
27381ad6265SDimitry Andric /// First is a uleb128 containing flags. Normally, it is followed by
27481ad6265SDimitry Andric /// a uleb128 encoded offset which is location of the content named
27581ad6265SDimitry Andric /// by the symbol from the mach_header for the image.  If the flags
27681ad6265SDimitry Andric /// is EXPORT_SYMBOL_FLAGS_REEXPORT, then following the flags is
27781ad6265SDimitry Andric /// a uleb128 encoded library ordinal, then a zero terminated
27881ad6265SDimitry Andric /// UTF8 string.  If the string is zero length, then the symbol
27981ad6265SDimitry Andric /// is re-export from the specified dylib with the same name.
28081ad6265SDimitry Andric /// If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following
28181ad6265SDimitry Andric /// the flags is two uleb128s: the stub offset and the resolver offset.
28281ad6265SDimitry Andric /// The stub is used by non-lazy pointers.  The resolver is used
28381ad6265SDimitry Andric /// by lazy pointers and must be called to get the actual address to use.
28481ad6265SDimitry Andric /// After the optional exported symbol information is a byte of
28581ad6265SDimitry Andric /// how many edges (0-255) that this node has leaving it,
28681ad6265SDimitry Andric /// followed by each edge.
28781ad6265SDimitry Andric /// Each edge is a zero terminated UTF8 of the addition chars
28881ad6265SDimitry Andric /// in the symbol, followed by a uleb128 offset for the node that
28981ad6265SDimitry Andric /// edge points to.
29081ad6265SDimitry Andric struct ExportInfo {
29181ad6265SDimitry Andric   ArrayRef<uint8_t> Trie;
29281ad6265SDimitry Andric };
29381ad6265SDimitry Andric 
29481ad6265SDimitry Andric struct LinkData {
29581ad6265SDimitry Andric   ArrayRef<uint8_t> Data;
29681ad6265SDimitry Andric };
29781ad6265SDimitry Andric 
29881ad6265SDimitry Andric struct Object {
29981ad6265SDimitry Andric   MachHeader Header;
30081ad6265SDimitry Andric   std::vector<LoadCommand> LoadCommands;
30181ad6265SDimitry Andric 
30281ad6265SDimitry Andric   SymbolTable SymTable;
30381ad6265SDimitry Andric   StringTable StrTable;
30481ad6265SDimitry Andric 
30581ad6265SDimitry Andric   RebaseInfo Rebases;
30681ad6265SDimitry Andric   BindInfo Binds;
30781ad6265SDimitry Andric   WeakBindInfo WeakBinds;
30881ad6265SDimitry Andric   LazyBindInfo LazyBinds;
30981ad6265SDimitry Andric   ExportInfo Exports;
31081ad6265SDimitry Andric   IndirectSymbolTable IndirectSymTable;
31181ad6265SDimitry Andric   LinkData DataInCode;
31281ad6265SDimitry Andric   LinkData LinkerOptimizationHint;
31381ad6265SDimitry Andric   LinkData FunctionStarts;
31481ad6265SDimitry Andric   LinkData ExportsTrie;
31581ad6265SDimitry Andric   LinkData ChainedFixups;
316bdd1243dSDimitry Andric   LinkData DylibCodeSignDRs;
31781ad6265SDimitry Andric 
318bdd1243dSDimitry Andric   std::optional<uint32_t> SwiftVersion;
31981ad6265SDimitry Andric 
32081ad6265SDimitry Andric   /// The index of LC_CODE_SIGNATURE load command if present.
321bdd1243dSDimitry Andric   std::optional<size_t> CodeSignatureCommandIndex;
322bdd1243dSDimitry Andric   /// The index of LC_DYLIB_CODE_SIGN_DRS load command if present.
323bdd1243dSDimitry Andric   std::optional<size_t> DylibCodeSignDRsIndex;
32481ad6265SDimitry Andric   /// The index of LC_SYMTAB load command if present.
325bdd1243dSDimitry Andric   std::optional<size_t> SymTabCommandIndex;
32681ad6265SDimitry Andric   /// The index of LC_DYLD_INFO or LC_DYLD_INFO_ONLY load command if present.
327bdd1243dSDimitry Andric   std::optional<size_t> DyLdInfoCommandIndex;
32881ad6265SDimitry Andric   /// The index LC_DYSYMTAB load command if present.
329bdd1243dSDimitry Andric   std::optional<size_t> DySymTabCommandIndex;
33081ad6265SDimitry Andric   /// The index LC_DATA_IN_CODE load command if present.
331bdd1243dSDimitry Andric   std::optional<size_t> DataInCodeCommandIndex;
33281ad6265SDimitry Andric   /// The index of LC_LINKER_OPTIMIZATIN_HINT load command if present.
333bdd1243dSDimitry Andric   std::optional<size_t> LinkerOptimizationHintCommandIndex;
33481ad6265SDimitry Andric   /// The index LC_FUNCTION_STARTS load command if present.
335bdd1243dSDimitry Andric   std::optional<size_t> FunctionStartsCommandIndex;
33681ad6265SDimitry Andric   /// The index LC_DYLD_CHAINED_FIXUPS load command if present.
337bdd1243dSDimitry Andric   std::optional<size_t> ChainedFixupsCommandIndex;
33881ad6265SDimitry Andric   /// The index LC_DYLD_EXPORTS_TRIE load command if present.
339bdd1243dSDimitry Andric   std::optional<size_t> ExportsTrieCommandIndex;
34081ad6265SDimitry Andric   /// The index of the LC_SEGMENT or LC_SEGMENT_64 load command
34181ad6265SDimitry Andric   /// corresponding to the __TEXT segment.
342bdd1243dSDimitry Andric   std::optional<size_t> TextSegmentCommandIndex;
34381ad6265SDimitry Andric 
34481ad6265SDimitry Andric   BumpPtrAllocator Alloc;
34581ad6265SDimitry Andric   StringSaver NewSectionsContents;
34681ad6265SDimitry Andric 
ObjectObject34781ad6265SDimitry Andric   Object() : NewSectionsContents(Alloc) {}
34881ad6265SDimitry Andric 
34981ad6265SDimitry Andric   Error
35081ad6265SDimitry Andric   removeSections(function_ref<bool(const std::unique_ptr<Section> &)> ToRemove);
35181ad6265SDimitry Andric 
35281ad6265SDimitry Andric   Error removeLoadCommands(function_ref<bool(const LoadCommand &)> ToRemove);
35381ad6265SDimitry Andric 
35481ad6265SDimitry Andric   void updateLoadCommandIndexes();
35581ad6265SDimitry Andric 
35681ad6265SDimitry Andric   /// Creates a new segment load command in the object and returns a reference
35781ad6265SDimitry Andric   /// to the newly created load command. The caller should verify that SegName
35881ad6265SDimitry Andric   /// is not too long (SegName.size() should be less than or equal to 16).
35981ad6265SDimitry Andric   LoadCommand &addSegment(StringRef SegName, uint64_t SegVMSize);
36081ad6265SDimitry Andric 
is64BitObject36181ad6265SDimitry Andric   bool is64Bit() const {
36281ad6265SDimitry Andric     return Header.Magic == MachO::MH_MAGIC_64 ||
36381ad6265SDimitry Andric            Header.Magic == MachO::MH_CIGAM_64;
36481ad6265SDimitry Andric   }
36581ad6265SDimitry Andric 
36681ad6265SDimitry Andric   uint64_t nextAvailableSegmentAddress() const;
36781ad6265SDimitry Andric };
36881ad6265SDimitry Andric 
36981ad6265SDimitry Andric } // end namespace macho
37081ad6265SDimitry Andric } // end namespace objcopy
37181ad6265SDimitry Andric } // end namespace llvm
37281ad6265SDimitry Andric 
37381ad6265SDimitry Andric #endif // LLVM_LIB_OBJCOPY_MACHO_MACHOOBJECT_H
374