/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
Line | Count | Source (jump to first uncovered line) |
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 | 354k | 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 | 0 | bool operator==(const Segment &rhs) const { |
91 | 0 | return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize; |
92 | 0 | } |
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 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 | 115k | ImageInfo() = default; |
124 | | |
125 | 2.15k | void Clear(bool load_cmd_data_only) { |
126 | 2.15k | if (!load_cmd_data_only) { |
127 | 2.15k | address = LLDB_INVALID_ADDRESS; |
128 | 2.15k | slide = 0; |
129 | 2.15k | file_spec.Clear(); |
130 | 2.15k | ::memset(&header, 0, sizeof(header)); |
131 | 2.15k | } |
132 | 2.15k | uuid.Clear(); |
133 | 2.15k | segments.clear(); |
134 | 2.15k | load_stop_id = 0; |
135 | 2.15k | os_type = llvm::Triple::OSType::UnknownOS; |
136 | 2.15k | os_env = llvm::Triple::EnvironmentType::UnknownEnvironment; |
137 | 2.15k | min_version_os_sdk.clear(); |
138 | 2.15k | } |
139 | | |
140 | 0 | bool operator==(const ImageInfo &rhs) const { |
141 | 0 | return address == rhs.address && slide == rhs.slide && |
142 | 0 | file_spec == rhs.file_spec && uuid == rhs.uuid && |
143 | 0 | memcmp(&header, &rhs.header, sizeof(header)) == 0 && |
144 | 0 | segments == rhs.segments && os_type == rhs.os_type && |
145 | 0 | os_env == rhs.os_env; |
146 | 0 | } |
147 | | |
148 | 0 | bool UUIDValid() const { return uuid.IsValid(); } |
149 | | |
150 | 0 | uint32_t GetAddressByteSize() { |
151 | 0 | if (header.cputype) { |
152 | 0 | if (header.cputype & llvm::MachO::CPU_ARCH_ABI64) |
153 | 0 | return 8; |
154 | 0 | else |
155 | 0 | return 4; |
156 | 0 | } |
157 | 0 | return 0; |
158 | 0 | } |
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 | 14 | 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 |