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