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