blob: 5dddfedb1f0cc83c0d93ec6d11ddce441be1e6c5 [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);
92 bool
93 LoadKernelModule ();
94
95 bool
96 DidSetNotificationBreakpoint () const;
97
98 void
99 Clear (bool clear_process);
100
101 void
102 PutToLog (lldb_private::Log *log) const;
103
104 static bool
105 NotifyBreakpointHit (void *baton,
106 lldb_private::StoppointCallbackContext *context,
107 lldb::user_id_t break_id,
108 lldb::user_id_t break_loc_id);
109
110 uint32_t
111 AddrByteSize()
112 {
113 switch (m_kernel.header.magic)
114 {
115 case llvm::MachO::HeaderMagic32:
116 case llvm::MachO::HeaderMagic32Swapped:
117 return 4;
118
119 case llvm::MachO::HeaderMagic64:
120 case llvm::MachO::HeaderMagic64Swapped:
121 return 8;
122
123 default:
124 break;
125 }
126 return 0;
127 }
128
129 static lldb::ByteOrder
130 GetByteOrderFromMagic (uint32_t magic)
131 {
132 switch (magic)
133 {
134 case llvm::MachO::HeaderMagic32:
135 case llvm::MachO::HeaderMagic64:
136 return lldb::endian::InlHostByteOrder();
137
138 case llvm::MachO::HeaderMagic32Swapped:
139 case llvm::MachO::HeaderMagic64Swapped:
140 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
141 return lldb::eByteOrderLittle;
142 else
143 return lldb::eByteOrderBig;
144
145 default:
146 break;
147 }
148 return lldb::eByteOrderInvalid;
149 }
150
Greg Clayton7b242382011-07-08 00:48:09 +0000151 class Segment
152 {
153 public:
154
155 Segment() :
156 name(),
157 vmaddr(LLDB_INVALID_ADDRESS),
158 vmsize(0),
159 fileoff(0),
160 filesize(0),
161 maxprot(0),
162 initprot(0),
163 nsects(0),
164 flags(0)
165 {
166 }
167
168 lldb_private::ConstString name;
169 lldb::addr_t vmaddr;
170 lldb::addr_t vmsize;
171 lldb::addr_t fileoff;
172 lldb::addr_t filesize;
173 uint32_t maxprot;
174 uint32_t initprot;
175 uint32_t nsects;
176 uint32_t flags;
177
178 bool
179 operator==(const Segment& rhs) const
180 {
181 return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
182 }
183
184 void
185 PutToLog (lldb_private::Log *log,
186 lldb::addr_t slide) const;
187
188 };
189
190 enum { KERNEL_MODULE_MAX_NAME = 64u };
191
192 struct OSKextLoadedKextSummary
193 {
194 char name[KERNEL_MODULE_MAX_NAME];
195 lldb::ModuleSP module_sp;
Greg Claytondf0b7d52011-07-08 04:11:42 +0000196 uint32_t module_create_stop_id;
Greg Clayton7b242382011-07-08 00:48:09 +0000197 lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
Greg Clayton0d9fc762011-07-08 03:21:57 +0000198 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 +0000199 uint64_t address;
200 uint64_t size;
201 uint64_t version;
202 uint32_t load_tag;
203 uint32_t flags;
204 uint64_t reference_list;
205 llvm::MachO::mach_header header; // The mach header for this image
206 std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
207
208 OSKextLoadedKextSummary() :
209 module_sp (),
Greg Claytondf0b7d52011-07-08 04:11:42 +0000210 module_create_stop_id (UINT32_MAX),
Greg Clayton7b242382011-07-08 00:48:09 +0000211 uuid (),
Greg Clayton0d9fc762011-07-08 03:21:57 +0000212 so_address (),
Greg Clayton7b242382011-07-08 00:48:09 +0000213 address (LLDB_INVALID_ADDRESS),
214 size (0),
215 version (0),
216 load_tag (0),
217 flags (0),
218 reference_list (0),
219 header(),
220 segments()
221 {
222 name[0] = '\0';
223 }
224
225 void
226 Clear (bool load_cmd_data_only)
227 {
228 if (!load_cmd_data_only)
229 {
Greg Clayton0d9fc762011-07-08 03:21:57 +0000230 so_address.Clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000231 address = LLDB_INVALID_ADDRESS;
232 size = 0;
233 version = 0;
234 load_tag = 0;
235 flags = 0;
236 reference_list = 0;
237 name[0] = '\0';
238 ::memset (&header, 0, sizeof(header));
239 }
240 module_sp.reset();
Greg Claytondf0b7d52011-07-08 04:11:42 +0000241 module_create_stop_id = UINT32_MAX;
Greg Clayton7b242382011-07-08 00:48:09 +0000242 uuid.Clear();
243 segments.clear();
244 }
245
246 bool
247 operator == (const OSKextLoadedKextSummary& rhs) const
248 {
249 return address == rhs.address
250 && size == rhs.size
251 //&& module_sp.get() == rhs.module_sp.get()
252 && uuid == rhs.uuid
253 && version == rhs.version
254 && load_tag == rhs.load_tag
255 && flags == rhs.flags
256 && reference_list == rhs.reference_list
257 && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0
258 && memcmp(&header, &rhs.header, sizeof(header)) == 0
259 && segments == rhs.segments;
260 }
261
262 bool
263 UUIDValid() const
264 {
265 return uuid.IsValid();
266 }
267
268 uint32_t
269 GetAddressByteSize ()
270 {
271 if (header.cputype)
272 {
273 if (header.cputype & llvm::MachO::CPUArchABI64)
274 return 8;
275 else
276 return 4;
277 }
278 return 0;
279 }
280
281 lldb::ByteOrder
282 GetByteOrder()
283 {
284 switch (header.magic)
285 {
286 case llvm::MachO::HeaderMagic32: // MH_MAGIC
287 case llvm::MachO::HeaderMagic64: // MH_MAGIC_64
288 return lldb::endian::InlHostByteOrder();
289
290 case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
291 case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
292 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle)
293 return lldb::eByteOrderBig;
294 else
295 return lldb::eByteOrderLittle;
296 default:
297 assert (!"invalid header.magic value");
298 break;
299 }
300 return lldb::endian::InlHostByteOrder();
301 }
302
303 lldb_private::ArchSpec
304 GetArchitecture () const
305 {
306 return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
307 }
308
309 const Segment *
310 FindSegment (const lldb_private::ConstString &name) const;
311
312 void
313 PutToLog (lldb_private::Log *log) const;
314
315 typedef std::vector<OSKextLoadedKextSummary> collection;
316 typedef collection::iterator iterator;
317 typedef collection::const_iterator const_iterator;
318 };
319
320 struct OSKextLoadedKextSummaryHeader
321 {
322 uint32_t version;
323 uint32_t entry_size;
324 uint32_t entry_count;
325 uint32_t reserved; /* explicit alignment for gdb */
326 lldb::addr_t image_infos_addr;
327
328 OSKextLoadedKextSummaryHeader() :
329 version (0),
330 entry_size (0),
331 entry_count (0),
332 reserved (0),
333 image_infos_addr (LLDB_INVALID_ADDRESS)
334 {
335 }
336
337 void
338 Clear()
339 {
340 version = 0;
341 entry_size = 0;
342 entry_count = 0;
343 reserved = 0;
344 image_infos_addr = LLDB_INVALID_ADDRESS;
345 }
346
347 bool
348 IsValid() const
349 {
350 return version >= 1 || version <= 2;
351 }
352 };
353
Greg Clayton0d9fc762011-07-08 03:21:57 +0000354 bool
355 ReadMachHeader (OSKextLoadedKextSummary& kext_summary,
356 lldb_private::DataExtractor *load_command_data);
357
Greg Clayton7b242382011-07-08 00:48:09 +0000358 void
359 RegisterNotificationCallbacks();
360
361 void
362 UnregisterNotificationCallbacks();
363
364 uint32_t
365 ParseLoadCommands (const lldb_private::DataExtractor& data,
366 OSKextLoadedKextSummary& dylib_info);
367
368 bool
369 UpdateImageLoadAddress(OSKextLoadedKextSummary& info);
370
371 bool
372 FindTargetModule (OSKextLoadedKextSummary &image_info,
373 bool can_create,
374 bool *did_create_ptr);
375
376 bool
377 SetNotificationBreakpoint ();
378
379 bool
380 ReadAllKextSummaries (bool force);
381
382 bool
383 ReadKextSummaryHeader ();
384
385 bool
Greg Clayton0d9fc762011-07-08 03:21:57 +0000386 ParseKextSummaries (const lldb_private::Address &kext_summary_addr,
387 uint32_t count);
Greg Clayton7b242382011-07-08 00:48:09 +0000388
389 bool
390 AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos);
391
Greg Clayton7b242382011-07-08 00:48:09 +0000392 void
393 UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos,
394 uint32_t infos_count,
395 bool update_executable);
396
397 bool
398 UpdateCommPageLoadAddress (lldb_private::Module *module);
399
400 uint32_t
Greg Clayton0d9fc762011-07-08 03:21:57 +0000401 ReadKextSummaries (const lldb_private::Address &kext_summary_addr,
Greg Clayton7b242382011-07-08 00:48:09 +0000402 uint32_t image_infos_count,
403 OSKextLoadedKextSummary::collection &image_infos);
404
405 bool
406 UnloadImageLoadAddress (OSKextLoadedKextSummary& info);
407
408 OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used
Greg Clayton0d9fc762011-07-08 03:21:57 +0000409 lldb_private::Address m_kext_summary_header_addr;
Greg Clayton7b242382011-07-08 00:48:09 +0000410 OSKextLoadedKextSummaryHeader m_kext_summary_header;
411 uint32_t m_kext_summary_header_stop_id; // The process stop ID that "m_kext_summary_header" is valid for
412 lldb::user_id_t m_break_id;
413 OSKextLoadedKextSummary::collection m_kext_summaries;
414 uint32_t m_kext_summaries_stop_id; // The process stop ID that "m_kext_summaries" is valid for
415 mutable lldb_private::Mutex m_mutex;
416 lldb_private::Process::Notifications m_notification_callbacks;
417
418private:
419 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXKernel);
420};
421
422#endif // liblldb_DynamicLoaderMacOSXKernel_h_