blob: c2066f56269d7e0905ff5bd90b8c99d084facf04 [file] [log] [blame]
Greg Clayton7b242382011-07-08 00:48:09 +00001//===-- DynamicLoaderMacOSXKernel.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_DynamicLoaderMacOSXKernel_h_
11#define liblldb_DynamicLoaderMacOSXKernel_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
29class DynamicLoaderMacOSXKernel : public lldb_private::DynamicLoader
30{
31public:
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 DynamicLoaderMacOSXKernel (lldb_private::Process *process);
51
52 virtual
53 ~DynamicLoaderMacOSXKernel ();
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
85protected:
86 void
87 PrivateInitialize (lldb_private::Process *process);
88
89 void
90 PrivateProcessStateChanged (lldb_private::Process *process,
91 lldb::StateType state);
Greg Clayton374972e2011-07-09 17:15:55 +000092
93 void
94 UpdateIfNeeded();
Greg Clayton7b242382011-07-08 00:48:09 +000095
Greg Clayton374972e2011-07-09 17:15:55 +000096 void
97 LoadKernelModuleIfNeeded ();
Greg Clayton7b242382011-07-08 00:48:09 +000098
99 void
100 Clear (bool clear_process);
101
102 void
103 PutToLog (lldb_private::Log *log) const;
104
105 static bool
Greg Clayton374972e2011-07-09 17:15:55 +0000106 BreakpointHitCallback (void *baton,
107 lldb_private::StoppointCallbackContext *context,
108 lldb::user_id_t break_id,
109 lldb::user_id_t break_loc_id);
Greg Clayton7b242382011-07-08 00:48:09 +0000110
Greg Clayton374972e2011-07-09 17:15:55 +0000111 bool
112 BreakpointHit (lldb_private::StoppointCallbackContext *context,
113 lldb::user_id_t break_id,
114 lldb::user_id_t break_loc_id);
Greg Clayton7b242382011-07-08 00:48:09 +0000115 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
Greg Clayton7b242382011-07-08 00:48:09 +0000156 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 { KERNEL_MODULE_MAX_NAME = 64u };
196
197 struct OSKextLoadedKextSummary
198 {
199 char name[KERNEL_MODULE_MAX_NAME];
200 lldb::ModuleSP module_sp;
Greg Claytondf0b7d52011-07-08 04:11:42 +0000201 uint32_t module_create_stop_id;
Greg Clayton7b242382011-07-08 00:48:09 +0000202 lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
Greg Clayton0d9fc762011-07-08 03:21:57 +0000203 lldb_private::Address so_address; // The section offset address for this kext in case it can be read from object files
Greg Clayton7b242382011-07-08 00:48:09 +0000204 uint64_t address;
205 uint64_t size;
206 uint64_t version;
207 uint32_t load_tag;
208 uint32_t flags;
209 uint64_t reference_list;
210 llvm::MachO::mach_header header; // The mach header for this image
211 std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
212
213 OSKextLoadedKextSummary() :
214 module_sp (),
Greg Claytondf0b7d52011-07-08 04:11:42 +0000215 module_create_stop_id (UINT32_MAX),
Greg Clayton7b242382011-07-08 00:48:09 +0000216 uuid (),
Greg Clayton0d9fc762011-07-08 03:21:57 +0000217 so_address (),
Greg Clayton7b242382011-07-08 00:48:09 +0000218 address (LLDB_INVALID_ADDRESS),
219 size (0),
220 version (0),
221 load_tag (0),
222 flags (0),
223 reference_list (0),
224 header(),
225 segments()
226 {
227 name[0] = '\0';
228 }
229
230 void
231 Clear (bool load_cmd_data_only)
232 {
233 if (!load_cmd_data_only)
234 {
Greg Clayton0d9fc762011-07-08 03:21:57 +0000235 so_address.Clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000236 address = LLDB_INVALID_ADDRESS;
237 size = 0;
238 version = 0;
239 load_tag = 0;
240 flags = 0;
241 reference_list = 0;
242 name[0] = '\0';
243 ::memset (&header, 0, sizeof(header));
244 }
245 module_sp.reset();
Greg Claytondf0b7d52011-07-08 04:11:42 +0000246 module_create_stop_id = UINT32_MAX;
Greg Clayton7b242382011-07-08 00:48:09 +0000247 uuid.Clear();
248 segments.clear();
249 }
250
251 bool
252 operator == (const OSKextLoadedKextSummary& rhs) const
253 {
254 return address == rhs.address
255 && size == rhs.size
256 //&& module_sp.get() == rhs.module_sp.get()
257 && uuid == rhs.uuid
258 && version == rhs.version
259 && load_tag == rhs.load_tag
260 && flags == rhs.flags
261 && reference_list == rhs.reference_list
262 && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0
263 && memcmp(&header, &rhs.header, sizeof(header)) == 0
264 && segments == rhs.segments;
265 }
266
267 bool
268 UUIDValid() const
269 {
270 return uuid.IsValid();
271 }
272
273 uint32_t
274 GetAddressByteSize ()
275 {
276 if (header.cputype)
277 {
278 if (header.cputype & llvm::MachO::CPUArchABI64)
279 return 8;
280 else
281 return 4;
282 }
283 return 0;
284 }
285
286 lldb::ByteOrder
287 GetByteOrder()
288 {
289 switch (header.magic)
290 {
291 case llvm::MachO::HeaderMagic32: // MH_MAGIC
292 case llvm::MachO::HeaderMagic64: // MH_MAGIC_64
293 return lldb::endian::InlHostByteOrder();
294
295 case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
296 case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
297 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle)
298 return lldb::eByteOrderBig;
299 else
300 return lldb::eByteOrderLittle;
301 default:
302 assert (!"invalid header.magic value");
303 break;
304 }
305 return lldb::endian::InlHostByteOrder();
306 }
307
308 lldb_private::ArchSpec
309 GetArchitecture () const
310 {
311 return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
312 }
313
314 const Segment *
315 FindSegment (const lldb_private::ConstString &name) const;
316
317 void
318 PutToLog (lldb_private::Log *log) const;
319
320 typedef std::vector<OSKextLoadedKextSummary> collection;
321 typedef collection::iterator iterator;
322 typedef collection::const_iterator const_iterator;
323 };
324
325 struct OSKextLoadedKextSummaryHeader
326 {
327 uint32_t version;
328 uint32_t entry_size;
329 uint32_t entry_count;
330 uint32_t reserved; /* explicit alignment for gdb */
331 lldb::addr_t image_infos_addr;
332
333 OSKextLoadedKextSummaryHeader() :
334 version (0),
335 entry_size (0),
336 entry_count (0),
337 reserved (0),
338 image_infos_addr (LLDB_INVALID_ADDRESS)
339 {
340 }
341
342 void
343 Clear()
344 {
345 version = 0;
346 entry_size = 0;
347 entry_count = 0;
348 reserved = 0;
349 image_infos_addr = LLDB_INVALID_ADDRESS;
350 }
351
352 bool
353 IsValid() const
354 {
355 return version >= 1 || version <= 2;
356 }
357 };
358
Greg Clayton0d9fc762011-07-08 03:21:57 +0000359 bool
360 ReadMachHeader (OSKextLoadedKextSummary& kext_summary,
361 lldb_private::DataExtractor *load_command_data);
362
Greg Clayton7b242382011-07-08 00:48:09 +0000363 void
364 RegisterNotificationCallbacks();
365
366 void
367 UnregisterNotificationCallbacks();
368
369 uint32_t
370 ParseLoadCommands (const lldb_private::DataExtractor& data,
371 OSKextLoadedKextSummary& dylib_info);
372
373 bool
374 UpdateImageLoadAddress(OSKextLoadedKextSummary& info);
375
376 bool
377 FindTargetModule (OSKextLoadedKextSummary &image_info,
378 bool can_create,
379 bool *did_create_ptr);
380
Greg Clayton374972e2011-07-09 17:15:55 +0000381 void
382 SetNotificationBreakpointIfNeeded ();
Greg Clayton7b242382011-07-08 00:48:09 +0000383
384 bool
Greg Clayton374972e2011-07-09 17:15:55 +0000385 ReadAllKextSummaries ();
Greg Clayton7b242382011-07-08 00:48:09 +0000386
387 bool
388 ReadKextSummaryHeader ();
389
390 bool
Greg Clayton0d9fc762011-07-08 03:21:57 +0000391 ParseKextSummaries (const lldb_private::Address &kext_summary_addr,
392 uint32_t count);
Greg Clayton7b242382011-07-08 00:48:09 +0000393
394 bool
395 AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos);
396
Greg Clayton7b242382011-07-08 00:48:09 +0000397 void
398 UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos,
399 uint32_t infos_count,
400 bool update_executable);
401
402 bool
403 UpdateCommPageLoadAddress (lldb_private::Module *module);
404
405 uint32_t
Greg Clayton0d9fc762011-07-08 03:21:57 +0000406 ReadKextSummaries (const lldb_private::Address &kext_summary_addr,
Greg Clayton7b242382011-07-08 00:48:09 +0000407 uint32_t image_infos_count,
408 OSKextLoadedKextSummary::collection &image_infos);
409
410 bool
411 UnloadImageLoadAddress (OSKextLoadedKextSummary& info);
412
413 OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used
Greg Claytond16e1e52011-07-12 17:06:17 +0000414 lldb_private::Address m_kext_summary_header_ptr_addr;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000415 lldb_private::Address m_kext_summary_header_addr;
Greg Clayton7b242382011-07-08 00:48:09 +0000416 OSKextLoadedKextSummaryHeader m_kext_summary_header;
Greg Clayton7b242382011-07-08 00:48:09 +0000417 OSKextLoadedKextSummary::collection m_kext_summaries;
Greg Clayton7b242382011-07-08 00:48:09 +0000418 mutable lldb_private::Mutex m_mutex;
Greg Clayton374972e2011-07-09 17:15:55 +0000419 lldb::user_id_t m_break_id;
Greg Clayton7b242382011-07-08 00:48:09 +0000420
421private:
422 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXKernel);
423};
424
425#endif // liblldb_DynamicLoaderMacOSXKernel_h_