1061da546Spatrick //===-- DynamicLoaderDarwin.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_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERDARWIN_H
10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERDARWIN_H
11061da546Spatrick 
12061da546Spatrick #include <map>
13061da546Spatrick #include <mutex>
14061da546Spatrick #include <vector>
15061da546Spatrick 
16061da546Spatrick #include "lldb/Host/SafeMachO.h"
17061da546Spatrick #include "lldb/Target/DynamicLoader.h"
18061da546Spatrick #include "lldb/Target/Process.h"
19061da546Spatrick #include "lldb/Utility/FileSpec.h"
20061da546Spatrick #include "lldb/Utility/StructuredData.h"
21061da546Spatrick #include "lldb/Utility/UUID.h"
22061da546Spatrick 
23061da546Spatrick #include "llvm/ADT/Triple.h"
24061da546Spatrick 
25061da546Spatrick namespace lldb_private {
26061da546Spatrick 
27061da546Spatrick class DynamicLoaderDarwin : public lldb_private::DynamicLoader {
28061da546Spatrick public:
29061da546Spatrick   DynamicLoaderDarwin(lldb_private::Process *process);
30061da546Spatrick 
31061da546Spatrick   ~DynamicLoaderDarwin() override;
32061da546Spatrick 
33061da546Spatrick   /// Called after attaching a process.
34061da546Spatrick   ///
35061da546Spatrick   /// Allow DynamicLoader plug-ins to execute some code after
36061da546Spatrick   /// attaching to a process.
37061da546Spatrick   void DidAttach() override;
38061da546Spatrick 
39061da546Spatrick   void DidLaunch() override;
40061da546Spatrick 
41061da546Spatrick   lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
42061da546Spatrick                                                   bool stop_others) override;
43061da546Spatrick 
44061da546Spatrick   void FindEquivalentSymbols(
45061da546Spatrick       lldb_private::Symbol *original_symbol,
46061da546Spatrick       lldb_private::ModuleList &module_list,
47061da546Spatrick       lldb_private::SymbolContextList &equivalent_symbols) override;
48061da546Spatrick 
49061da546Spatrick   lldb::addr_t GetThreadLocalData(const lldb::ModuleSP module,
50061da546Spatrick                                   const lldb::ThreadSP thread,
51061da546Spatrick                                   lldb::addr_t tls_file_addr) override;
52061da546Spatrick 
53061da546Spatrick   bool AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override;
54061da546Spatrick 
55061da546Spatrick   virtual void DoInitialImageFetch() = 0;
56061da546Spatrick 
57061da546Spatrick   virtual bool NeedToDoInitialImageFetch() = 0;
58061da546Spatrick 
59061da546Spatrick protected:
60061da546Spatrick   void PrivateInitialize(lldb_private::Process *process);
61061da546Spatrick 
62061da546Spatrick   void PrivateProcessStateChanged(lldb_private::Process *process,
63061da546Spatrick                                   lldb::StateType state);
64061da546Spatrick 
65061da546Spatrick   void Clear(bool clear_process);
66061da546Spatrick 
67061da546Spatrick   // Clear method for classes derived from this one
68061da546Spatrick   virtual void DoClear() = 0;
69061da546Spatrick 
70061da546Spatrick   void SetDYLDModule(lldb::ModuleSP &dyld_module_sp);
71061da546Spatrick 
72061da546Spatrick   lldb::ModuleSP GetDYLDModule();
73061da546Spatrick 
74*f6aab3d8Srobert   void ClearDYLDModule();
75*f6aab3d8Srobert 
76061da546Spatrick   class Segment {
77061da546Spatrick   public:
Segment()78be691f3bSpatrick     Segment() : name() {}
79061da546Spatrick 
80061da546Spatrick     lldb_private::ConstString name;
81be691f3bSpatrick     lldb::addr_t vmaddr = LLDB_INVALID_ADDRESS;
82be691f3bSpatrick     lldb::addr_t vmsize = 0;
83be691f3bSpatrick     lldb::addr_t fileoff = 0;
84be691f3bSpatrick     lldb::addr_t filesize = 0;
85be691f3bSpatrick     uint32_t maxprot = 0;
86be691f3bSpatrick     uint32_t initprot = 0;
87be691f3bSpatrick     uint32_t nsects = 0;
88be691f3bSpatrick     uint32_t flags = 0;
89061da546Spatrick 
90061da546Spatrick     bool operator==(const Segment &rhs) const {
91061da546Spatrick       return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
92061da546Spatrick     }
93061da546Spatrick 
94061da546Spatrick     void PutToLog(lldb_private::Log *log, lldb::addr_t slide) const;
95061da546Spatrick   };
96061da546Spatrick 
97061da546Spatrick   struct ImageInfo {
98061da546Spatrick     /// Address of mach header for this dylib.
99061da546Spatrick     lldb::addr_t address = LLDB_INVALID_ADDRESS;
100061da546Spatrick     /// The amount to slide all segments by if there is a global
101061da546Spatrick     /// slide.
102061da546Spatrick     lldb::addr_t slide = 0;
103061da546Spatrick     /// Modification date for this dylib.
104061da546Spatrick     lldb::addr_t mod_date = 0;
105061da546Spatrick     /// Resolved path for this dylib.
106061da546Spatrick     lldb_private::FileSpec file_spec;
107061da546Spatrick     /// UUID for this dylib if it has one, else all zeros.
108061da546Spatrick     lldb_private::UUID uuid;
109061da546Spatrick     /// The mach header for this image.
110061da546Spatrick     llvm::MachO::mach_header header;
111061da546Spatrick     /// All segment vmaddr and vmsize pairs for this executable (from
112061da546Spatrick     /// memory of inferior).
113061da546Spatrick     std::vector<Segment> segments;
114061da546Spatrick     /// The process stop ID that the sections for this image were
115061da546Spatrick     /// loaded.
116061da546Spatrick     uint32_t load_stop_id = 0;
117061da546Spatrick     /// LC_VERSION_MIN_... load command os type.
118061da546Spatrick     llvm::Triple::OSType os_type = llvm::Triple::OSType::UnknownOS;
119061da546Spatrick     /// LC_VERSION_MIN_... load command os environment.
120061da546Spatrick     llvm::Triple::EnvironmentType os_env =
121061da546Spatrick         llvm::Triple::EnvironmentType::UnknownEnvironment;
122061da546Spatrick     /// LC_VERSION_MIN_... SDK.
123061da546Spatrick     std::string min_version_os_sdk;
124061da546Spatrick 
125061da546Spatrick     ImageInfo() = default;
126061da546Spatrick 
ClearImageInfo127061da546Spatrick     void Clear(bool load_cmd_data_only) {
128061da546Spatrick       if (!load_cmd_data_only) {
129061da546Spatrick         address = LLDB_INVALID_ADDRESS;
130061da546Spatrick         slide = 0;
131061da546Spatrick         mod_date = 0;
132061da546Spatrick         file_spec.Clear();
133061da546Spatrick         ::memset(&header, 0, sizeof(header));
134061da546Spatrick       }
135061da546Spatrick       uuid.Clear();
136061da546Spatrick       segments.clear();
137061da546Spatrick       load_stop_id = 0;
138061da546Spatrick       os_type = llvm::Triple::OSType::UnknownOS;
139061da546Spatrick       os_env = llvm::Triple::EnvironmentType::UnknownEnvironment;
140061da546Spatrick       min_version_os_sdk.clear();
141061da546Spatrick     }
142061da546Spatrick 
143061da546Spatrick     bool operator==(const ImageInfo &rhs) const {
144061da546Spatrick       return address == rhs.address && slide == rhs.slide &&
145061da546Spatrick              mod_date == rhs.mod_date && file_spec == rhs.file_spec &&
146061da546Spatrick              uuid == rhs.uuid &&
147061da546Spatrick              memcmp(&header, &rhs.header, sizeof(header)) == 0 &&
148061da546Spatrick              segments == rhs.segments && os_type == rhs.os_type &&
149061da546Spatrick              os_env == rhs.os_env;
150061da546Spatrick     }
151061da546Spatrick 
UUIDValidImageInfo152061da546Spatrick     bool UUIDValid() const { return uuid.IsValid(); }
153061da546Spatrick 
GetAddressByteSizeImageInfo154061da546Spatrick     uint32_t GetAddressByteSize() {
155061da546Spatrick       if (header.cputype) {
156061da546Spatrick         if (header.cputype & llvm::MachO::CPU_ARCH_ABI64)
157061da546Spatrick           return 8;
158061da546Spatrick         else
159061da546Spatrick           return 4;
160061da546Spatrick       }
161061da546Spatrick       return 0;
162061da546Spatrick     }
163061da546Spatrick 
164061da546Spatrick     lldb_private::ArchSpec GetArchitecture() const;
165061da546Spatrick 
166061da546Spatrick     const Segment *FindSegment(lldb_private::ConstString name) const;
167061da546Spatrick 
168061da546Spatrick     void PutToLog(lldb_private::Log *log) const;
169061da546Spatrick 
170061da546Spatrick     typedef std::vector<ImageInfo> collection;
171061da546Spatrick     typedef collection::iterator iterator;
172061da546Spatrick     typedef collection::const_iterator const_iterator;
173061da546Spatrick   };
174061da546Spatrick 
175061da546Spatrick   bool UpdateImageLoadAddress(lldb_private::Module *module, ImageInfo &info);
176061da546Spatrick 
177061da546Spatrick   bool UnloadModuleSections(lldb_private::Module *module, ImageInfo &info);
178061da546Spatrick 
179061da546Spatrick   lldb::ModuleSP FindTargetModuleForImageInfo(ImageInfo &image_info,
180061da546Spatrick                                               bool can_create,
181061da546Spatrick                                               bool *did_create_ptr);
182061da546Spatrick 
183061da546Spatrick   void UnloadImages(const std::vector<lldb::addr_t> &solib_addresses);
184061da546Spatrick 
185061da546Spatrick   void UnloadAllImages();
186061da546Spatrick 
187061da546Spatrick   virtual bool SetNotificationBreakpoint() = 0;
188061da546Spatrick 
189061da546Spatrick   virtual void ClearNotificationBreakpoint() = 0;
190061da546Spatrick 
191061da546Spatrick   virtual bool DidSetNotificationBreakpoint() = 0;
192061da546Spatrick 
193061da546Spatrick   typedef std::map<uint64_t, lldb::addr_t> PthreadKeyToTLSMap;
194061da546Spatrick   typedef std::map<lldb::user_id_t, PthreadKeyToTLSMap> ThreadIDToTLSMap;
195061da546Spatrick 
GetMutex()196061da546Spatrick   std::recursive_mutex &GetMutex() const { return m_mutex; }
197061da546Spatrick 
198061da546Spatrick   lldb::ModuleSP GetPThreadLibraryModule();
199061da546Spatrick 
200061da546Spatrick   lldb_private::Address GetPthreadSetSpecificAddress();
201061da546Spatrick 
202061da546Spatrick   bool JSONImageInformationIntoImageInfo(
203061da546Spatrick       lldb_private::StructuredData::ObjectSP image_details,
204061da546Spatrick       ImageInfo::collection &image_infos);
205061da546Spatrick 
206061da546Spatrick   // If image_infos contains / may contain dyld or executable image, call this
207061da546Spatrick   // method
208061da546Spatrick   // to keep our internal record keeping of the special binaries up-to-date.
209061da546Spatrick   void
210061da546Spatrick   UpdateSpecialBinariesFromNewImageInfos(ImageInfo::collection &image_infos);
211061da546Spatrick 
212061da546Spatrick   // if image_info is a dyld binary, call this method
213061da546Spatrick   void UpdateDYLDImageInfoFromNewImageInfo(ImageInfo &image_info);
214061da546Spatrick 
215061da546Spatrick   // If image_infos contains / may contain executable image, call this method
216061da546Spatrick   // to keep our internal record keeping of the special dyld binary up-to-date.
217061da546Spatrick   void AddExecutableModuleIfInImageInfos(ImageInfo::collection &image_infos);
218061da546Spatrick 
219061da546Spatrick   bool AddModulesUsingImageInfos(ImageInfo::collection &image_infos);
220061da546Spatrick 
221061da546Spatrick   // Whether we should use the new dyld SPI to get shared library information,
222061da546Spatrick   // or read
223061da546Spatrick   // it directly out of the dyld_all_image_infos.  Whether we use the (newer)
224061da546Spatrick   // DynamicLoaderMacOS
225061da546Spatrick   // plugin or the (older) DynamicLoaderMacOSX plugin.
226061da546Spatrick   static bool UseDYLDSPI(lldb_private::Process *process);
227061da546Spatrick 
228061da546Spatrick   lldb::ModuleWP m_dyld_module_wp; // the dyld whose file type (mac, ios, etc)
229061da546Spatrick                                    // matches the process
230061da546Spatrick   lldb::ModuleWP m_libpthread_module_wp;
231061da546Spatrick   lldb_private::Address m_pthread_getspecific_addr;
232061da546Spatrick   ThreadIDToTLSMap m_tid_to_tls_map;
233061da546Spatrick   ImageInfo::collection
234061da546Spatrick       m_dyld_image_infos;              // Current shared libraries information
235061da546Spatrick   uint32_t m_dyld_image_infos_stop_id; // The process stop ID that
236061da546Spatrick                                        // "m_dyld_image_infos" is valid for
237061da546Spatrick   ImageInfo m_dyld;
238061da546Spatrick   mutable std::recursive_mutex m_mutex;
239061da546Spatrick 
240061da546Spatrick private:
241dda28197Spatrick   DynamicLoaderDarwin(const DynamicLoaderDarwin &) = delete;
242dda28197Spatrick   const DynamicLoaderDarwin &operator=(const DynamicLoaderDarwin &) = delete;
243061da546Spatrick };
244061da546Spatrick 
245061da546Spatrick } // namespace lldb_private
246061da546Spatrick 
247dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERDARWIN_H
248