xref: /llvm-project/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h (revision 944b828abbdf5e7b5284d8a11c7f0e08da3f9749)
1 //===-- DynamicLoaderDarwinKernel.h -----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef liblldb_DynamicLoaderDarwinKernel_h_
11 #define liblldb_DynamicLoaderDarwinKernel_h_
12 
13 // C Includes
14 // C++ Includes
15 #include <map>
16 #include <vector>
17 #include <string>
18 
19 // Other libraries and framework includes
20 #include "llvm/Support/MachO.h"
21 
22 #include "lldb/Target/DynamicLoader.h"
23 #include "lldb/Host/FileSpec.h"
24 #include "lldb/Host/TimeValue.h"
25 #include "lldb/Core/UUID.h"
26 #include "lldb/Host/Mutex.h"
27 #include "lldb/Target/Process.h"
28 
29 class DynamicLoaderDarwinKernel : public lldb_private::DynamicLoader
30 {
31 public:
32     //------------------------------------------------------------------
33     // Static Functions
34     //------------------------------------------------------------------
35     static void
36     Initialize();
37 
38     static void
39     Terminate();
40 
41     static const char *
42     GetPluginNameStatic();
43 
44     static const char *
45     GetPluginDescriptionStatic();
46 
47     static lldb_private::DynamicLoader *
48     CreateInstance (lldb_private::Process *process, bool force);
49 
50     DynamicLoaderDarwinKernel (lldb_private::Process *process);
51 
52     virtual
53     ~DynamicLoaderDarwinKernel ();
54     //------------------------------------------------------------------
55     /// Called after attaching a process.
56     ///
57     /// Allow DynamicLoader plug-ins to execute some code after
58     /// attaching to a process.
59     //------------------------------------------------------------------
60     virtual void
61     DidAttach ();
62 
63     virtual void
64     DidLaunch ();
65 
66     virtual lldb::ThreadPlanSP
67     GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
68                                   bool stop_others);
69 
70     virtual lldb_private::Error
71     CanLoadImage ();
72 
73     //------------------------------------------------------------------
74     // PluginInterface protocol
75     //------------------------------------------------------------------
76     virtual const char *
77     GetPluginName();
78 
79     virtual const char *
80     GetShortPluginName();
81 
82     virtual uint32_t
83     GetPluginVersion();
84 
85 protected:
86     void
87     PrivateInitialize (lldb_private::Process *process);
88 
89     void
90     PrivateProcessStateChanged (lldb_private::Process *process,
91                                 lldb::StateType state);
92 
93     void
94     UpdateIfNeeded();
95 
96     void
97     LoadKernelModuleIfNeeded ();
98 
99     void
100     Clear (bool clear_process);
101 
102     void
103     PutToLog (lldb_private::Log *log) const;
104 
105     static bool
106     BreakpointHitCallback (void *baton,
107                            lldb_private::StoppointCallbackContext *context,
108                            lldb::user_id_t break_id,
109                            lldb::user_id_t break_loc_id);
110 
111     bool
112     BreakpointHit (lldb_private::StoppointCallbackContext *context,
113                    lldb::user_id_t break_id,
114                    lldb::user_id_t break_loc_id);
115     uint32_t
116     AddrByteSize()
117     {
118         switch (m_kernel.header.magic)
119         {
120             case llvm::MachO::HeaderMagic32:
121             case llvm::MachO::HeaderMagic32Swapped:
122                 return 4;
123 
124             case llvm::MachO::HeaderMagic64:
125             case llvm::MachO::HeaderMagic64Swapped:
126                 return 8;
127 
128             default:
129                 break;
130         }
131         return 0;
132     }
133 
134     static lldb::ByteOrder
135     GetByteOrderFromMagic (uint32_t magic)
136     {
137         switch (magic)
138         {
139             case llvm::MachO::HeaderMagic32:
140             case llvm::MachO::HeaderMagic64:
141                 return lldb::endian::InlHostByteOrder();
142 
143             case llvm::MachO::HeaderMagic32Swapped:
144             case llvm::MachO::HeaderMagic64Swapped:
145                 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
146                     return lldb::eByteOrderLittle;
147                 else
148                     return lldb::eByteOrderBig;
149 
150             default:
151                 break;
152         }
153         return lldb::eByteOrderInvalid;
154     }
155 
156     class Segment
157     {
158     public:
159 
160         Segment() :
161             name(),
162             vmaddr(LLDB_INVALID_ADDRESS),
163             vmsize(0),
164             fileoff(0),
165             filesize(0),
166             maxprot(0),
167             initprot(0),
168             nsects(0),
169             flags(0)
170         {
171         }
172 
173         lldb_private::ConstString name;
174         lldb::addr_t vmaddr;
175         lldb::addr_t vmsize;
176         lldb::addr_t fileoff;
177         lldb::addr_t filesize;
178         uint32_t maxprot;
179         uint32_t initprot;
180         uint32_t nsects;
181         uint32_t flags;
182 
183         bool
184         operator==(const Segment& rhs) const
185         {
186             return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
187         }
188 
189         void
190         PutToLog (lldb_private::Log *log,
191                   lldb::addr_t slide) const;
192 
193     };
194 
195     enum
196     {
197         KERNEL_MODULE_MAX_NAME = 64u,
198         // Versions less than 2 didn't have an entry size,
199         // they had a 64 bit name, 16 byte UUID, 8 byte addr,
200         // 8 byte size, 8 byte version, 4 byte load tag, and
201         // 4 byte flags
202         KERNEL_MODULE_ENTRY_SIZE_VERSION_1 = 64u + 16u + 8u + 8u + 8u + 4u + 4u
203     };
204 
205     struct OSKextLoadedKextSummary
206     {
207         char                     name[KERNEL_MODULE_MAX_NAME];
208         lldb::ModuleSP           module_sp;
209         uint32_t                 module_create_stop_id;
210         lldb_private::UUID       uuid;            // UUID for this dylib if it has one, else all zeros
211         lldb_private::Address    so_address;        // The section offset address for this kext in case it can be read from object files
212         uint64_t                 address;
213         uint64_t                 size;
214         uint64_t                 version;
215         uint32_t                 load_tag;
216         uint32_t                 flags;
217         uint64_t                 reference_list;
218         llvm::MachO::mach_header header;    // The mach header for this image
219         std::vector<Segment>     segments;      // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
220 
221         OSKextLoadedKextSummary() :
222             module_sp (),
223             module_create_stop_id (UINT32_MAX),
224             uuid (),
225             so_address (),
226             address (LLDB_INVALID_ADDRESS),
227             size (0),
228             version (0),
229             load_tag (0),
230             flags (0),
231             reference_list (0),
232             header(),
233             segments()
234         {
235             name[0] = '\0';
236         }
237 
238         void
239         Clear (bool load_cmd_data_only)
240         {
241             if (!load_cmd_data_only)
242             {
243                 so_address.Clear();
244                 address = LLDB_INVALID_ADDRESS;
245                 size = 0;
246                 version = 0;
247                 load_tag = 0;
248                 flags = 0;
249                 reference_list = 0;
250                 name[0] = '\0';
251                 ::memset (&header, 0, sizeof(header));
252             }
253             module_sp.reset();
254             module_create_stop_id = UINT32_MAX;
255             uuid.Clear();
256             segments.clear();
257         }
258 
259         bool
260         operator == (const OSKextLoadedKextSummary& rhs) const
261         {
262             return  address == rhs.address
263                     && size == rhs.size
264             //&& module_sp.get() == rhs.module_sp.get()
265                     && uuid == rhs.uuid
266                     && version == rhs.version
267                     && load_tag == rhs.load_tag
268                     && flags == rhs.flags
269                     && reference_list == rhs.reference_list
270                     && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0
271                     && memcmp(&header, &rhs.header, sizeof(header)) == 0
272                     && segments == rhs.segments;
273         }
274 
275         bool
276         UUIDValid() const
277         {
278             return uuid.IsValid();
279         }
280 
281         uint32_t
282         GetAddressByteSize ()
283         {
284             if (header.cputype)
285             {
286                 if (header.cputype & llvm::MachO::CPUArchABI64)
287                     return 8;
288                 else
289                     return 4;
290             }
291             return 0;
292         }
293 
294         lldb::ByteOrder
295         GetByteOrder()
296         {
297             switch (header.magic)
298             {
299             case llvm::MachO::HeaderMagic32:        // MH_MAGIC
300             case llvm::MachO::HeaderMagic64:        // MH_MAGIC_64
301                 return lldb::endian::InlHostByteOrder();
302 
303             case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
304             case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
305                 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle)
306                     return lldb::eByteOrderBig;
307                 else
308                     return lldb::eByteOrderLittle;
309             default:
310                 assert (!"invalid header.magic value");
311                 break;
312             }
313             return lldb::endian::InlHostByteOrder();
314         }
315 
316         lldb_private::ArchSpec
317         GetArchitecture () const
318         {
319             return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
320         }
321 
322         const Segment *
323         FindSegment (const lldb_private::ConstString &name) const;
324 
325         void
326         PutToLog (lldb_private::Log *log) const;
327 
328         typedef std::vector<OSKextLoadedKextSummary> collection;
329         typedef collection::iterator iterator;
330         typedef collection::const_iterator const_iterator;
331     };
332 
333     struct OSKextLoadedKextSummaryHeader
334     {
335         uint32_t version;
336         uint32_t entry_size;
337         uint32_t entry_count;
338         lldb::addr_t image_infos_addr;
339 
340         OSKextLoadedKextSummaryHeader() :
341             version (0),
342             entry_size (0),
343             entry_count (0),
344             image_infos_addr (LLDB_INVALID_ADDRESS)
345         {
346         }
347 
348         uint32_t
349         GetSize()
350         {
351             switch (version)
352             {
353                 case 0: return 0;   // Can't know the size without a valid version
354                 case 1: return 8;   // Version 1 only had a version + entry_count
355                 default: break;
356             }
357             // Version 2 and above has version, entry_size, entry_count, and reserved
358             return 16;
359         }
360 
361         void
362         Clear()
363         {
364             version = 0;
365             entry_size = 0;
366             entry_count = 0;
367             image_infos_addr = LLDB_INVALID_ADDRESS;
368         }
369 
370         bool
371         IsValid() const
372         {
373             return version >= 1 || version <= 2;
374         }
375     };
376 
377     bool
378     ReadMachHeader (OSKextLoadedKextSummary& kext_summary,
379                     lldb_private::DataExtractor *load_command_data);
380 
381     void
382     RegisterNotificationCallbacks();
383 
384     void
385     UnregisterNotificationCallbacks();
386 
387     uint32_t
388     ParseLoadCommands (const lldb_private::DataExtractor& data,
389                        OSKextLoadedKextSummary& dylib_info);
390 
391     bool
392     UpdateImageLoadAddress(OSKextLoadedKextSummary& info);
393 
394     bool
395     FindTargetModule (OSKextLoadedKextSummary &image_info,
396                       bool can_create,
397                       bool *did_create_ptr);
398 
399     void
400     SetNotificationBreakpointIfNeeded ();
401 
402     bool
403     ReadAllKextSummaries ();
404 
405     bool
406     ReadKextSummaryHeader ();
407 
408     bool
409     ParseKextSummaries (const lldb_private::Address &kext_summary_addr,
410                         uint32_t count);
411 
412     bool
413     AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos);
414 
415     void
416     UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos,
417                                           uint32_t infos_count,
418                                           bool update_executable);
419 
420     bool
421     UpdateCommPageLoadAddress (lldb_private::Module *module);
422 
423     uint32_t
424     ReadKextSummaries (const lldb_private::Address &kext_summary_addr,
425                        uint32_t image_infos_count,
426                        OSKextLoadedKextSummary::collection &image_infos);
427 
428     bool
429     UnloadImageLoadAddress (OSKextLoadedKextSummary& info);
430 
431     OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used
432     lldb_private::Address m_kext_summary_header_ptr_addr;
433     lldb_private::Address m_kext_summary_header_addr;
434     OSKextLoadedKextSummaryHeader m_kext_summary_header;
435     OSKextLoadedKextSummary::collection m_kext_summaries;
436     mutable lldb_private::Mutex m_mutex;
437     lldb::user_id_t m_break_id;
438 
439 private:
440     DISALLOW_COPY_AND_ASSIGN (DynamicLoaderDarwinKernel);
441 };
442 
443 #endif  // liblldb_DynamicLoaderDarwinKernel_h_
444