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     GetAddrByteSize()
117     {
118         return m_kernel.GetAddressByteSize();
119     }
120 
121     static lldb::ByteOrder
122     GetByteOrderFromMagic (uint32_t magic)
123     {
124         switch (magic)
125         {
126             case llvm::MachO::HeaderMagic32:
127             case llvm::MachO::HeaderMagic64:
128                 return lldb::endian::InlHostByteOrder();
129 
130             case llvm::MachO::HeaderMagic32Swapped:
131             case llvm::MachO::HeaderMagic64Swapped:
132                 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
133                     return lldb::eByteOrderLittle;
134                 else
135                     return lldb::eByteOrderBig;
136 
137             default:
138                 break;
139         }
140         return lldb::eByteOrderInvalid;
141     }
142     enum
143     {
144         KERNEL_MODULE_MAX_NAME = 64u,
145         // Versions less than 2 didn't have an entry size,
146         // they had a 64 bit name, 16 byte UUID, 8 byte addr,
147         // 8 byte size, 8 byte version, 4 byte load tag, and
148         // 4 byte flags
149         KERNEL_MODULE_ENTRY_SIZE_VERSION_1 = 64u + 16u + 8u + 8u + 8u + 4u + 4u
150     };
151 
152     struct OSKextLoadedKextSummary
153     {
154         char                     name[KERNEL_MODULE_MAX_NAME];
155         lldb::ModuleSP           module_sp;
156         uint32_t                 load_process_stop_id;
157         lldb_private::UUID       uuid;            // UUID for this dylib if it has one, else all zeros
158         lldb_private::Address    so_address;        // The section offset address for this kext in case it can be read from object files
159         uint64_t                 address;
160         uint64_t                 size;
161         uint64_t                 version;
162         uint32_t                 load_tag;
163         uint32_t                 flags;
164         uint64_t                 reference_list;
165 
166         OSKextLoadedKextSummary() :
167             module_sp (),
168             load_process_stop_id (UINT32_MAX),
169             uuid (),
170             so_address (),
171             address (LLDB_INVALID_ADDRESS),
172             size (0),
173             version (0),
174             load_tag (0),
175             flags (0),
176             reference_list (0)
177         {
178             name[0] = '\0';
179         }
180 
181         bool
182         IsLoaded ()
183         {
184             return load_process_stop_id != UINT32_MAX;
185         }
186 
187         void
188         Clear (bool load_cmd_data_only)
189         {
190             if (!load_cmd_data_only)
191             {
192                 so_address.Clear();
193                 address = LLDB_INVALID_ADDRESS;
194                 size = 0;
195                 version = 0;
196                 load_tag = 0;
197                 flags = 0;
198                 reference_list = 0;
199                 name[0] = '\0';
200             }
201             module_sp.reset();
202             load_process_stop_id = UINT32_MAX;
203         }
204 
205         bool
206         LoadImageAtFileAddress (lldb_private::Process *process);
207 
208         bool
209         LoadImageUsingMemoryModule (lldb_private::Process *process);
210 
211 //        bool
212 //        operator == (const OSKextLoadedKextSummary& rhs) const
213 //        {
214 //            return  address == rhs.address
215 //                    && size == rhs.size
216 //            //&& module_sp.get() == rhs.module_sp.get()
217 //                    && uuid == rhs.uuid
218 //                    && version == rhs.version
219 //                    && load_tag == rhs.load_tag
220 //                    && flags == rhs.flags
221 //                    && reference_list == rhs.reference_list
222 //                    && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0;
223 //        }
224 //
225         bool
226         UUIDValid() const
227         {
228             return uuid.IsValid();
229         }
230 
231         uint32_t
232         GetAddressByteSize ()
233         {
234             if (module_sp)
235                 return module_sp->GetArchitecture().GetAddressByteSize();
236             return 0;
237         }
238 
239         lldb::ByteOrder
240         GetByteOrder()
241         {
242             if (module_sp)
243                 return module_sp->GetArchitecture().GetByteOrder();
244             return lldb::endian::InlHostByteOrder();
245         }
246 
247         lldb_private::ArchSpec
248         GetArchitecture () const
249         {
250             if (module_sp)
251                 return module_sp->GetArchitecture();
252             return lldb_private::ArchSpec ();
253         }
254 
255         void
256         PutToLog (lldb_private::Log *log) const;
257 
258         typedef std::vector<OSKextLoadedKextSummary> collection;
259         typedef collection::iterator iterator;
260         typedef collection::const_iterator const_iterator;
261     };
262 
263     struct OSKextLoadedKextSummaryHeader
264     {
265         uint32_t version;
266         uint32_t entry_size;
267         uint32_t entry_count;
268         lldb::addr_t image_infos_addr;
269 
270         OSKextLoadedKextSummaryHeader() :
271             version (0),
272             entry_size (0),
273             entry_count (0),
274             image_infos_addr (LLDB_INVALID_ADDRESS)
275         {
276         }
277 
278         uint32_t
279         GetSize()
280         {
281             switch (version)
282             {
283                 case 0: return 0;   // Can't know the size without a valid version
284                 case 1: return 8;   // Version 1 only had a version + entry_count
285                 default: break;
286             }
287             // Version 2 and above has version, entry_size, entry_count, and reserved
288             return 16;
289         }
290 
291         void
292         Clear()
293         {
294             version = 0;
295             entry_size = 0;
296             entry_count = 0;
297             image_infos_addr = LLDB_INVALID_ADDRESS;
298         }
299 
300         bool
301         IsValid() const
302         {
303             return version >= 1 || version <= 2;
304         }
305     };
306 
307     void
308     RegisterNotificationCallbacks();
309 
310     void
311     UnregisterNotificationCallbacks();
312 
313     void
314     SetNotificationBreakpointIfNeeded ();
315 
316     bool
317     ReadAllKextSummaries ();
318 
319     bool
320     ReadKextSummaryHeader ();
321 
322     bool
323     ParseKextSummaries (const lldb_private::Address &kext_summary_addr,
324                         uint32_t count);
325 
326     bool
327     AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos);
328 
329     void
330     UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos,
331                                           uint32_t infos_count,
332                                           bool update_executable);
333 
334     uint32_t
335     ReadKextSummaries (const lldb_private::Address &kext_summary_addr,
336                        uint32_t image_infos_count,
337                        OSKextLoadedKextSummary::collection &image_infos);
338 
339     OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used
340     lldb_private::Address m_kext_summary_header_ptr_addr;
341     lldb_private::Address m_kext_summary_header_addr;
342     OSKextLoadedKextSummaryHeader m_kext_summary_header;
343     OSKextLoadedKextSummary::collection m_kext_summaries;
344     mutable lldb_private::Mutex m_mutex;
345     lldb::user_id_t m_break_id;
346 
347 private:
348     DISALLOW_COPY_AND_ASSIGN (DynamicLoaderDarwinKernel);
349 };
350 
351 #endif  // liblldb_DynamicLoaderDarwinKernel_h_
352