brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.5 KiB · 5456f03 Raw
448 lines · c
1//===-- ObjectFileMachO.h ---------------------------------------*- C++ -*-===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_MACH_O_OBJECTFILEMACHO_H10#define LLDB_SOURCE_PLUGINS_OBJECTFILE_MACH_O_OBJECTFILEMACHO_H11 12#include "lldb/Core/Address.h"13#include "lldb/Host/SafeMachO.h"14#include "lldb/Symbol/ObjectFile.h"15#include "lldb/Symbol/SaveCoreOptions.h"16#include "lldb/Utility/FileSpec.h"17#include "lldb/Utility/FileSpecList.h"18#include "lldb/Utility/RangeMap.h"19#include "lldb/Utility/StreamString.h"20#include "lldb/Utility/UUID.h"21#include <optional>22 23// This class needs to be hidden as eventually belongs in a plugin that24// will export the ObjectFile protocol25class ObjectFileMachO : public lldb_private::ObjectFile {26public:27  ObjectFileMachO(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,28                  lldb::offset_t data_offset,29                  const lldb_private::FileSpec *file, lldb::offset_t offset,30                  lldb::offset_t length);31 32  ObjectFileMachO(const lldb::ModuleSP &module_sp,33                  lldb::WritableDataBufferSP data_sp,34                  const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);35 36  ~ObjectFileMachO() override = default;37 38  // Static Functions39  static void Initialize();40 41  static void Terminate();42 43  static llvm::StringRef GetPluginNameStatic() { return "mach-o"; }44 45  static llvm::StringRef GetPluginDescriptionStatic() {46    return "Mach-o object file reader (32 and 64 bit)";47  }48 49  static lldb_private::ObjectFile *50  CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,51                 lldb::offset_t data_offset, const lldb_private::FileSpec *file,52                 lldb::offset_t file_offset, lldb::offset_t length);53 54  static lldb_private::ObjectFile *CreateMemoryInstance(55      const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp,56      const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);57 58  static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,59                                        lldb::DataBufferSP &data_sp,60                                        lldb::offset_t data_offset,61                                        lldb::offset_t file_offset,62                                        lldb::offset_t length,63                                        lldb_private::ModuleSpecList &specs);64 65  static bool SaveCore(const lldb::ProcessSP &process_sp,66                       lldb_private::SaveCoreOptions &options,67                       lldb_private::Status &error);68 69  static bool MagicBytesMatch(lldb::DataBufferSP data_sp, lldb::addr_t offset,70                              lldb::addr_t length);71 72  // LLVM RTTI support73  static char ID;74  bool isA(const void *ClassID) const override {75    return ClassID == &ID || ObjectFile::isA(ClassID);76  }77  static bool classof(const ObjectFile *obj) { return obj->isA(&ID); }78 79  // Member Functions80  bool ParseHeader() override;81 82  bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value,83                      bool value_is_offset) override;84 85  lldb::ByteOrder GetByteOrder() const override;86 87  bool IsExecutable() const override;88 89  bool IsDynamicLoader() const;90 91  bool IsSharedCacheBinary() const;92 93  bool IsKext() const;94 95  uint32_t GetAddressByteSize() const override;96 97  lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;98 99  void ParseSymtab(lldb_private::Symtab &symtab) override;100 101  bool IsStripped() override;102 103  void CreateSections(lldb_private::SectionList &unified_section_list) override;104 105  void Dump(lldb_private::Stream *s) override;106 107  lldb_private::ArchSpec GetArchitecture() override;108 109  lldb_private::UUID GetUUID() override;110 111  uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;112 113  lldb_private::FileSpecList GetReExportedLibraries() override {114    return m_reexported_dylibs;115  }116 117  lldb_private::Address GetEntryPointAddress() override;118 119  lldb_private::Address GetBaseAddress() override;120 121  uint32_t GetNumThreadContexts() override;122 123  std::vector<std::tuple<lldb::offset_t, lldb::offset_t>>124  FindLC_NOTEByName(std::string name);125 126  std::string GetIdentifierString() override;127 128  lldb_private::AddressableBits GetAddressableBits() override;129 130  bool GetCorefileMainBinaryInfo(lldb::addr_t &value, bool &value_is_offset,131                                 lldb_private::UUID &uuid,132                                 ObjectFile::BinaryType &type) override;133 134  bool GetCorefileThreadExtraInfos(std::vector<lldb::tid_t> &tids) override;135 136  lldb_private::StructuredData::ObjectSP GetCorefileProcessMetadata() override;137 138  bool LoadCoreFileImages(lldb_private::Process &process) override;139 140  lldb::RegisterContextSP141  GetThreadContextAtIndex(uint32_t idx, lldb_private::Thread &thread) override;142 143  ObjectFile::Type CalculateType() override;144 145  ObjectFile::Strata CalculateStrata() override;146 147  llvm::VersionTuple GetVersion() override;148 149  llvm::VersionTuple GetMinimumOSVersion() override;150 151  llvm::VersionTuple GetSDKVersion() override;152 153  bool GetIsDynamicLinkEditor() override;154 155  bool CanTrustAddressRanges() override;156 157  static bool ParseHeader(lldb_private::DataExtractor &data,158                          lldb::offset_t *data_offset_ptr,159                          llvm::MachO::mach_header &header);160 161  bool AllowAssemblyEmulationUnwindPlans() override;162 163  lldb_private::Section *GetMachHeaderSection();164 165  bool IsGOTSection(const lldb_private::Section &section) const override;166 167  // PluginInterface protocol168  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }169 170protected:171  static lldb_private::UUID172  GetUUID(const llvm::MachO::mach_header &header,173          const lldb_private::DataExtractor &data,174          lldb::offset_t lc_offset); // Offset to the first load command175 176  static lldb_private::ArchSpec GetArchitecture(177      lldb::ModuleSP module_sp, const llvm::MachO::mach_header &header,178      const lldb_private::DataExtractor &data, lldb::offset_t lc_offset);179 180  /// Enumerate all ArchSpecs supported by this Mach-O file.181  ///182  /// On macOS one Mach-O slice can contain multiple load commands:183  /// One load command for being loaded into a macOS process and one184  /// load command for being loaded into a macCatalyst process. In185  /// contrast to ObjectContainerUniversalMachO, this is the same186  /// binary that can be loaded into different contexts.187  static void GetAllArchSpecs(const llvm::MachO::mach_header &header,188                              const lldb_private::DataExtractor &data,189                              lldb::offset_t lc_offset,190                              lldb_private::ModuleSpec &base_spec,191                              lldb_private::ModuleSpecList &all_specs);192 193  /// Intended for same-host arm device debugging where lldb needs to194  /// detect libraries in the shared cache and augment the nlist entries195  /// with an on-disk dyld_shared_cache file.  The process will record196  /// the shared cache UUID so the on-disk cache can be matched or rejected197  /// correctly.198  void GetProcessSharedCacheUUID(lldb_private::Process *,199                                 lldb::addr_t &base_addr,200                                 lldb_private::UUID &uuid);201 202  /// Intended for same-host arm device debugging where lldb will read203  /// shared cache libraries out of its own memory instead of the remote204  /// process' memory as an optimization.  If lldb's shared cache UUID205  /// does not match the process' shared cache UUID, this optimization206  /// should not be used.207  void GetLLDBSharedCacheUUID(lldb::addr_t &base_addir, lldb_private::UUID &uuid);208 209  lldb::addr_t CalculateSectionLoadAddressForMemoryImage(210      lldb::addr_t mach_header_load_address,211      const lldb_private::Section *mach_header_section,212      const lldb_private::Section *section);213 214  lldb_private::UUID215  GetSharedCacheUUID(lldb_private::FileSpec dyld_shared_cache,216                     const lldb::ByteOrder byte_order,217                     const uint32_t addr_byte_size);218 219  size_t ParseSymtab();220 221  typedef lldb_private::RangeVector<uint32_t, uint32_t, 8> EncryptedFileRanges;222  EncryptedFileRanges GetEncryptedFileRanges();223 224  struct SegmentParsingContext;225  void ProcessDysymtabCommand(const llvm::MachO::load_command &load_cmd,226                              lldb::offset_t offset);227  void ProcessSegmentCommand(const llvm::MachO::load_command &load_cmd,228                             lldb::offset_t offset, uint32_t cmd_idx,229                             SegmentParsingContext &context);230  void SanitizeSegmentCommand(llvm::MachO::segment_command_64 &seg_cmd,231                              uint32_t cmd_idx);232 233  bool SectionIsLoadable(const lldb_private::Section *section);234 235  /// A corefile may include metadata about all of the binaries that were236  /// present in the process when the corefile was taken.  This is only237  /// implemented for Mach-O files for now; we'll generalize it when we238  /// have other systems that can include the same.239  struct MachOCorefileImageEntry {240    std::string filename;241    lldb_private::UUID uuid;242    lldb::addr_t load_address = LLDB_INVALID_ADDRESS;243    lldb::addr_t slide = 0;244    bool currently_executing = false;245    std::vector<std::tuple<lldb_private::ConstString, lldb::addr_t>>246        segment_load_addresses;247  };248 249  struct LCNoteEntry {250    LCNoteEntry(uint32_t addr_byte_size, lldb::ByteOrder byte_order)251        : payload(lldb_private::Stream::eBinary, addr_byte_size, byte_order) {}252 253    std::string name;254    lldb::addr_t payload_file_offset = 0;255    lldb_private::StreamString payload;256  };257 258  struct MachOCorefileAllImageInfos {259    std::vector<MachOCorefileImageEntry> all_image_infos;260    bool IsValid() { return all_image_infos.size() > 0; }261  };262 263  // The LC_SYMTAB's symtab_command structure uses 32-bit file offsets264  // for two fields, but ObjectFileMachO needs to calculate the offsets265  // in virtual address layout from the start of the TEXT segment, and266  // that span may be larger than 4GB.267  struct SymtabCommandLargeOffsets {268    SymtabCommandLargeOffsets() {}269    SymtabCommandLargeOffsets(const llvm::MachO::symtab_command &in)270        : cmd(in.cmd), cmdsize(in.cmdsize), symoff(in.symoff), nsyms(in.nsyms),271          stroff(in.stroff), strsize(in.strsize) {}272    void operator=(const llvm::MachO::symtab_command &in) {273      cmd = in.cmd;274      cmdsize = in.cmdsize;275      symoff = in.symoff;276      nsyms = in.nsyms;277      stroff = in.stroff;278      strsize = in.strsize;279    }280    uint32_t cmd = 0;          /* LC_SYMTAB */281    uint32_t cmdsize = 0;      /* sizeof(struct symtab_command) */282    lldb::offset_t symoff = 0; /* symbol table offset */283    uint32_t nsyms = 0;        /* number of symbol table entries */284    lldb::offset_t stroff = 0; /* string table offset */285    uint32_t strsize = 0;      /* string table size in bytes */286  };287 288  // The LC_DYLD_INFO's dyld_info_command has 32-bit file offsets289  // that we will use as virtual address offsets, and may need to span290  // more than 4GB in virtual memory.291  struct DyldInfoCommandLargeOffsets {292    DyldInfoCommandLargeOffsets() {}293    DyldInfoCommandLargeOffsets(const llvm::MachO::dyld_info_command &in)294        : cmd(in.cmd), cmdsize(in.cmdsize), rebase_off(in.rebase_off),295          rebase_size(in.rebase_size), bind_off(in.bind_off),296          bind_size(in.bind_size), weak_bind_off(in.weak_bind_off),297          weak_bind_size(in.weak_bind_size), lazy_bind_off(in.lazy_bind_off),298          lazy_bind_size(in.lazy_bind_size), export_off(in.export_off),299          export_size(in.export_size) {}300 301    void operator=(const llvm::MachO::dyld_info_command &in) {302      cmd = in.cmd;303      cmdsize = in.cmdsize;304      rebase_off = in.rebase_off;305      rebase_size = in.rebase_size;306      bind_off = in.bind_off;307      bind_size = in.bind_size;308      weak_bind_off = in.weak_bind_off;309      weak_bind_size = in.weak_bind_size;310      lazy_bind_off = in.lazy_bind_off;311      lazy_bind_size = in.lazy_bind_size;312      export_off = in.export_off;313      export_size = in.export_size;314    };315 316    /// LC_DYLD_INFO or LC_DYLD_INFO_ONLY317    uint32_t cmd = 0;318    uint32_t cmdsize = 0;             /* sizeof(struct dyld_info_command) */319    lldb::offset_t rebase_off = 0;    /* file offset to rebase info  */320    uint32_t rebase_size = 0;         /* size of rebase info   */321    lldb::offset_t bind_off = 0;      /* file offset to binding info   */322    uint32_t bind_size = 0;           /* size of binding info  */323    lldb::offset_t weak_bind_off = 0; /* file offset to weak binding info   */324    uint32_t weak_bind_size = 0;      /* size of weak binding info  */325    lldb::offset_t lazy_bind_off = 0; /* file offset to lazy binding info */326    uint32_t lazy_bind_size = 0;      /* size of lazy binding infs */327    lldb::offset_t export_off = 0;    /* file offset to lazy binding info */328    uint32_t export_size = 0;         /* size of lazy binding infs */329  };330 331  /// The LC_DYSYMTAB's dysymtab_command has 32-bit file offsets332  /// that we will use as virtual address offsets, and may need to span333  /// more than 4GB in virtual memory.334  struct DysymtabCommandLargeOffsets {335    DysymtabCommandLargeOffsets() {}336    DysymtabCommandLargeOffsets(const llvm::MachO::dysymtab_command &in)337        : cmd(in.cmd), cmdsize(in.cmdsize), ilocalsym(in.ilocalsym),338          nlocalsym(in.nlocalsym), iextdefsym(in.iextdefsym),339          nextdefsym(in.nextdefsym), iundefsym(in.iundefsym),340          nundefsym(in.nundefsym), tocoff(in.tocoff), ntoc(in.ntoc),341          modtaboff(in.modtaboff), nmodtab(in.nmodtab),342          extrefsymoff(in.extrefsymoff), nextrefsyms(in.nextrefsyms),343          indirectsymoff(in.indirectsymoff), nindirectsyms(in.nindirectsyms),344          extreloff(in.extreloff), nextrel(in.nextrel), locreloff(in.locreloff),345          nlocrel(in.nlocrel) {}346 347    void operator=(const llvm::MachO::dysymtab_command &in) {348      cmd = in.cmd;349      cmdsize = in.cmdsize;350      ilocalsym = in.ilocalsym;351      nlocalsym = in.nlocalsym;352      iextdefsym = in.iextdefsym;353      nextdefsym = in.nextdefsym;354      iundefsym = in.iundefsym;355      nundefsym = in.nundefsym;356      tocoff = in.tocoff;357      ntoc = in.ntoc;358      modtaboff = in.modtaboff;359      nmodtab = in.nmodtab;360      extrefsymoff = in.extrefsymoff;361      nextrefsyms = in.nextrefsyms;362      indirectsymoff = in.indirectsymoff;363      nindirectsyms = in.nindirectsyms;364      extreloff = in.extreloff;365      nextrel = in.nextrel;366      locreloff = in.locreloff;367      nlocrel = in.nlocrel;368    };369 370    uint32_t cmd = 0;             /* LC_DYSYMTAB */371    uint32_t cmdsize = 0;         /* sizeof(struct dysymtab_command) */372    uint32_t ilocalsym = 0;       /* index to local symbols */373    uint32_t nlocalsym = 0;       /* number of local symbols */374    uint32_t iextdefsym = 0;      /* index to externally defined symbols */375    uint32_t nextdefsym = 0;      /* number of externally defined symbols */376    uint32_t iundefsym = 0;       /* index to undefined symbols */377    uint32_t nundefsym = 0;       /* number of undefined symbols */378    lldb::offset_t tocoff = 0;    /* file offset to table of contents */379    uint32_t ntoc = 0;            /* number of entries in table of contents */380    lldb::offset_t modtaboff = 0; /* file offset to module table */381    uint32_t nmodtab = 0;         /* number of module table entries */382    lldb::offset_t extrefsymoff = 0; /* offset to referenced symbol table */383    uint32_t nextrefsyms = 0; /* number of referenced symbol table entries */384    lldb::offset_t indirectsymoff =385        0;                        /* file offset to the indirect symbol table */386    uint32_t nindirectsyms = 0;   /* number of indirect symbol table entries */387    lldb::offset_t extreloff = 0; /* offset to external relocation entries */388    uint32_t nextrel = 0;         /* number of external relocation entries */389    lldb::offset_t locreloff = 0; /* offset to local relocation entries */390    uint32_t nlocrel = 0;         /* number of local relocation entries */391  };392 393  // The linkedit_data_command is used in several load commands including394  // LC_FUNCTION_STARTS and LC_DYLD_EXPORTS_TRIE.  It has a 32-bit file offset395  // that may need to span more than 4GB in real virtual addresses.396  struct LinkeditDataCommandLargeOffsets {397    LinkeditDataCommandLargeOffsets() {}398    LinkeditDataCommandLargeOffsets(399        const llvm::MachO::linkedit_data_command &in)400        : cmd(in.cmd), cmdsize(in.cmdsize), dataoff(in.dataoff),401          datasize(in.datasize) {}402    void operator=(const llvm::MachO::linkedit_data_command &in) {403      cmd = in.cmd;404      cmdsize = in.cmdsize;405      dataoff = in.dataoff;406      datasize = in.datasize;407    }408    uint32_t cmd = 0;     /* LC_FUNCTION_STARTS, LC_DYLD_EXPORTS_TRIE, etc */409    uint32_t cmdsize = 0; /* sizeof(struct linkedit_data_command) */410    lldb::offset_t dataoff = 0; /* file offset of data in __LINKEDIT segment */411    uint32_t datasize = 0;      /* file size of data in __LINKEDIT segment  */412  };413 414  /// Get the list of binary images that were present in the process415  /// when the corefile was produced.416  /// \return417  ///     The MachOCorefileAllImageInfos object returned will have418  ///     IsValid() == false if the information is unavailable.419  MachOCorefileAllImageInfos GetCorefileAllImageInfos();420 421  llvm::MachO::mach_header m_header;422  static lldb_private::ConstString GetSegmentNameTEXT();423  static lldb_private::ConstString GetSegmentNameDATA();424  static lldb_private::ConstString GetSegmentNameDATA_DIRTY();425  static lldb_private::ConstString GetSegmentNameDATA_CONST();426  static lldb_private::ConstString GetSegmentNameOBJC();427  static lldb_private::ConstString GetSegmentNameLINKEDIT();428  static lldb_private::ConstString GetSegmentNameDWARF();429  static lldb_private::ConstString GetSegmentNameLLVM_COV();430  static lldb_private::ConstString GetSectionNameEHFrame();431  static lldb_private::ConstString GetSectionNameLLDBNoNlist();432 433  llvm::MachO::dysymtab_command m_dysymtab;434  std::vector<llvm::MachO::section_64> m_mach_sections;435  std::optional<llvm::VersionTuple> m_min_os_version;436  std::optional<llvm::VersionTuple> m_sdk_versions;437  typedef lldb_private::RangeVector<uint32_t, uint32_t> FileRangeArray;438  lldb_private::Address m_entry_point_address;439  FileRangeArray m_thread_context_offsets;440  lldb::offset_t m_linkedit_original_offset = 0;441  lldb::addr_t m_text_address = LLDB_INVALID_ADDRESS;442  bool m_thread_context_offsets_valid;443  lldb_private::FileSpecList m_reexported_dylibs;444  bool m_allow_assembly_emulation_unwind_plans;445};446 447#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_MACH_O_OBJECTFILEMACHO_H448