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 | protected: |
60 | void PrivateInitialize(lldb_private::Process *process); |
61 | |
62 | void PrivateProcessStateChanged(lldb_private::Process *process, |
63 | lldb::StateType state); |
64 | |
65 | void Clear(bool clear_process); |
66 | |
67 | // Clear method for classes derived from this one |
68 | virtual void DoClear() = 0; |
69 | |
70 | void SetDYLDModule(lldb::ModuleSP &dyld_module_sp); |
71 | |
72 | lldb::ModuleSP GetDYLDModule(); |
73 | |
74 | void ClearDYLDModule(); |
75 | |
76 | class Segment { |
77 | public: |
78 | Segment() : name() {} |
79 | |
80 | lldb_private::ConstString name; |
81 | lldb::addr_t vmaddr = LLDB_INVALID_ADDRESS; |
82 | lldb::addr_t vmsize = 0; |
83 | lldb::addr_t fileoff = 0; |
84 | lldb::addr_t filesize = 0; |
85 | uint32_t maxprot = 0; |
86 | uint32_t initprot = 0; |
87 | uint32_t nsects = 0; |
88 | uint32_t flags = 0; |
89 | |
90 | bool operator==(const Segment &rhs) const { |
91 | return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize; |
92 | } |
93 | |
94 | void PutToLog(lldb_private::Log *log, lldb::addr_t slide) const; |
95 | }; |
96 | |
97 | struct ImageInfo { |
98 | /// Address of mach header for this dylib. |
99 | lldb::addr_t address = LLDB_INVALID_ADDRESS; |
100 | /// The amount to slide all segments by if there is a global |
101 | /// slide. |
102 | lldb::addr_t slide = 0; |
103 | /// Resolved path for this dylib. |
104 | lldb_private::FileSpec file_spec; |
105 | /// UUID for this dylib if it has one, else all zeros. |
106 | lldb_private::UUID uuid; |
107 | /// The mach header for this image. |
108 | llvm::MachO::mach_header ; |
109 | /// All segment vmaddr and vmsize pairs for this executable (from |
110 | /// memory of inferior). |
111 | std::vector<Segment> segments; |
112 | /// The process stop ID that the sections for this image were |
113 | /// loaded. |
114 | uint32_t load_stop_id = 0; |
115 | /// LC_VERSION_MIN_... load command os type. |
116 | llvm::Triple::OSType os_type = llvm::Triple::OSType::UnknownOS; |
117 | /// LC_VERSION_MIN_... load command os environment. |
118 | llvm::Triple::EnvironmentType os_env = |
119 | llvm::Triple::EnvironmentType::UnknownEnvironment; |
120 | /// LC_VERSION_MIN_... SDK. |
121 | std::string min_version_os_sdk; |
122 | |
123 | ImageInfo() = default; |
124 | |
125 | void Clear(bool load_cmd_data_only) { |
126 | if (!load_cmd_data_only) { |
127 | address = LLDB_INVALID_ADDRESS; |
128 | slide = 0; |
129 | file_spec.Clear(); |
130 | ::memset(s: &header, c: 0, n: sizeof(header)); |
131 | } |
132 | uuid.Clear(); |
133 | segments.clear(); |
134 | load_stop_id = 0; |
135 | os_type = llvm::Triple::OSType::UnknownOS; |
136 | os_env = llvm::Triple::EnvironmentType::UnknownEnvironment; |
137 | min_version_os_sdk.clear(); |
138 | } |
139 | |
140 | bool operator==(const ImageInfo &rhs) const { |
141 | return address == rhs.address && slide == rhs.slide && |
142 | file_spec == rhs.file_spec && uuid == rhs.uuid && |
143 | memcmp(s1: &header, s2: &rhs.header, n: sizeof(header)) == 0 && |
144 | segments == rhs.segments && os_type == rhs.os_type && |
145 | os_env == rhs.os_env; |
146 | } |
147 | |
148 | bool UUIDValid() const { return uuid.IsValid(); } |
149 | |
150 | uint32_t GetAddressByteSize() { |
151 | if (header.cputype) { |
152 | if (header.cputype & llvm::MachO::CPU_ARCH_ABI64) |
153 | return 8; |
154 | else |
155 | return 4; |
156 | } |
157 | return 0; |
158 | } |
159 | |
160 | lldb_private::ArchSpec GetArchitecture() const; |
161 | |
162 | const Segment *FindSegment(lldb_private::ConstString name) const; |
163 | |
164 | void PutToLog(lldb_private::Log *log) const; |
165 | |
166 | typedef std::vector<ImageInfo> collection; |
167 | typedef collection::iterator iterator; |
168 | typedef collection::const_iterator const_iterator; |
169 | }; |
170 | |
171 | bool UpdateImageLoadAddress(lldb_private::Module *module, ImageInfo &info); |
172 | |
173 | bool UnloadModuleSections(lldb_private::Module *module, ImageInfo &info); |
174 | |
175 | lldb::ModuleSP FindTargetModuleForImageInfo(ImageInfo &image_info, |
176 | bool can_create, |
177 | bool *did_create_ptr); |
178 | |
179 | void UnloadImages(const std::vector<lldb::addr_t> &solib_addresses); |
180 | |
181 | void UnloadAllImages(); |
182 | |
183 | virtual bool SetNotificationBreakpoint() = 0; |
184 | |
185 | virtual void ClearNotificationBreakpoint() = 0; |
186 | |
187 | virtual bool DidSetNotificationBreakpoint() = 0; |
188 | |
189 | typedef std::map<uint64_t, lldb::addr_t> PthreadKeyToTLSMap; |
190 | typedef std::map<lldb::user_id_t, PthreadKeyToTLSMap> ThreadIDToTLSMap; |
191 | |
192 | std::recursive_mutex &GetMutex() const { return m_mutex; } |
193 | |
194 | lldb::ModuleSP GetPThreadLibraryModule(); |
195 | |
196 | lldb_private::Address GetPthreadSetSpecificAddress(); |
197 | |
198 | bool JSONImageInformationIntoImageInfo( |
199 | lldb_private::StructuredData::ObjectSP image_details, |
200 | ImageInfo::collection &image_infos); |
201 | |
202 | // If image_infos contains / may contain dyld or executable image, call this |
203 | // method |
204 | // to keep our internal record keeping of the special binaries up-to-date. |
205 | void |
206 | UpdateSpecialBinariesFromNewImageInfos(ImageInfo::collection &image_infos); |
207 | |
208 | // if image_info is a dyld binary, call this method |
209 | void UpdateDYLDImageInfoFromNewImageInfo(ImageInfo &image_info); |
210 | |
211 | // If image_infos contains / may contain executable image, call this method |
212 | // to keep our internal record keeping of the special dyld binary up-to-date. |
213 | void AddExecutableModuleIfInImageInfos(ImageInfo::collection &image_infos); |
214 | |
215 | bool AddModulesUsingImageInfos(ImageInfo::collection &image_infos); |
216 | |
217 | // Whether we should use the new dyld SPI to get shared library information, |
218 | // or read |
219 | // it directly out of the dyld_all_image_infos. Whether we use the (newer) |
220 | // DynamicLoaderMacOS |
221 | // plugin or the (older) DynamicLoaderMacOSX plugin. |
222 | static bool UseDYLDSPI(lldb_private::Process *process); |
223 | |
224 | lldb::ModuleWP m_dyld_module_wp; // the dyld whose file type (mac, ios, etc) |
225 | // matches the process |
226 | lldb::ModuleWP m_libpthread_module_wp; |
227 | lldb_private::Address m_pthread_getspecific_addr; |
228 | ThreadIDToTLSMap m_tid_to_tls_map; |
229 | ImageInfo::collection |
230 | m_dyld_image_infos; // Current shared libraries information |
231 | uint32_t m_dyld_image_infos_stop_id; // The process stop ID that |
232 | // "m_dyld_image_infos" is valid for |
233 | ImageInfo m_dyld; |
234 | mutable std::recursive_mutex m_mutex; |
235 | |
236 | private: |
237 | DynamicLoaderDarwin(const DynamicLoaderDarwin &) = delete; |
238 | const DynamicLoaderDarwin &operator=(const DynamicLoaderDarwin &) = delete; |
239 | }; |
240 | |
241 | } // namespace lldb_private |
242 | |
243 | #endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERDARWIN_H |
244 | |