1061da546Spatrick //===-- ObjectFileMachO.h ---------------------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_MACH_O_OBJECTFILEMACHO_H 10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_OBJECTFILE_MACH_O_OBJECTFILEMACHO_H 11061da546Spatrick 12061da546Spatrick #include "lldb/Core/Address.h" 13061da546Spatrick #include "lldb/Core/FileSpecList.h" 14061da546Spatrick #include "lldb/Host/SafeMachO.h" 15061da546Spatrick #include "lldb/Symbol/ObjectFile.h" 16061da546Spatrick #include "lldb/Utility/FileSpec.h" 17061da546Spatrick #include "lldb/Utility/RangeMap.h" 18be691f3bSpatrick #include "lldb/Utility/StreamString.h" 19061da546Spatrick #include "lldb/Utility/UUID.h" 20*f6aab3d8Srobert #include <optional> 21061da546Spatrick 22061da546Spatrick // This class needs to be hidden as eventually belongs in a plugin that 23061da546Spatrick // will export the ObjectFile protocol 24061da546Spatrick class ObjectFileMachO : public lldb_private::ObjectFile { 25061da546Spatrick public: 26*f6aab3d8Srobert ObjectFileMachO(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, 27061da546Spatrick lldb::offset_t data_offset, 28061da546Spatrick const lldb_private::FileSpec *file, lldb::offset_t offset, 29061da546Spatrick lldb::offset_t length); 30061da546Spatrick 31*f6aab3d8Srobert ObjectFileMachO(const lldb::ModuleSP &module_sp, 32*f6aab3d8Srobert lldb::WritableDataBufferSP data_sp, 33061da546Spatrick const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); 34061da546Spatrick 35061da546Spatrick ~ObjectFileMachO() override = default; 36061da546Spatrick 37061da546Spatrick // Static Functions 38061da546Spatrick static void Initialize(); 39061da546Spatrick 40061da546Spatrick static void Terminate(); 41061da546Spatrick GetPluginNameStatic()42*f6aab3d8Srobert static llvm::StringRef GetPluginNameStatic() { return "mach-o"; } 43061da546Spatrick GetPluginDescriptionStatic()44*f6aab3d8Srobert static llvm::StringRef GetPluginDescriptionStatic() { 45*f6aab3d8Srobert return "Mach-o object file reader (32 and 64 bit)"; 46*f6aab3d8Srobert } 47061da546Spatrick 48061da546Spatrick static lldb_private::ObjectFile * 49*f6aab3d8Srobert CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, 50061da546Spatrick lldb::offset_t data_offset, const lldb_private::FileSpec *file, 51061da546Spatrick lldb::offset_t file_offset, lldb::offset_t length); 52061da546Spatrick 53061da546Spatrick static lldb_private::ObjectFile *CreateMemoryInstance( 54*f6aab3d8Srobert const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, 55061da546Spatrick const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); 56061da546Spatrick 57061da546Spatrick static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, 58061da546Spatrick lldb::DataBufferSP &data_sp, 59061da546Spatrick lldb::offset_t data_offset, 60061da546Spatrick lldb::offset_t file_offset, 61061da546Spatrick lldb::offset_t length, 62061da546Spatrick lldb_private::ModuleSpecList &specs); 63061da546Spatrick 64061da546Spatrick static bool SaveCore(const lldb::ProcessSP &process_sp, 65061da546Spatrick const lldb_private::FileSpec &outfile, 66be691f3bSpatrick lldb::SaveCoreStyle &core_style, 67061da546Spatrick lldb_private::Status &error); 68061da546Spatrick 69*f6aab3d8Srobert static bool MagicBytesMatch(lldb::DataBufferSP data_sp, lldb::addr_t offset, 70061da546Spatrick lldb::addr_t length); 71061da546Spatrick 72061da546Spatrick // LLVM RTTI support 73061da546Spatrick static char ID; isA(const void * ClassID)74061da546Spatrick bool isA(const void *ClassID) const override { 75061da546Spatrick return ClassID == &ID || ObjectFile::isA(ClassID); 76061da546Spatrick } classof(const ObjectFile * obj)77061da546Spatrick static bool classof(const ObjectFile *obj) { return obj->isA(&ID); } 78061da546Spatrick 79061da546Spatrick // Member Functions 80061da546Spatrick bool ParseHeader() override; 81061da546Spatrick 82061da546Spatrick bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value, 83061da546Spatrick bool value_is_offset) override; 84061da546Spatrick 85061da546Spatrick lldb::ByteOrder GetByteOrder() const override; 86061da546Spatrick 87061da546Spatrick bool IsExecutable() const override; 88061da546Spatrick 89061da546Spatrick bool IsDynamicLoader() const; 90061da546Spatrick 91*f6aab3d8Srobert bool IsSharedCacheBinary() const; 92*f6aab3d8Srobert 93061da546Spatrick uint32_t GetAddressByteSize() const override; 94061da546Spatrick 95061da546Spatrick lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override; 96061da546Spatrick 97*f6aab3d8Srobert void ParseSymtab(lldb_private::Symtab &symtab) override; 98061da546Spatrick 99061da546Spatrick bool IsStripped() override; 100061da546Spatrick 101061da546Spatrick void CreateSections(lldb_private::SectionList &unified_section_list) override; 102061da546Spatrick 103061da546Spatrick void Dump(lldb_private::Stream *s) override; 104061da546Spatrick 105061da546Spatrick lldb_private::ArchSpec GetArchitecture() override; 106061da546Spatrick 107061da546Spatrick lldb_private::UUID GetUUID() override; 108061da546Spatrick 109061da546Spatrick uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; 110061da546Spatrick GetReExportedLibraries()111061da546Spatrick lldb_private::FileSpecList GetReExportedLibraries() override { 112061da546Spatrick return m_reexported_dylibs; 113061da546Spatrick } 114061da546Spatrick 115061da546Spatrick lldb_private::Address GetEntryPointAddress() override; 116061da546Spatrick 117061da546Spatrick lldb_private::Address GetBaseAddress() override; 118061da546Spatrick 119061da546Spatrick uint32_t GetNumThreadContexts() override; 120061da546Spatrick 121061da546Spatrick std::string GetIdentifierString() override; 122061da546Spatrick 123be691f3bSpatrick lldb::addr_t GetAddressMask() override; 124be691f3bSpatrick 125*f6aab3d8Srobert bool GetCorefileMainBinaryInfo(lldb::addr_t &value, bool &value_is_offset, 126be691f3bSpatrick lldb_private::UUID &uuid, 127be691f3bSpatrick ObjectFile::BinaryType &type) override; 128be691f3bSpatrick 129be691f3bSpatrick bool LoadCoreFileImages(lldb_private::Process &process) override; 130061da546Spatrick 131061da546Spatrick lldb::RegisterContextSP 132061da546Spatrick GetThreadContextAtIndex(uint32_t idx, lldb_private::Thread &thread) override; 133061da546Spatrick 134061da546Spatrick ObjectFile::Type CalculateType() override; 135061da546Spatrick 136061da546Spatrick ObjectFile::Strata CalculateStrata() override; 137061da546Spatrick 138061da546Spatrick llvm::VersionTuple GetVersion() override; 139061da546Spatrick 140061da546Spatrick llvm::VersionTuple GetMinimumOSVersion() override; 141061da546Spatrick 142061da546Spatrick llvm::VersionTuple GetSDKVersion() override; 143061da546Spatrick 144061da546Spatrick bool GetIsDynamicLinkEditor() override; 145061da546Spatrick 146*f6aab3d8Srobert bool CanTrustAddressRanges() override; 147*f6aab3d8Srobert 148061da546Spatrick static bool ParseHeader(lldb_private::DataExtractor &data, 149061da546Spatrick lldb::offset_t *data_offset_ptr, 150061da546Spatrick llvm::MachO::mach_header &header); 151061da546Spatrick 152061da546Spatrick bool AllowAssemblyEmulationUnwindPlans() override; 153061da546Spatrick 154061da546Spatrick // PluginInterface protocol GetPluginName()155*f6aab3d8Srobert llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 156061da546Spatrick 157061da546Spatrick protected: 158061da546Spatrick static lldb_private::UUID 159061da546Spatrick GetUUID(const llvm::MachO::mach_header &header, 160061da546Spatrick const lldb_private::DataExtractor &data, 161061da546Spatrick lldb::offset_t lc_offset); // Offset to the first load command 162061da546Spatrick 163061da546Spatrick static lldb_private::ArchSpec GetArchitecture( 164061da546Spatrick lldb::ModuleSP module_sp, const llvm::MachO::mach_header &header, 165061da546Spatrick const lldb_private::DataExtractor &data, lldb::offset_t lc_offset); 166061da546Spatrick 167061da546Spatrick /// Enumerate all ArchSpecs supported by this Mach-O file. 168061da546Spatrick /// 169061da546Spatrick /// On macOS one Mach-O slice can contain multiple load commands: 170061da546Spatrick /// One load command for being loaded into a macOS process and one 171061da546Spatrick /// load command for being loaded into a macCatalyst process. In 172061da546Spatrick /// contrast to ObjectContainerUniversalMachO, this is the same 173061da546Spatrick /// binary that can be loaded into different contexts. 174061da546Spatrick static void GetAllArchSpecs(const llvm::MachO::mach_header &header, 175061da546Spatrick const lldb_private::DataExtractor &data, 176061da546Spatrick lldb::offset_t lc_offset, 177061da546Spatrick lldb_private::ModuleSpec &base_spec, 178061da546Spatrick lldb_private::ModuleSpecList &all_specs); 179061da546Spatrick 180061da546Spatrick /// Intended for same-host arm device debugging where lldb needs to 181061da546Spatrick /// detect libraries in the shared cache and augment the nlist entries 182061da546Spatrick /// with an on-disk dyld_shared_cache file. The process will record 183061da546Spatrick /// the shared cache UUID so the on-disk cache can be matched or rejected 184061da546Spatrick /// correctly. 185061da546Spatrick void GetProcessSharedCacheUUID(lldb_private::Process *, 186061da546Spatrick lldb::addr_t &base_addr, 187061da546Spatrick lldb_private::UUID &uuid); 188061da546Spatrick 189061da546Spatrick /// Intended for same-host arm device debugging where lldb will read 190061da546Spatrick /// shared cache libraries out of its own memory instead of the remote 191061da546Spatrick /// process' memory as an optimization. If lldb's shared cache UUID 192061da546Spatrick /// does not match the process' shared cache UUID, this optimization 193061da546Spatrick /// should not be used. 194061da546Spatrick void GetLLDBSharedCacheUUID(lldb::addr_t &base_addir, lldb_private::UUID &uuid); 195061da546Spatrick 196061da546Spatrick lldb_private::Section *GetMachHeaderSection(); 197061da546Spatrick 198061da546Spatrick lldb::addr_t CalculateSectionLoadAddressForMemoryImage( 199061da546Spatrick lldb::addr_t mach_header_load_address, 200061da546Spatrick const lldb_private::Section *mach_header_section, 201061da546Spatrick const lldb_private::Section *section); 202061da546Spatrick 203061da546Spatrick lldb_private::UUID 204061da546Spatrick GetSharedCacheUUID(lldb_private::FileSpec dyld_shared_cache, 205061da546Spatrick const lldb::ByteOrder byte_order, 206061da546Spatrick const uint32_t addr_byte_size); 207061da546Spatrick 208061da546Spatrick size_t ParseSymtab(); 209061da546Spatrick 210dda28197Spatrick typedef lldb_private::RangeVector<uint32_t, uint32_t, 8> EncryptedFileRanges; 211061da546Spatrick EncryptedFileRanges GetEncryptedFileRanges(); 212061da546Spatrick 213061da546Spatrick struct SegmentParsingContext; 214061da546Spatrick void ProcessDysymtabCommand(const llvm::MachO::load_command &load_cmd, 215061da546Spatrick lldb::offset_t offset); 216061da546Spatrick void ProcessSegmentCommand(const llvm::MachO::load_command &load_cmd, 217061da546Spatrick lldb::offset_t offset, uint32_t cmd_idx, 218061da546Spatrick SegmentParsingContext &context); 219061da546Spatrick void SanitizeSegmentCommand(llvm::MachO::segment_command_64 &seg_cmd, 220061da546Spatrick uint32_t cmd_idx); 221061da546Spatrick 222061da546Spatrick bool SectionIsLoadable(const lldb_private::Section *section); 223061da546Spatrick 224be691f3bSpatrick /// A corefile may include metadata about all of the binaries that were 225be691f3bSpatrick /// present in the process when the corefile was taken. This is only 226be691f3bSpatrick /// implemented for Mach-O files for now; we'll generalize it when we 227be691f3bSpatrick /// have other systems that can include the same. 228be691f3bSpatrick struct MachOCorefileImageEntry { 229be691f3bSpatrick std::string filename; 230be691f3bSpatrick lldb_private::UUID uuid; 231be691f3bSpatrick lldb::addr_t load_address = LLDB_INVALID_ADDRESS; 232*f6aab3d8Srobert lldb::addr_t slide = 0; 233*f6aab3d8Srobert bool currently_executing = false; 234be691f3bSpatrick std::vector<std::tuple<lldb_private::ConstString, lldb::addr_t>> 235be691f3bSpatrick segment_load_addresses; 236be691f3bSpatrick }; 237be691f3bSpatrick 238be691f3bSpatrick struct LCNoteEntry { LCNoteEntryLCNoteEntry239be691f3bSpatrick LCNoteEntry(uint32_t addr_byte_size, lldb::ByteOrder byte_order) 240be691f3bSpatrick : payload(lldb_private::Stream::eBinary, addr_byte_size, byte_order) {} 241be691f3bSpatrick 242be691f3bSpatrick std::string name; 243be691f3bSpatrick lldb::addr_t payload_file_offset = 0; 244be691f3bSpatrick lldb_private::StreamString payload; 245be691f3bSpatrick }; 246be691f3bSpatrick 247be691f3bSpatrick struct MachOCorefileAllImageInfos { 248be691f3bSpatrick std::vector<MachOCorefileImageEntry> all_image_infos; IsValidMachOCorefileAllImageInfos249be691f3bSpatrick bool IsValid() { return all_image_infos.size() > 0; } 250be691f3bSpatrick }; 251be691f3bSpatrick 252be691f3bSpatrick /// Get the list of binary images that were present in the process 253be691f3bSpatrick /// when the corefile was produced. 254be691f3bSpatrick /// \return 255be691f3bSpatrick /// The MachOCorefileAllImageInfos object returned will have 256be691f3bSpatrick /// IsValid() == false if the information is unavailable. 257be691f3bSpatrick MachOCorefileAllImageInfos GetCorefileAllImageInfos(); 258be691f3bSpatrick 259061da546Spatrick llvm::MachO::mach_header m_header; 260061da546Spatrick static lldb_private::ConstString GetSegmentNameTEXT(); 261061da546Spatrick static lldb_private::ConstString GetSegmentNameDATA(); 262061da546Spatrick static lldb_private::ConstString GetSegmentNameDATA_DIRTY(); 263061da546Spatrick static lldb_private::ConstString GetSegmentNameDATA_CONST(); 264061da546Spatrick static lldb_private::ConstString GetSegmentNameOBJC(); 265061da546Spatrick static lldb_private::ConstString GetSegmentNameLINKEDIT(); 266061da546Spatrick static lldb_private::ConstString GetSegmentNameDWARF(); 267061da546Spatrick static lldb_private::ConstString GetSectionNameEHFrame(); 268061da546Spatrick 269061da546Spatrick llvm::MachO::dysymtab_command m_dysymtab; 270061da546Spatrick std::vector<llvm::MachO::segment_command_64> m_mach_segments; 271061da546Spatrick std::vector<llvm::MachO::section_64> m_mach_sections; 272*f6aab3d8Srobert std::optional<llvm::VersionTuple> m_min_os_version; 273*f6aab3d8Srobert std::optional<llvm::VersionTuple> m_sdk_versions; 274061da546Spatrick typedef lldb_private::RangeVector<uint32_t, uint32_t> FileRangeArray; 275061da546Spatrick lldb_private::Address m_entry_point_address; 276061da546Spatrick FileRangeArray m_thread_context_offsets; 277*f6aab3d8Srobert lldb::offset_t m_linkedit_original_offset = 0; 278*f6aab3d8Srobert lldb::addr_t m_text_address = LLDB_INVALID_ADDRESS; 279061da546Spatrick bool m_thread_context_offsets_valid; 280061da546Spatrick lldb_private::FileSpecList m_reexported_dylibs; 281061da546Spatrick bool m_allow_assembly_emulation_unwind_plans; 282061da546Spatrick }; 283061da546Spatrick 284dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_MACH_O_OBJECTFILEMACHO_H 285