blob: fd8a14a02365026e3799f8c8178f4876a24e5b9d [file] [log] [blame]
Greg Clayton944b8282011-08-22 22:30:57 +00001//===-- DynamicLoaderDarwinKernel.h -----------------------------*- C++ -*-===//
Greg Clayton7b242382011-07-08 00:48:09 +00002//
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
Greg Clayton944b8282011-08-22 22:30:57 +000010#ifndef liblldb_DynamicLoaderDarwinKernel_h_
11#define liblldb_DynamicLoaderDarwinKernel_h_
Greg Clayton7b242382011-07-08 00:48:09 +000012
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
Greg Clayton944b8282011-08-22 22:30:57 +000029class DynamicLoaderDarwinKernel : public lldb_private::DynamicLoader
Greg Clayton7b242382011-07-08 00:48:09 +000030{
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
Greg Clayton944b8282011-08-22 22:30:57 +000050 DynamicLoaderDarwinKernel (lldb_private::Process *process);
Greg Clayton7b242382011-07-08 00:48:09 +000051
52 virtual
Greg Clayton944b8282011-08-22 22:30:57 +000053 ~DynamicLoaderDarwinKernel ();
Greg Clayton7b242382011-07-08 00:48:09 +000054 //------------------------------------------------------------------
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
Greg Claytona63d08c2011-07-19 03:57:15 +0000195 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 };
Greg Clayton7b242382011-07-08 00:48:09 +0000204
205 struct OSKextLoadedKextSummary
206 {
207 char name[KERNEL_MODULE_MAX_NAME];
208 lldb::ModuleSP module_sp;
Greg Claytondf0b7d52011-07-08 04:11:42 +0000209 uint32_t module_create_stop_id;
Greg Clayton7b242382011-07-08 00:48:09 +0000210 lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
Greg Clayton0d9fc762011-07-08 03:21:57 +0000211 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 +0000212 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 (),
Greg Claytondf0b7d52011-07-08 04:11:42 +0000223 module_create_stop_id (UINT32_MAX),
Greg Clayton7b242382011-07-08 00:48:09 +0000224 uuid (),
Greg Clayton0d9fc762011-07-08 03:21:57 +0000225 so_address (),
Greg Clayton7b242382011-07-08 00:48:09 +0000226 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 {
Greg Clayton0d9fc762011-07-08 03:21:57 +0000243 so_address.Clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000244 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();
Greg Claytondf0b7d52011-07-08 04:11:42 +0000254 module_create_stop_id = UINT32_MAX;
Greg Clayton7b242382011-07-08 00:48:09 +0000255 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;
Greg Clayton7b242382011-07-08 00:48:09 +0000338 lldb::addr_t image_infos_addr;
339
340 OSKextLoadedKextSummaryHeader() :
341 version (0),
342 entry_size (0),
343 entry_count (0),
Greg Clayton7b242382011-07-08 00:48:09 +0000344 image_infos_addr (LLDB_INVALID_ADDRESS)
345 {
346 }
347
Greg Claytona63d08c2011-07-19 03:57:15 +0000348 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
Greg Clayton7b242382011-07-08 00:48:09 +0000361 void
362 Clear()
363 {
364 version = 0;
365 entry_size = 0;
366 entry_count = 0;
Greg Clayton7b242382011-07-08 00:48:09 +0000367 image_infos_addr = LLDB_INVALID_ADDRESS;
368 }
369
370 bool
371 IsValid() const
372 {
373 return version >= 1 || version <= 2;
374 }
375 };
376
Greg Clayton0d9fc762011-07-08 03:21:57 +0000377 bool
378 ReadMachHeader (OSKextLoadedKextSummary& kext_summary,
379 lldb_private::DataExtractor *load_command_data);
380
Greg Clayton7b242382011-07-08 00:48:09 +0000381 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
Greg Clayton374972e2011-07-09 17:15:55 +0000399 void
400 SetNotificationBreakpointIfNeeded ();
Greg Clayton7b242382011-07-08 00:48:09 +0000401
402 bool
Greg Clayton374972e2011-07-09 17:15:55 +0000403 ReadAllKextSummaries ();
Greg Clayton7b242382011-07-08 00:48:09 +0000404
405 bool
406 ReadKextSummaryHeader ();
407
408 bool
Greg Clayton0d9fc762011-07-08 03:21:57 +0000409 ParseKextSummaries (const lldb_private::Address &kext_summary_addr,
410 uint32_t count);
Greg Clayton7b242382011-07-08 00:48:09 +0000411
412 bool
413 AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos);
414
Greg Clayton7b242382011-07-08 00:48:09 +0000415 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
Greg Clayton0d9fc762011-07-08 03:21:57 +0000424 ReadKextSummaries (const lldb_private::Address &kext_summary_addr,
Greg Clayton7b242382011-07-08 00:48:09 +0000425 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
Greg Claytond16e1e52011-07-12 17:06:17 +0000432 lldb_private::Address m_kext_summary_header_ptr_addr;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000433 lldb_private::Address m_kext_summary_header_addr;
Greg Clayton7b242382011-07-08 00:48:09 +0000434 OSKextLoadedKextSummaryHeader m_kext_summary_header;
Greg Clayton7b242382011-07-08 00:48:09 +0000435 OSKextLoadedKextSummary::collection m_kext_summaries;
Greg Clayton7b242382011-07-08 00:48:09 +0000436 mutable lldb_private::Mutex m_mutex;
Greg Clayton374972e2011-07-09 17:15:55 +0000437 lldb::user_id_t m_break_id;
Greg Clayton7b242382011-07-08 00:48:09 +0000438
439private:
Greg Clayton944b8282011-08-22 22:30:57 +0000440 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderDarwinKernel);
Greg Clayton7b242382011-07-08 00:48:09 +0000441};
442
Greg Clayton944b8282011-08-22 22:30:57 +0000443#endif // liblldb_DynamicLoaderDarwinKernel_h_