|  | //===-- DynamicLoaderDarwin.h -------------------------------*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef liblldb_DynamicLoaderDarwin_h_ | 
|  | #define liblldb_DynamicLoaderDarwin_h_ | 
|  |  | 
|  | // C Includes | 
|  | // C++ Includes | 
|  | #include <map> | 
|  | #include <mutex> | 
|  | #include <vector> | 
|  |  | 
|  | // Other libraries and framework includes | 
|  | // Project includes | 
|  | #include "lldb/Core/StructuredData.h" | 
|  | #include "lldb/Core/UUID.h" | 
|  | #include "lldb/Host/FileSpec.h" | 
|  | #include "lldb/Target/DynamicLoader.h" | 
|  | #include "lldb/Target/Process.h" | 
|  | #include "lldb/Utility/SafeMachO.h" | 
|  |  | 
|  | #include "llvm/ADT/Triple.h" | 
|  |  | 
|  | namespace lldb_private { | 
|  |  | 
|  | class DynamicLoaderDarwin : public lldb_private::DynamicLoader { | 
|  | public: | 
|  | DynamicLoaderDarwin(lldb_private::Process *process); | 
|  |  | 
|  | virtual ~DynamicLoaderDarwin() override; | 
|  |  | 
|  | //------------------------------------------------------------------ | 
|  | /// Called after attaching a process. | 
|  | /// | 
|  | /// Allow DynamicLoader plug-ins to execute some code after | 
|  | /// attaching to a process. | 
|  | //------------------------------------------------------------------ | 
|  | void DidAttach() override; | 
|  |  | 
|  | void DidLaunch() override; | 
|  |  | 
|  | lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, | 
|  | bool stop_others) override; | 
|  |  | 
|  | size_t FindEquivalentSymbols( | 
|  | lldb_private::Symbol *original_symbol, | 
|  | lldb_private::ModuleList &module_list, | 
|  | lldb_private::SymbolContextList &equivalent_symbols) override; | 
|  |  | 
|  | lldb::addr_t GetThreadLocalData(const lldb::ModuleSP module, | 
|  | const lldb::ThreadSP thread, | 
|  | lldb::addr_t tls_file_addr) override; | 
|  |  | 
|  | bool AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override; | 
|  |  | 
|  | virtual void DoInitialImageFetch() = 0; | 
|  |  | 
|  | virtual bool NeedToDoInitialImageFetch() = 0; | 
|  |  | 
|  | protected: | 
|  | void PrivateInitialize(lldb_private::Process *process); | 
|  |  | 
|  | void PrivateProcessStateChanged(lldb_private::Process *process, | 
|  | lldb::StateType state); | 
|  |  | 
|  | void Clear(bool clear_process); | 
|  |  | 
|  | // Clear method for classes derived from this one | 
|  | virtual void DoClear() = 0; | 
|  |  | 
|  | void SetDYLDModule(lldb::ModuleSP &dyld_module_sp); | 
|  |  | 
|  | lldb::ModuleSP GetDYLDModule(); | 
|  |  | 
|  | class Segment { | 
|  | public: | 
|  | Segment() | 
|  | : name(), vmaddr(LLDB_INVALID_ADDRESS), vmsize(0), fileoff(0), | 
|  | filesize(0), maxprot(0), initprot(0), nsects(0), flags(0) {} | 
|  |  | 
|  | lldb_private::ConstString name; | 
|  | lldb::addr_t vmaddr; | 
|  | lldb::addr_t vmsize; | 
|  | lldb::addr_t fileoff; | 
|  | lldb::addr_t filesize; | 
|  | uint32_t maxprot; | 
|  | uint32_t initprot; | 
|  | uint32_t nsects; | 
|  | uint32_t flags; | 
|  |  | 
|  | bool operator==(const Segment &rhs) const { | 
|  | return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize; | 
|  | } | 
|  |  | 
|  | void PutToLog(lldb_private::Log *log, lldb::addr_t slide) const; | 
|  | }; | 
|  |  | 
|  | struct ImageInfo { | 
|  | lldb::addr_t address;  // Address of mach header for this dylib | 
|  | lldb::addr_t slide;    // The amount to slide all segments by if there is a | 
|  | // global slide. | 
|  | lldb::addr_t mod_date; // Modification date for this dylib | 
|  | lldb_private::FileSpec file_spec; // Resolved path for this dylib | 
|  | lldb_private::UUID | 
|  | uuid; // UUID for this dylib if it has one, else all zeros | 
|  | llvm::MachO::mach_header header; // The mach header for this image | 
|  | std::vector<Segment> segments;   // All segment vmaddr and vmsize pairs for | 
|  | // this executable (from memory of inferior) | 
|  | uint32_t load_stop_id; // The process stop ID that the sections for this | 
|  | // image were loaded | 
|  | llvm::Triple::OSType os_type;   // LC_VERSION_MIN_... load command os type | 
|  | std::string min_version_os_sdk; // LC_VERSION_MIN_... sdk value | 
|  |  | 
|  | ImageInfo() | 
|  | : address(LLDB_INVALID_ADDRESS), slide(0), mod_date(0), file_spec(), | 
|  | uuid(), header(), segments(), load_stop_id(0), | 
|  | os_type(llvm::Triple::OSType::UnknownOS), min_version_os_sdk() {} | 
|  |  | 
|  | void Clear(bool load_cmd_data_only) { | 
|  | if (!load_cmd_data_only) { | 
|  | address = LLDB_INVALID_ADDRESS; | 
|  | slide = 0; | 
|  | mod_date = 0; | 
|  | file_spec.Clear(); | 
|  | ::memset(&header, 0, sizeof(header)); | 
|  | } | 
|  | uuid.Clear(); | 
|  | segments.clear(); | 
|  | load_stop_id = 0; | 
|  | os_type = llvm::Triple::OSType::UnknownOS; | 
|  | min_version_os_sdk.clear(); | 
|  | } | 
|  |  | 
|  | bool operator==(const ImageInfo &rhs) const { | 
|  | return address == rhs.address && slide == rhs.slide && | 
|  | mod_date == rhs.mod_date && file_spec == rhs.file_spec && | 
|  | uuid == rhs.uuid && | 
|  | memcmp(&header, &rhs.header, sizeof(header)) == 0 && | 
|  | segments == rhs.segments && os_type == rhs.os_type; | 
|  | } | 
|  |  | 
|  | bool UUIDValid() const { return uuid.IsValid(); } | 
|  |  | 
|  | uint32_t GetAddressByteSize() { | 
|  | if (header.cputype) { | 
|  | if (header.cputype & llvm::MachO::CPU_ARCH_ABI64) | 
|  | return 8; | 
|  | else | 
|  | return 4; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | lldb_private::ArchSpec GetArchitecture() const { | 
|  | return lldb_private::ArchSpec(lldb_private::eArchTypeMachO, | 
|  | header.cputype, header.cpusubtype); | 
|  | } | 
|  |  | 
|  | const Segment *FindSegment(const lldb_private::ConstString &name) const; | 
|  |  | 
|  | void PutToLog(lldb_private::Log *log) const; | 
|  |  | 
|  | typedef std::vector<ImageInfo> collection; | 
|  | typedef collection::iterator iterator; | 
|  | typedef collection::const_iterator const_iterator; | 
|  | }; | 
|  |  | 
|  | bool UpdateImageLoadAddress(lldb_private::Module *module, ImageInfo &info); | 
|  |  | 
|  | bool UnloadModuleSections(lldb_private::Module *module, ImageInfo &info); | 
|  |  | 
|  | lldb::ModuleSP FindTargetModuleForImageInfo(ImageInfo &image_info, | 
|  | bool can_create, | 
|  | bool *did_create_ptr); | 
|  |  | 
|  | void UnloadImages(const std::vector<lldb::addr_t> &solib_addresses); | 
|  |  | 
|  | void UnloadAllImages(); | 
|  |  | 
|  | virtual bool SetNotificationBreakpoint() = 0; | 
|  |  | 
|  | virtual void ClearNotificationBreakpoint() = 0; | 
|  |  | 
|  | virtual bool DidSetNotificationBreakpoint() = 0; | 
|  |  | 
|  | typedef std::map<uint64_t, lldb::addr_t> PthreadKeyToTLSMap; | 
|  | typedef std::map<lldb::user_id_t, PthreadKeyToTLSMap> ThreadIDToTLSMap; | 
|  |  | 
|  | std::recursive_mutex &GetMutex() const { return m_mutex; } | 
|  |  | 
|  | lldb::ModuleSP GetPThreadLibraryModule(); | 
|  |  | 
|  | lldb_private::Address GetPthreadSetSpecificAddress(); | 
|  |  | 
|  | bool JSONImageInformationIntoImageInfo( | 
|  | lldb_private::StructuredData::ObjectSP image_details, | 
|  | ImageInfo::collection &image_infos); | 
|  |  | 
|  | // If image_infos contains / may contain dyld or executable image, call this | 
|  | // method | 
|  | // to keep our internal record keeping of the special binaries up-to-date. | 
|  | void | 
|  | UpdateSpecialBinariesFromNewImageInfos(ImageInfo::collection &image_infos); | 
|  |  | 
|  | // if image_info is a dyld binary, call this method | 
|  | void UpdateDYLDImageInfoFromNewImageInfo(ImageInfo &image_info); | 
|  |  | 
|  | // If image_infos contains / may contain executable image, call this method | 
|  | // to keep our internal record keeping of the special dyld binary up-to-date. | 
|  | void AddExecutableModuleIfInImageInfos(ImageInfo::collection &image_infos); | 
|  |  | 
|  | bool AddModulesUsingImageInfos(ImageInfo::collection &image_infos); | 
|  |  | 
|  | // Whether we should use the new dyld SPI to get shared library information, | 
|  | // or read | 
|  | // it directly out of the dyld_all_image_infos.  Whether we use the (newer) | 
|  | // DynamicLoaderMacOS | 
|  | // plugin or the (older) DynamicLoaderMacOSX plugin. | 
|  | static bool UseDYLDSPI(lldb_private::Process *process); | 
|  |  | 
|  | lldb::ModuleWP m_dyld_module_wp; // the dyld whose file type (mac, ios, etc) | 
|  | // matches the process | 
|  | lldb::ModuleWP m_libpthread_module_wp; | 
|  | lldb_private::Address m_pthread_getspecific_addr; | 
|  | ThreadIDToTLSMap m_tid_to_tls_map; | 
|  | ImageInfo::collection | 
|  | m_dyld_image_infos;              // Current shared libraries information | 
|  | uint32_t m_dyld_image_infos_stop_id; // The process stop ID that | 
|  | // "m_dyld_image_infos" is valid for | 
|  | ImageInfo m_dyld; | 
|  | mutable std::recursive_mutex m_mutex; | 
|  |  | 
|  | private: | 
|  | DISALLOW_COPY_AND_ASSIGN(DynamicLoaderDarwin); | 
|  | }; | 
|  |  | 
|  | } // namespace lldb_private | 
|  |  | 
|  | #endif // liblldb_DynamicLoaderDarwin_h_ |