blob: 7dbd98db2ab1b5fc86f7439618eebd13d06c7102 [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
151 bool
152 ReadMachHeader (lldb::addr_t addr,
153 llvm::MachO::mach_header *header,
154 lldb_private::DataExtractor *load_command_data);
155 class Segment
156 {
157 public:
158
159 Segment() :
160 name(),
161 vmaddr(LLDB_INVALID_ADDRESS),
162 vmsize(0),
163 fileoff(0),
164 filesize(0),
165 maxprot(0),
166 initprot(0),
167 nsects(0),
168 flags(0)
169 {
170 }
171
172 lldb_private::ConstString name;
173 lldb::addr_t vmaddr;
174 lldb::addr_t vmsize;
175 lldb::addr_t fileoff;
176 lldb::addr_t filesize;
177 uint32_t maxprot;
178 uint32_t initprot;
179 uint32_t nsects;
180 uint32_t flags;
181
182 bool
183 operator==(const Segment& rhs) const
184 {
185 return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
186 }
187
188 void
189 PutToLog (lldb_private::Log *log,
190 lldb::addr_t slide) const;
191
192 };
193
194 enum { KERNEL_MODULE_MAX_NAME = 64u };
195
196 struct OSKextLoadedKextSummary
197 {
198 char name[KERNEL_MODULE_MAX_NAME];
199 lldb::ModuleSP module_sp;
200 lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
201 uint64_t address;
202 uint64_t size;
203 uint64_t version;
204 uint32_t load_tag;
205 uint32_t flags;
206 uint64_t reference_list;
207 llvm::MachO::mach_header header; // The mach header for this image
208 std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
209
210 OSKextLoadedKextSummary() :
211 module_sp (),
212 uuid (),
213 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 {
230 address = LLDB_INVALID_ADDRESS;
231 size = 0;
232 version = 0;
233 load_tag = 0;
234 flags = 0;
235 reference_list = 0;
236 name[0] = '\0';
237 ::memset (&header, 0, sizeof(header));
238 }
239 module_sp.reset();
240 uuid.Clear();
241 segments.clear();
242 }
243
244 bool
245 operator == (const OSKextLoadedKextSummary& rhs) const
246 {
247 return address == rhs.address
248 && size == rhs.size
249 //&& module_sp.get() == rhs.module_sp.get()
250 && uuid == rhs.uuid
251 && version == rhs.version
252 && load_tag == rhs.load_tag
253 && flags == rhs.flags
254 && reference_list == rhs.reference_list
255 && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0
256 && memcmp(&header, &rhs.header, sizeof(header)) == 0
257 && segments == rhs.segments;
258 }
259
260 bool
261 UUIDValid() const
262 {
263 return uuid.IsValid();
264 }
265
266 uint32_t
267 GetAddressByteSize ()
268 {
269 if (header.cputype)
270 {
271 if (header.cputype & llvm::MachO::CPUArchABI64)
272 return 8;
273 else
274 return 4;
275 }
276 return 0;
277 }
278
279 lldb::ByteOrder
280 GetByteOrder()
281 {
282 switch (header.magic)
283 {
284 case llvm::MachO::HeaderMagic32: // MH_MAGIC
285 case llvm::MachO::HeaderMagic64: // MH_MAGIC_64
286 return lldb::endian::InlHostByteOrder();
287
288 case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
289 case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
290 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle)
291 return lldb::eByteOrderBig;
292 else
293 return lldb::eByteOrderLittle;
294 default:
295 assert (!"invalid header.magic value");
296 break;
297 }
298 return lldb::endian::InlHostByteOrder();
299 }
300
301 lldb_private::ArchSpec
302 GetArchitecture () const
303 {
304 return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
305 }
306
307 const Segment *
308 FindSegment (const lldb_private::ConstString &name) const;
309
310 void
311 PutToLog (lldb_private::Log *log) const;
312
313 typedef std::vector<OSKextLoadedKextSummary> collection;
314 typedef collection::iterator iterator;
315 typedef collection::const_iterator const_iterator;
316 };
317
318 struct OSKextLoadedKextSummaryHeader
319 {
320 uint32_t version;
321 uint32_t entry_size;
322 uint32_t entry_count;
323 uint32_t reserved; /* explicit alignment for gdb */
324 lldb::addr_t image_infos_addr;
325
326 OSKextLoadedKextSummaryHeader() :
327 version (0),
328 entry_size (0),
329 entry_count (0),
330 reserved (0),
331 image_infos_addr (LLDB_INVALID_ADDRESS)
332 {
333 }
334
335 void
336 Clear()
337 {
338 version = 0;
339 entry_size = 0;
340 entry_count = 0;
341 reserved = 0;
342 image_infos_addr = LLDB_INVALID_ADDRESS;
343 }
344
345 bool
346 IsValid() const
347 {
348 return version >= 1 || version <= 2;
349 }
350 };
351
352 void
353 RegisterNotificationCallbacks();
354
355 void
356 UnregisterNotificationCallbacks();
357
358 uint32_t
359 ParseLoadCommands (const lldb_private::DataExtractor& data,
360 OSKextLoadedKextSummary& dylib_info);
361
362 bool
363 UpdateImageLoadAddress(OSKextLoadedKextSummary& info);
364
365 bool
366 FindTargetModule (OSKextLoadedKextSummary &image_info,
367 bool can_create,
368 bool *did_create_ptr);
369
370 bool
371 SetNotificationBreakpoint ();
372
373 bool
374 ReadAllKextSummaries (bool force);
375
376 bool
377 ReadKextSummaryHeader ();
378
379 bool
380 ParseKextSummaries (lldb::addr_t kext_summary_addr, uint32_t count);
381
382 bool
383 AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos);
384
385 bool
386 RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
387
388 void
389 UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos,
390 uint32_t infos_count,
391 bool update_executable);
392
393 bool
394 UpdateCommPageLoadAddress (lldb_private::Module *module);
395
396 uint32_t
397 ReadKextSummaries (lldb::addr_t image_infos_addr,
398 uint32_t image_infos_count,
399 OSKextLoadedKextSummary::collection &image_infos);
400
401 bool
402 UnloadImageLoadAddress (OSKextLoadedKextSummary& info);
403
404 OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used
405 lldb::addr_t m_kext_summary_header_addr;
406 OSKextLoadedKextSummaryHeader m_kext_summary_header;
407 uint32_t m_kext_summary_header_stop_id; // The process stop ID that "m_kext_summary_header" is valid for
408 lldb::user_id_t m_break_id;
409 OSKextLoadedKextSummary::collection m_kext_summaries;
410 uint32_t m_kext_summaries_stop_id; // The process stop ID that "m_kext_summaries" is valid for
411 mutable lldb_private::Mutex m_mutex;
412 lldb_private::Process::Notifications m_notification_callbacks;
413
414private:
415 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXKernel);
416};
417
418#endif // liblldb_DynamicLoaderMacOSXKernel_h_