xref: /llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h (revision 5f2cf99e146ce99d4e148038d9bdd012331b4821)
1 //===-- DynamicLoaderDarwin.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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERDARWIN_H
10 #define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERDARWIN_H
11 
12 #include <map>
13 #include <mutex>
14 #include <vector>
15 
16 #include "lldb/Host/SafeMachO.h"
17 #include "lldb/Target/DynamicLoader.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Utility/FileSpec.h"
20 #include "lldb/Utility/StructuredData.h"
21 #include "lldb/Utility/UUID.h"
22 
23 #include "llvm/TargetParser/Triple.h"
24 
25 namespace lldb_private {
26 
27 class DynamicLoaderDarwin : public lldb_private::DynamicLoader {
28 public:
29   DynamicLoaderDarwin(lldb_private::Process *process);
30 
31   ~DynamicLoaderDarwin() override;
32 
33   /// Called after attaching a process.
34   ///
35   /// Allow DynamicLoader plug-ins to execute some code after
36   /// attaching to a process.
37   void DidAttach() override;
38 
39   void DidLaunch() override;
40 
41   lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
42                                                   bool stop_others) override;
43 
44   void FindEquivalentSymbols(
45       lldb_private::Symbol *original_symbol,
46       lldb_private::ModuleList &module_list,
47       lldb_private::SymbolContextList &equivalent_symbols) override;
48 
49   lldb::addr_t GetThreadLocalData(const lldb::ModuleSP module,
50                                   const lldb::ThreadSP thread,
51                                   lldb::addr_t tls_file_addr) override;
52 
53   bool AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override;
54 
55   virtual void DoInitialImageFetch() = 0;
56 
57   virtual bool NeedToDoInitialImageFetch() = 0;
58 
59   std::optional<lldb_private::Address> GetStartAddress() override;
60 
61   static void CreateSettings(lldb_private::Debugger &debugger);
62 
63 protected:
64   void PrivateInitialize(lldb_private::Process *process);
65 
66   void PrivateProcessStateChanged(lldb_private::Process *process,
67                                   lldb::StateType state);
68 
69   void Clear(bool clear_process);
70 
71   // Clear method for classes derived from this one
72   virtual void DoClear() = 0;
73 
74   void SetDYLDModule(lldb::ModuleSP &dyld_module_sp);
75 
76   lldb::ModuleSP GetDYLDModule();
77 
78   void ClearDYLDModule();
79 
80   class Segment {
81   public:
82     Segment() : name() {}
83 
84     lldb_private::ConstString name;
85     lldb::addr_t vmaddr = LLDB_INVALID_ADDRESS;
86     lldb::addr_t vmsize = 0;
87     lldb::addr_t fileoff = 0;
88     lldb::addr_t filesize = 0;
89     uint32_t maxprot = 0;
90     uint32_t initprot = 0;
91     uint32_t nsects = 0;
92     uint32_t flags = 0;
93 
94     bool operator==(const Segment &rhs) const {
95       return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
96     }
97 
98     void PutToLog(lldb_private::Log *log, lldb::addr_t slide) const;
99   };
100 
101   struct ImageInfo {
102     /// Address of mach header for this dylib.
103     lldb::addr_t address = LLDB_INVALID_ADDRESS;
104     /// The amount to slide all segments by if there is a global
105     /// slide.
106     lldb::addr_t slide = 0;
107     /// Resolved path for this dylib.
108     lldb_private::FileSpec file_spec;
109     /// UUID for this dylib if it has one, else all zeros.
110     lldb_private::UUID uuid;
111     /// The mach header for this image.
112     llvm::MachO::mach_header header;
113     /// All segment vmaddr and vmsize pairs for this executable (from
114     /// memory of inferior).
115     std::vector<Segment> segments;
116     /// The process stop ID that the sections for this image were
117     /// loaded.
118     uint32_t load_stop_id = 0;
119     /// LC_VERSION_MIN_... load command os type.
120     llvm::Triple::OSType os_type = llvm::Triple::OSType::UnknownOS;
121     /// LC_VERSION_MIN_... load command os environment.
122     llvm::Triple::EnvironmentType os_env =
123         llvm::Triple::EnvironmentType::UnknownEnvironment;
124     /// LC_VERSION_MIN_... SDK.
125     std::string min_version_os_sdk;
126 
127     ImageInfo() = default;
128 
129     void Clear(bool load_cmd_data_only) {
130       if (!load_cmd_data_only) {
131         address = LLDB_INVALID_ADDRESS;
132         slide = 0;
133         file_spec.Clear();
134         ::memset(&header, 0, sizeof(header));
135       }
136       uuid.Clear();
137       segments.clear();
138       load_stop_id = 0;
139       os_type = llvm::Triple::OSType::UnknownOS;
140       os_env = llvm::Triple::EnvironmentType::UnknownEnvironment;
141       min_version_os_sdk.clear();
142     }
143 
144     bool operator==(const ImageInfo &rhs) const {
145       return address == rhs.address && slide == rhs.slide &&
146              file_spec == rhs.file_spec && uuid == rhs.uuid &&
147              memcmp(&header, &rhs.header, sizeof(header)) == 0 &&
148              segments == rhs.segments && os_type == rhs.os_type &&
149              os_env == rhs.os_env;
150     }
151 
152     bool UUIDValid() const { return uuid.IsValid(); }
153 
154     uint32_t GetAddressByteSize() {
155       if (header.cputype) {
156         if (header.cputype & llvm::MachO::CPU_ARCH_ABI64)
157           return 8;
158         else
159           return 4;
160       }
161       return 0;
162     }
163 
164     lldb_private::ArchSpec GetArchitecture() const;
165 
166     const Segment *FindSegment(lldb_private::ConstString name) const;
167 
168     void PutToLog(lldb_private::Log *log) const;
169 
170     typedef std::vector<ImageInfo> collection;
171     typedef collection::iterator iterator;
172     typedef collection::const_iterator const_iterator;
173   };
174 
175   bool UpdateImageLoadAddress(lldb_private::Module *module, ImageInfo &info);
176 
177   bool UnloadModuleSections(lldb_private::Module *module, ImageInfo &info);
178 
179   lldb::ModuleSP FindTargetModuleForImageInfo(const ImageInfo &image_info,
180                                               bool can_create,
181                                               bool *did_create_ptr);
182 
183   void UnloadImages(const std::vector<lldb::addr_t> &solib_addresses);
184 
185   void UnloadAllImages();
186 
187   virtual bool SetNotificationBreakpoint() = 0;
188 
189   virtual void ClearNotificationBreakpoint() = 0;
190 
191   virtual bool DidSetNotificationBreakpoint() = 0;
192 
193   typedef std::map<uint64_t, lldb::addr_t> PthreadKeyToTLSMap;
194   typedef std::map<lldb::user_id_t, PthreadKeyToTLSMap> ThreadIDToTLSMap;
195 
196   std::recursive_mutex &GetMutex() const { return m_mutex; }
197 
198   lldb::ModuleSP GetPThreadLibraryModule();
199 
200   lldb_private::Address GetPthreadSetSpecificAddress();
201 
202   bool JSONImageInformationIntoImageInfo(
203       lldb_private::StructuredData::ObjectSP image_details,
204       ImageInfo::collection &image_infos);
205 
206   // Finds/loads modules for a given `image_infos` and returns pairs
207   // (ImageInfo, ModuleSP).
208   // Prefer using this method rather than calling `FindTargetModuleForImageInfo`
209   // directly as this method may load the modules in parallel.
210   std::vector<std::pair<ImageInfo, lldb::ModuleSP>>
211   PreloadModulesFromImageInfos(const ImageInfo::collection &image_infos);
212 
213   // If `images` contains / may contain dyld or executable image, call this
214   // method to keep our internal record keeping of the special binaries
215   // up-to-date.
216   void UpdateSpecialBinariesFromPreloadedModules(
217       std::vector<std::pair<ImageInfo, lldb::ModuleSP>> &images);
218 
219   // if image_info is a dyld binary, call this method
220   bool UpdateDYLDImageInfoFromNewImageInfo(ImageInfo &image_info);
221 
222   // If image_infos contains / may contain executable image, call this method
223   // to keep our internal record keeping of the special dyld binary up-to-date.
224   void AddExecutableModuleIfInImageInfos(ImageInfo::collection &image_infos);
225 
226   bool AddModulesUsingImageInfos(ImageInfo::collection &image_infos);
227   bool AddModulesUsingPreloadedModules(
228       std::vector<std::pair<ImageInfo, lldb::ModuleSP>> &images);
229 
230   // Whether we should use the new dyld SPI to get shared library information,
231   // or read
232   // it directly out of the dyld_all_image_infos.  Whether we use the (newer)
233   // DynamicLoaderMacOS
234   // plugin or the (older) DynamicLoaderMacOSX plugin.
235   static bool UseDYLDSPI(lldb_private::Process *process);
236 
237   lldb::ModuleWP m_dyld_module_wp; // the dyld whose file type (mac, ios, etc)
238                                    // matches the process
239   lldb::ModuleWP m_libpthread_module_wp;
240   lldb_private::Address m_pthread_getspecific_addr;
241   ThreadIDToTLSMap m_tid_to_tls_map;
242   ImageInfo::collection
243       m_dyld_image_infos;              // Current shared libraries information
244   uint32_t m_dyld_image_infos_stop_id; // The process stop ID that
245                                        // "m_dyld_image_infos" is valid for
246   ImageInfo m_dyld;
247   mutable std::recursive_mutex m_mutex;
248 
249 private:
250   DynamicLoaderDarwin(const DynamicLoaderDarwin &) = delete;
251   const DynamicLoaderDarwin &operator=(const DynamicLoaderDarwin &) = delete;
252 };
253 
254 } // namespace lldb_private
255 
256 #endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERDARWIN_H
257