blob: e6de4041c22dff8bd7b3075eb0ea471fe835d7d9 [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;
196 lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
Greg Clayton0d9fc762011-07-08 03:21:57 +0000197 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 +0000198 uint64_t address;
199 uint64_t size;
200 uint64_t version;
201 uint32_t load_tag;
202 uint32_t flags;
203 uint64_t reference_list;
204 llvm::MachO::mach_header header; // The mach header for this image
205 std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
206
207 OSKextLoadedKextSummary() :
208 module_sp (),
209 uuid (),
Greg Clayton0d9fc762011-07-08 03:21:57 +0000210 so_address (),
Greg Clayton7b242382011-07-08 00:48:09 +0000211 address (LLDB_INVALID_ADDRESS),
212 size (0),
213 version (0),
214 load_tag (0),
215 flags (0),
216 reference_list (0),
217 header(),
218 segments()
219 {
220 name[0] = '\0';
221 }
222
223 void
224 Clear (bool load_cmd_data_only)
225 {
226 if (!load_cmd_data_only)
227 {
Greg Clayton0d9fc762011-07-08 03:21:57 +0000228 so_address.Clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000229 address = LLDB_INVALID_ADDRESS;
230 size = 0;
231 version = 0;
232 load_tag = 0;
233 flags = 0;
234 reference_list = 0;
235 name[0] = '\0';
236 ::memset (&header, 0, sizeof(header));
237 }
238 module_sp.reset();
239 uuid.Clear();
240 segments.clear();
241 }
242
243 bool
244 operator == (const OSKextLoadedKextSummary& rhs) const
245 {
246 return address == rhs.address
247 && size == rhs.size
248 //&& module_sp.get() == rhs.module_sp.get()
249 && uuid == rhs.uuid
250 && version == rhs.version
251 && load_tag == rhs.load_tag
252 && flags == rhs.flags
253 && reference_list == rhs.reference_list
254 && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0
255 && memcmp(&header, &rhs.header, sizeof(header)) == 0
256 && segments == rhs.segments;
257 }
258
259 bool
260 UUIDValid() const
261 {
262 return uuid.IsValid();
263 }
264
265 uint32_t
266 GetAddressByteSize ()
267 {
268 if (header.cputype)
269 {
270 if (header.cputype & llvm::MachO::CPUArchABI64)
271 return 8;
272 else
273 return 4;
274 }
275 return 0;
276 }
277
278 lldb::ByteOrder
279 GetByteOrder()
280 {
281 switch (header.magic)
282 {
283 case llvm::MachO::HeaderMagic32: // MH_MAGIC
284 case llvm::MachO::HeaderMagic64: // MH_MAGIC_64
285 return lldb::endian::InlHostByteOrder();
286
287 case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
288 case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
289 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle)
290 return lldb::eByteOrderBig;
291 else
292 return lldb::eByteOrderLittle;
293 default:
294 assert (!"invalid header.magic value");
295 break;
296 }
297 return lldb::endian::InlHostByteOrder();
298 }
299
300 lldb_private::ArchSpec
301 GetArchitecture () const
302 {
303 return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
304 }
305
306 const Segment *
307 FindSegment (const lldb_private::ConstString &name) const;
308
309 void
310 PutToLog (lldb_private::Log *log) const;
311
312 typedef std::vector<OSKextLoadedKextSummary> collection;
313 typedef collection::iterator iterator;
314 typedef collection::const_iterator const_iterator;
315 };
316
317 struct OSKextLoadedKextSummaryHeader
318 {
319 uint32_t version;
320 uint32_t entry_size;
321 uint32_t entry_count;
322 uint32_t reserved; /* explicit alignment for gdb */
323 lldb::addr_t image_infos_addr;
324
325 OSKextLoadedKextSummaryHeader() :
326 version (0),
327 entry_size (0),
328 entry_count (0),
329 reserved (0),
330 image_infos_addr (LLDB_INVALID_ADDRESS)
331 {
332 }
333
334 void
335 Clear()
336 {
337 version = 0;
338 entry_size = 0;
339 entry_count = 0;
340 reserved = 0;
341 image_infos_addr = LLDB_INVALID_ADDRESS;
342 }
343
344 bool
345 IsValid() const
346 {
347 return version >= 1 || version <= 2;
348 }
349 };
350
Greg Clayton0d9fc762011-07-08 03:21:57 +0000351 bool
352 ReadMachHeader (OSKextLoadedKextSummary& kext_summary,
353 lldb_private::DataExtractor *load_command_data);
354
Greg Clayton7b242382011-07-08 00:48:09 +0000355 void
356 RegisterNotificationCallbacks();
357
358 void
359 UnregisterNotificationCallbacks();
360
361 uint32_t
362 ParseLoadCommands (const lldb_private::DataExtractor& data,
363 OSKextLoadedKextSummary& dylib_info);
364
365 bool
366 UpdateImageLoadAddress(OSKextLoadedKextSummary& info);
367
368 bool
369 FindTargetModule (OSKextLoadedKextSummary &image_info,
370 bool can_create,
371 bool *did_create_ptr);
372
373 bool
374 SetNotificationBreakpoint ();
375
376 bool
377 ReadAllKextSummaries (bool force);
378
379 bool
380 ReadKextSummaryHeader ();
381
382 bool
Greg Clayton0d9fc762011-07-08 03:21:57 +0000383 ParseKextSummaries (const lldb_private::Address &kext_summary_addr,
384 uint32_t count);
Greg Clayton7b242382011-07-08 00:48:09 +0000385
386 bool
387 AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos);
388
Greg Clayton7b242382011-07-08 00:48:09 +0000389 void
390 UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos,
391 uint32_t infos_count,
392 bool update_executable);
393
394 bool
395 UpdateCommPageLoadAddress (lldb_private::Module *module);
396
397 uint32_t
Greg Clayton0d9fc762011-07-08 03:21:57 +0000398 ReadKextSummaries (const lldb_private::Address &kext_summary_addr,
Greg Clayton7b242382011-07-08 00:48:09 +0000399 uint32_t image_infos_count,
400 OSKextLoadedKextSummary::collection &image_infos);
401
402 bool
403 UnloadImageLoadAddress (OSKextLoadedKextSummary& info);
404
405 OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used
Greg Clayton0d9fc762011-07-08 03:21:57 +0000406 lldb_private::Address m_kext_summary_header_addr;
Greg Clayton7b242382011-07-08 00:48:09 +0000407 OSKextLoadedKextSummaryHeader m_kext_summary_header;
408 uint32_t m_kext_summary_header_stop_id; // The process stop ID that "m_kext_summary_header" is valid for
409 lldb::user_id_t m_break_id;
410 OSKextLoadedKextSummary::collection m_kext_summaries;
411 uint32_t m_kext_summaries_stop_id; // The process stop ID that "m_kext_summaries" is valid for
412 mutable lldb_private::Mutex m_mutex;
413 lldb_private::Process::Notifications m_notification_callbacks;
414
415private:
416 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXKernel);
417};
418
419#endif // liblldb_DynamicLoaderMacOSXKernel_h_