blob: 50004ce27157aa49b2b06e09143492378e9826e4 [file] [log] [blame]
Greg Clayton7b242382011-07-08 00:48:09 +00001//===-- DynamicLoaderMacOSXKernel.cpp -----------------------------*- 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#include "lldb/Breakpoint/StoppointCallbackContext.h"
11#include "lldb/Core/DataBuffer.h"
12#include "lldb/Core/DataBufferHeap.h"
13#include "lldb/Core/Log.h"
14#include "lldb/Core/Module.h"
15#include "lldb/Core/PluginManager.h"
16#include "lldb/Core/State.h"
17#include "lldb/Symbol/ObjectFile.h"
18#include "lldb/Target/ObjCLanguageRuntime.h"
19#include "lldb/Target/RegisterContext.h"
20#include "lldb/Target/Target.h"
21#include "lldb/Target/Thread.h"
22#include "lldb/Target/ThreadPlanRunToAddress.h"
23#include "lldb/Target/StackFrame.h"
24
25#include "DynamicLoaderMacOSXKernel.h"
26
27//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
28#ifdef ENABLE_DEBUG_PRINTF
29#include <stdio.h>
30#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
31#else
32#define DEBUG_PRINTF(fmt, ...)
33#endif
34
35using namespace lldb;
36using namespace lldb_private;
37
38/// FIXME - The ObjC Runtime trampoline handler doesn't really belong here.
39/// I am putting it here so I can invoke it in the Trampoline code here, but
40/// it should be moved to the ObjC Runtime support when it is set up.
41
42
43//----------------------------------------------------------------------
44// Create an instance of this class. This function is filled into
45// the plugin info class that gets handed out by the plugin factory and
46// allows the lldb to instantiate an instance of this class.
47//----------------------------------------------------------------------
48DynamicLoader *
49DynamicLoaderMacOSXKernel::CreateInstance (Process* process, bool force)
50{
51 bool create = force;
52 if (!create)
53 {
Greg Claytondf0b7d52011-07-08 04:11:42 +000054 Module* exe_module = process->GetTarget().GetExecutableModule().get();
55 if (exe_module)
56 {
57 ObjectFile *object_file = exe_module->GetObjectFile();
58 if (object_file)
59 {
60 SectionList *section_list = object_file->GetSectionList();
61 if (section_list)
62 {
63 static ConstString g_kld_section_name ("__KLD");
64 if (section_list->FindSectionByName (g_kld_section_name))
65 {
66 create = true;
67 }
68 }
69 }
70 }
71
72 if (create)
73 {
74 const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
75 create = triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple;
76 }
Greg Clayton7b242382011-07-08 00:48:09 +000077 }
78
79 if (create)
80 return new DynamicLoaderMacOSXKernel (process);
81 return NULL;
82}
83
84//----------------------------------------------------------------------
85// Constructor
86//----------------------------------------------------------------------
87DynamicLoaderMacOSXKernel::DynamicLoaderMacOSXKernel (Process* process) :
88 DynamicLoader(process),
89 m_kernel(),
Greg Clayton0d9fc762011-07-08 03:21:57 +000090 m_kext_summary_header_addr (),
Greg Clayton7b242382011-07-08 00:48:09 +000091 m_kext_summary_header (),
Greg Clayton7b242382011-07-08 00:48:09 +000092 m_break_id (LLDB_INVALID_BREAK_ID),
93 m_kext_summaries(),
Greg Clayton374972e2011-07-09 17:15:55 +000094 m_mutex(Mutex::eMutexTypeRecursive)
Greg Clayton7b242382011-07-08 00:48:09 +000095{
96}
97
98//----------------------------------------------------------------------
99// Destructor
100//----------------------------------------------------------------------
101DynamicLoaderMacOSXKernel::~DynamicLoaderMacOSXKernel()
102{
103 Clear(true);
104}
105
Greg Clayton374972e2011-07-09 17:15:55 +0000106void
107DynamicLoaderMacOSXKernel::UpdateIfNeeded()
108{
109 LoadKernelModuleIfNeeded();
110 SetNotificationBreakpointIfNeeded ();
111}
Greg Clayton7b242382011-07-08 00:48:09 +0000112//------------------------------------------------------------------
113/// Called after attaching a process.
114///
115/// Allow DynamicLoader plug-ins to execute some code after
116/// attaching to a process.
117//------------------------------------------------------------------
118void
119DynamicLoaderMacOSXKernel::DidAttach ()
120{
121 PrivateInitialize(m_process);
Greg Clayton374972e2011-07-09 17:15:55 +0000122 UpdateIfNeeded();
Greg Clayton7b242382011-07-08 00:48:09 +0000123}
124
125//------------------------------------------------------------------
126/// Called after attaching a process.
127///
128/// Allow DynamicLoader plug-ins to execute some code after
129/// attaching to a process.
130//------------------------------------------------------------------
131void
132DynamicLoaderMacOSXKernel::DidLaunch ()
133{
134 PrivateInitialize(m_process);
Greg Clayton374972e2011-07-09 17:15:55 +0000135 UpdateIfNeeded();
Greg Clayton7b242382011-07-08 00:48:09 +0000136}
137
138
139//----------------------------------------------------------------------
140// Clear out the state of this class.
141//----------------------------------------------------------------------
142void
143DynamicLoaderMacOSXKernel::Clear (bool clear_process)
144{
145 Mutex::Locker locker(m_mutex);
146
147 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
148 m_process->ClearBreakpointSiteByID(m_break_id);
149
150 if (clear_process)
151 m_process = NULL;
152 m_kernel.Clear(false);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000153 m_kext_summary_header_addr.Clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000154 m_kext_summaries.clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000155 m_break_id = LLDB_INVALID_BREAK_ID;
156}
157
Greg Clayton7b242382011-07-08 00:48:09 +0000158
159//----------------------------------------------------------------------
160// Load the kernel module and initialize the "m_kernel" member. Return
161// true _only_ if the kernel is loaded the first time through (subsequent
162// calls to this function should return false after the kernel has been
163// already loaded).
164//----------------------------------------------------------------------
Greg Clayton374972e2011-07-09 17:15:55 +0000165void
166DynamicLoaderMacOSXKernel::LoadKernelModuleIfNeeded()
Greg Clayton7b242382011-07-08 00:48:09 +0000167{
Greg Clayton0d9fc762011-07-08 03:21:57 +0000168 if (!m_kext_summary_header_addr.IsValid())
Greg Clayton7b242382011-07-08 00:48:09 +0000169 {
170 m_kernel.Clear(false);
171 m_kernel.module_sp = m_process->GetTarget().GetExecutableModule();
172 if (m_kernel.module_sp)
173 {
174 static ConstString mach_header_name ("_mh_execute_header");
Greg Claytondf0b7d52011-07-08 04:11:42 +0000175 static ConstString kext_summary_symbol ("gLoadedKextSummaries");
176 const Symbol *symbol = NULL;
177 symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData);
178 if (symbol)
179 m_kext_summary_header_addr = symbol->GetValue();
180
181 symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute);
Greg Clayton7b242382011-07-08 00:48:09 +0000182 if (symbol)
183 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000184 // The "_mh_execute_header" symbol is absolute and not a section based
185 // symbol that will have a valid address, so we need to resolve it...
186 m_process->GetTarget().GetImages().ResolveFileAddress (symbol->GetValue().GetFileAddress(), m_kernel.so_address);
Greg Clayton7b242382011-07-08 00:48:09 +0000187 DataExtractor data; // Load command data
Greg Clayton0d9fc762011-07-08 03:21:57 +0000188 if (ReadMachHeader (m_kernel, &data))
Greg Clayton7b242382011-07-08 00:48:09 +0000189 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000190 if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeExecutable)
Greg Clayton7b242382011-07-08 00:48:09 +0000191 {
192 if (ParseLoadCommands (data, m_kernel))
193 UpdateImageLoadAddress (m_kernel);
194
195 // Update all image infos
Greg Clayton374972e2011-07-09 17:15:55 +0000196 ReadAllKextSummaries ();
Greg Clayton7b242382011-07-08 00:48:09 +0000197 }
198 }
199 else
200 {
201 m_kernel.Clear(false);
202 }
Greg Clayton7b242382011-07-08 00:48:09 +0000203 }
204 }
205 }
Greg Clayton7b242382011-07-08 00:48:09 +0000206}
207
208bool
209DynamicLoaderMacOSXKernel::FindTargetModule (OSKextLoadedKextSummary &image_info, bool can_create, bool *did_create_ptr)
210{
211 if (did_create_ptr)
212 *did_create_ptr = false;
213
214 const bool image_info_uuid_is_valid = image_info.uuid.IsValid();
215
216 if (image_info.module_sp)
217 {
218 if (image_info_uuid_is_valid)
219 {
220 if (image_info.module_sp->GetUUID() == image_info.uuid)
221 return true;
222 else
223 image_info.module_sp.reset();
224 }
225 else
226 return true;
227 }
228
229 ModuleList &target_images = m_process->GetTarget().GetImages();
230 if (image_info_uuid_is_valid)
231 image_info.module_sp = target_images.FindModule(image_info.uuid);
232
233 if (image_info.module_sp)
234 return true;
235
236 ArchSpec arch (image_info.GetArchitecture ());
237 if (can_create)
238 {
239 if (image_info_uuid_is_valid)
240 {
241 image_info.module_sp = m_process->GetTarget().GetSharedModule (FileSpec(),
242 arch,
243 &image_info.uuid);
244 if (did_create_ptr)
245 *did_create_ptr = image_info.module_sp;
246 }
247 }
248 return image_info.module_sp;
249}
250
251bool
252DynamicLoaderMacOSXKernel::UpdateCommPageLoadAddress(Module *module)
253{
254 bool changed = false;
255 if (module)
256 {
257 ObjectFile *image_object_file = module->GetObjectFile();
258 if (image_object_file)
259 {
260 SectionList *section_list = image_object_file->GetSectionList ();
261 if (section_list)
262 {
263 uint32_t num_sections = section_list->GetSize();
264 for (uint32_t i=0; i<num_sections; ++i)
265 {
266 Section* section = section_list->GetSectionAtIndex (i).get();
267 if (section)
268 {
269 const addr_t new_section_load_addr = section->GetFileAddress ();
270 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section);
271 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
272 old_section_load_addr != new_section_load_addr)
273 {
274 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ()))
275 changed = true;
276 }
277 }
278 }
279 }
280 }
281 }
282 return changed;
283}
284
285//----------------------------------------------------------------------
286// Update the load addresses for all segments in MODULE using the
287// updated INFO that is passed in.
288//----------------------------------------------------------------------
289bool
290DynamicLoaderMacOSXKernel::UpdateImageLoadAddress (OSKextLoadedKextSummary& info)
291{
292 Module *module = info.module_sp.get();
293 bool changed = false;
294 if (module)
295 {
296 ObjectFile *image_object_file = module->GetObjectFile();
297 if (image_object_file)
298 {
299 SectionList *section_list = image_object_file->GetSectionList ();
300 if (section_list)
301 {
302 // We now know the slide amount, so go through all sections
303 // and update the load addresses with the correct values.
304 uint32_t num_segments = info.segments.size();
305 for (uint32_t i=0; i<num_segments; ++i)
306 {
307 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
308 const addr_t new_section_load_addr = info.segments[i].vmaddr;
309 if (section_sp)
310 {
311 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
312 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
313 old_section_load_addr != new_section_load_addr)
314 {
315 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
316 changed = true;
317 }
318 }
319 else
320 {
321 fprintf (stderr,
322 "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
323 info.segments[i].name.AsCString("<invalid>"),
324 (uint64_t)new_section_load_addr,
325 image_object_file->GetFileSpec().GetDirectory().AsCString(),
326 image_object_file->GetFileSpec().GetFilename().AsCString());
327 }
328 }
329 }
330 }
331 }
332 return changed;
333}
334
335//----------------------------------------------------------------------
336// Update the load addresses for all segments in MODULE using the
337// updated INFO that is passed in.
338//----------------------------------------------------------------------
339bool
340DynamicLoaderMacOSXKernel::UnloadImageLoadAddress (OSKextLoadedKextSummary& info)
341{
342 Module *module = info.module_sp.get();
343 bool changed = false;
344 if (module)
345 {
346 ObjectFile *image_object_file = module->GetObjectFile();
347 if (image_object_file)
348 {
349 SectionList *section_list = image_object_file->GetSectionList ();
350 if (section_list)
351 {
352 uint32_t num_segments = info.segments.size();
353 for (uint32_t i=0; i<num_segments; ++i)
354 {
355 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
356 if (section_sp)
357 {
358 const addr_t old_section_load_addr = info.segments[i].vmaddr;
359 if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
360 changed = true;
361 }
362 else
363 {
364 fprintf (stderr,
365 "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n",
366 info.segments[i].name.AsCString("<invalid>"),
367 image_object_file->GetFileSpec().GetDirectory().AsCString(),
368 image_object_file->GetFileSpec().GetFilename().AsCString());
369 }
370 }
371 }
372 }
373 }
374 return changed;
375}
376
377
378//----------------------------------------------------------------------
379// Static callback function that gets called when our DYLD notification
380// breakpoint gets hit. We update all of our image infos and then
381// let our super class DynamicLoader class decide if we should stop
382// or not (based on global preference).
383//----------------------------------------------------------------------
384bool
Greg Clayton374972e2011-07-09 17:15:55 +0000385DynamicLoaderMacOSXKernel::BreakpointHitCallback (void *baton,
386 StoppointCallbackContext *context,
387 user_id_t break_id,
388 user_id_t break_loc_id)
Greg Clayton0d9fc762011-07-08 03:21:57 +0000389{
Greg Clayton374972e2011-07-09 17:15:55 +0000390 return static_cast<DynamicLoaderMacOSXKernel*>(baton)->BreakpointHit (context, break_id, break_loc_id);
Greg Clayton7b242382011-07-08 00:48:09 +0000391}
392
393bool
Greg Clayton374972e2011-07-09 17:15:55 +0000394DynamicLoaderMacOSXKernel::BreakpointHit (StoppointCallbackContext *context,
395 user_id_t break_id,
396 user_id_t break_loc_id)
397{
398 ReadAllKextSummaries ();
399 return GetStopWhenImagesChange();
400}
401
402
403bool
Greg Clayton7b242382011-07-08 00:48:09 +0000404DynamicLoaderMacOSXKernel::ReadKextSummaryHeader ()
405{
406 Mutex::Locker locker(m_mutex);
407
408 // the all image infos is already valid for this process stop ID
Greg Clayton7b242382011-07-08 00:48:09 +0000409
410 m_kext_summaries.clear();
Greg Clayton0d9fc762011-07-08 03:21:57 +0000411 if (m_kext_summary_header_addr.IsValid())
Greg Clayton7b242382011-07-08 00:48:09 +0000412 {
413 const uint32_t addr_size = m_kernel.GetAddressByteSize ();
414 const ByteOrder byte_order = m_kernel.GetByteOrder();
415 Error error;
416 // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure
417 // which is currenty 4 uint32_t and a pointer.
418 uint8_t buf[24];
419 DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
420 const size_t count = 4 * sizeof(uint32_t) + addr_size;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000421 const bool prefer_file_cache = false;
422 const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error);
Greg Clayton7b242382011-07-08 00:48:09 +0000423 if (bytes_read == count)
424 {
425 uint32_t offset = 0;
426 m_kext_summary_header.version = data.GetU32(&offset);
427 m_kext_summary_header.entry_size = data.GetU32(&offset);
428 m_kext_summary_header.entry_count = data.GetU32(&offset);
429 m_kext_summary_header.reserved = data.GetU32(&offset);
Greg Clayton7b242382011-07-08 00:48:09 +0000430 return true;
431 }
432 }
433 return false;
434}
435
436
437bool
Greg Clayton374972e2011-07-09 17:15:55 +0000438DynamicLoaderMacOSXKernel::ParseKextSummaries (const Address &kext_summary_addr,
Greg Clayton0d9fc762011-07-08 03:21:57 +0000439 uint32_t count)
Greg Clayton7b242382011-07-08 00:48:09 +0000440{
441 OSKextLoadedKextSummary::collection kext_summaries;
Greg Clayton374972e2011-07-09 17:15:55 +0000442 LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
Greg Clayton7b242382011-07-08 00:48:09 +0000443 if (log)
444 log->Printf ("Adding %d modules.\n");
445
446 Mutex::Locker locker(m_mutex);
Greg Clayton7b242382011-07-08 00:48:09 +0000447
448 if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
449 return false;
450
451 for (uint32_t i = 0; i < count; i++)
452 {
453 if (!kext_summaries[i].UUIDValid())
454 {
455 DataExtractor data; // Load command data
Greg Clayton0d9fc762011-07-08 03:21:57 +0000456 if (!ReadMachHeader (kext_summaries[i], &data))
Greg Clayton7b242382011-07-08 00:48:09 +0000457 continue;
458
459 ParseLoadCommands (data, kext_summaries[i]);
460 }
461 }
462 bool return_value = AddModulesUsingImageInfos (kext_summaries);
Greg Clayton7b242382011-07-08 00:48:09 +0000463 return return_value;
464}
465
466// Adds the modules in image_infos to m_kext_summaries.
467// NB don't call this passing in m_kext_summaries.
468
469bool
470DynamicLoaderMacOSXKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos)
471{
472 // Now add these images to the main list.
473 ModuleList loaded_module_list;
Greg Clayton374972e2011-07-09 17:15:55 +0000474 LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
Greg Clayton7b242382011-07-08 00:48:09 +0000475
476 for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
477 {
478 if (log)
479 {
480 log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address);
481 image_infos[idx].PutToLog (log.get());
482 }
483
484 m_kext_summaries.push_back(image_infos[idx]);
485
486 if (FindTargetModule (image_infos[idx], true, NULL))
487 {
488 // UpdateImageLoadAddress will return true if any segments
489 // change load address. We need to check this so we don't
490 // mention that all loaded shared libraries are newly loaded
491 // each time we hit out dyld breakpoint since dyld will list all
492 // shared libraries each time.
493 if (UpdateImageLoadAddress (image_infos[idx]))
494 {
495 loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
496 }
497 }
498 }
499
500 if (loaded_module_list.GetSize() > 0)
501 {
502 // FIXME: This should really be in the Runtime handlers class, which should get
503 // called by the target's ModulesDidLoad, but we're doing it all locally for now
504 // to save time.
505 // Also, I'm assuming there can be only one libobjc dylib loaded...
506
507 ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
508 if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
509 {
510 size_t num_modules = loaded_module_list.GetSize();
511 for (int i = 0; i < num_modules; i++)
512 {
513 if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
514 {
515 objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
516 break;
517 }
518 }
519 }
520 if (log)
521 loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidLoad");
522 m_process->GetTarget().ModulesDidLoad (loaded_module_list);
523 }
524 return true;
525}
526
Greg Clayton7b242382011-07-08 00:48:09 +0000527
528uint32_t
Greg Clayton374972e2011-07-09 17:15:55 +0000529DynamicLoaderMacOSXKernel::ReadKextSummaries (const Address &kext_summary_addr,
Greg Clayton7b242382011-07-08 00:48:09 +0000530 uint32_t image_infos_count,
531 OSKextLoadedKextSummary::collection &image_infos)
532{
533 const ByteOrder endian = m_kernel.GetByteOrder();
534 const uint32_t addr_size = m_kernel.GetAddressByteSize();
535
536 image_infos.resize(image_infos_count);
537 const size_t count = image_infos.size() * m_kext_summary_header.entry_size;
538 DataBufferHeap data(count, 0);
539 Error error;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000540 const bool prefer_file_cache = false;
541 const size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary_addr,
542 prefer_file_cache,
543 data.GetBytes(),
544 data.GetByteSize(),
545 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000546 if (bytes_read == count)
547 {
548 uint32_t offset = 0;
549 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size);
550 uint32_t i=0;
551 for (; i < image_infos.size() && extractor.ValidOffsetForDataOfSize(offset, m_kext_summary_header.entry_size); ++i)
552 {
553 const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
554 if (name_data == NULL)
555 break;
556 memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME);
557 image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16));
558 image_infos[i].address = extractor.GetU64(&offset);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000559 if (!image_infos[i].so_address.SetLoadAddress (image_infos[i].address, &m_process->GetTarget()))
560 m_process->GetTarget().GetImages().ResolveFileAddress (image_infos[i].address, image_infos[i].so_address);
Greg Clayton7b242382011-07-08 00:48:09 +0000561 image_infos[i].size = extractor.GetU64(&offset);
562 image_infos[i].version = extractor.GetU64(&offset);
563 image_infos[i].load_tag = extractor.GetU32(&offset);
564 image_infos[i].flags = extractor.GetU32(&offset);
565 image_infos[i].reference_list = extractor.GetU64(&offset);
566 }
567 if (i < image_infos.size())
568 image_infos.resize(i);
569 }
570 else
571 {
572 image_infos.clear();
573 }
574 return image_infos.size();
575}
576
577bool
Greg Clayton374972e2011-07-09 17:15:55 +0000578DynamicLoaderMacOSXKernel::ReadAllKextSummaries ()
Greg Clayton7b242382011-07-08 00:48:09 +0000579{
Greg Clayton374972e2011-07-09 17:15:55 +0000580 LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
Greg Clayton7b242382011-07-08 00:48:09 +0000581
582 Mutex::Locker locker(m_mutex);
Greg Clayton374972e2011-07-09 17:15:55 +0000583
Greg Clayton7b242382011-07-08 00:48:09 +0000584 if (ReadKextSummaryHeader ())
585 {
Greg Clayton374972e2011-07-09 17:15:55 +0000586 if (m_kext_summary_header.entry_count > 0 && m_kext_summary_header_addr.IsValid())
Greg Clayton7b242382011-07-08 00:48:09 +0000587 {
Greg Clayton0d9fc762011-07-08 03:21:57 +0000588 Address summary_addr (m_kext_summary_header_addr);
589 summary_addr.Slide(16);
590 if (!ParseKextSummaries (summary_addr, m_kext_summary_header.entry_count))
Greg Clayton7b242382011-07-08 00:48:09 +0000591 {
Greg Clayton7b242382011-07-08 00:48:09 +0000592 m_kext_summaries.clear();
593 }
594 return true;
595 }
596 }
597 return false;
598}
599
600//----------------------------------------------------------------------
601// Read a mach_header at ADDR into HEADER, and also fill in the load
602// command data into LOAD_COMMAND_DATA if it is non-NULL.
603//
604// Returns true if we succeed, false if we fail for any reason.
605//----------------------------------------------------------------------
606bool
Greg Clayton0d9fc762011-07-08 03:21:57 +0000607DynamicLoaderMacOSXKernel::ReadMachHeader (OSKextLoadedKextSummary& kext_summary, DataExtractor *load_command_data)
Greg Clayton7b242382011-07-08 00:48:09 +0000608{
609 DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
610 Error error;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000611 const bool prefer_file_cache = false;
612 size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary.so_address,
613 prefer_file_cache,
614 header_bytes.GetBytes(),
615 header_bytes.GetByteSize(),
616 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000617 if (bytes_read == sizeof(llvm::MachO::mach_header))
618 {
619 uint32_t offset = 0;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000620 ::memset (&kext_summary.header, 0, sizeof(kext_summary.header));
Greg Clayton7b242382011-07-08 00:48:09 +0000621
622 // Get the magic byte unswapped so we can figure out what we are dealing with
Greg Clayton374972e2011-07-09 17:15:55 +0000623 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), endian::InlHostByteOrder(), 4);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000624 kext_summary.header.magic = data.GetU32(&offset);
625 Address load_cmd_addr = kext_summary.so_address;
626 data.SetByteOrder(DynamicLoaderMacOSXKernel::GetByteOrderFromMagic(kext_summary.header.magic));
627 switch (kext_summary.header.magic)
Greg Clayton7b242382011-07-08 00:48:09 +0000628 {
629 case llvm::MachO::HeaderMagic32:
630 case llvm::MachO::HeaderMagic32Swapped:
631 data.SetAddressByteSize(4);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000632 load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header));
Greg Clayton7b242382011-07-08 00:48:09 +0000633 break;
634
635 case llvm::MachO::HeaderMagic64:
636 case llvm::MachO::HeaderMagic64Swapped:
637 data.SetAddressByteSize(8);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000638 load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header_64));
Greg Clayton7b242382011-07-08 00:48:09 +0000639 break;
640
641 default:
642 return false;
643 }
644
645 // Read the rest of dyld's mach header
Greg Clayton0d9fc762011-07-08 03:21:57 +0000646 if (data.GetU32(&offset, &kext_summary.header.cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
Greg Clayton7b242382011-07-08 00:48:09 +0000647 {
648 if (load_command_data == NULL)
649 return true; // We were able to read the mach_header and weren't asked to read the load command bytes
650
Greg Clayton0d9fc762011-07-08 03:21:57 +0000651 DataBufferSP load_cmd_data_sp(new DataBufferHeap(kext_summary.header.sizeofcmds, 0));
Greg Clayton7b242382011-07-08 00:48:09 +0000652
Greg Clayton0d9fc762011-07-08 03:21:57 +0000653 size_t load_cmd_bytes_read = m_process->GetTarget().ReadMemory (load_cmd_addr,
654 prefer_file_cache,
655 load_cmd_data_sp->GetBytes(),
656 load_cmd_data_sp->GetByteSize(),
657 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000658
Greg Clayton0d9fc762011-07-08 03:21:57 +0000659 if (load_cmd_bytes_read == kext_summary.header.sizeofcmds)
Greg Clayton7b242382011-07-08 00:48:09 +0000660 {
661 // Set the load command data and also set the correct endian
662 // swap settings and the correct address size
Greg Clayton0d9fc762011-07-08 03:21:57 +0000663 load_command_data->SetData(load_cmd_data_sp, 0, kext_summary.header.sizeofcmds);
Greg Clayton7b242382011-07-08 00:48:09 +0000664 load_command_data->SetByteOrder(data.GetByteOrder());
665 load_command_data->SetAddressByteSize(data.GetAddressByteSize());
666 return true; // We successfully read the mach_header and the load command data
667 }
668
669 return false; // We weren't able to read the load command data
670 }
671 }
672 return false; // We failed the read the mach_header
673}
674
675
676//----------------------------------------------------------------------
677// Parse the load commands for an image
678//----------------------------------------------------------------------
679uint32_t
Greg Claytondf0b7d52011-07-08 04:11:42 +0000680DynamicLoaderMacOSXKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& image_info)
Greg Clayton7b242382011-07-08 00:48:09 +0000681{
682 uint32_t offset = 0;
683 uint32_t cmd_idx;
684 Segment segment;
Greg Claytondf0b7d52011-07-08 04:11:42 +0000685 image_info.Clear (true);
Greg Clayton7b242382011-07-08 00:48:09 +0000686
Greg Claytondf0b7d52011-07-08 04:11:42 +0000687 for (cmd_idx = 0; cmd_idx < image_info.header.ncmds; cmd_idx++)
Greg Clayton7b242382011-07-08 00:48:09 +0000688 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000689 // Clear out any load command specific data from image_info since
Greg Clayton7b242382011-07-08 00:48:09 +0000690 // we are about to read it.
691
692 if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
693 {
694 llvm::MachO::load_command load_cmd;
695 uint32_t load_cmd_offset = offset;
696 load_cmd.cmd = data.GetU32 (&offset);
697 load_cmd.cmdsize = data.GetU32 (&offset);
698 switch (load_cmd.cmd)
699 {
700 case llvm::MachO::LoadCommandSegment32:
701 {
702 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
703 // We are putting 4 uint32_t values 4 uint64_t values so
704 // we have to use multiple 32 bit gets below.
705 segment.vmaddr = data.GetU32 (&offset);
706 segment.vmsize = data.GetU32 (&offset);
707 segment.fileoff = data.GetU32 (&offset);
708 segment.filesize = data.GetU32 (&offset);
709 // Extract maxprot, initprot, nsects and flags all at once
710 data.GetU32(&offset, &segment.maxprot, 4);
Greg Claytondf0b7d52011-07-08 04:11:42 +0000711 image_info.segments.push_back (segment);
Greg Clayton7b242382011-07-08 00:48:09 +0000712 }
713 break;
714
715 case llvm::MachO::LoadCommandSegment64:
716 {
717 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
718 // Extract vmaddr, vmsize, fileoff, and filesize all at once
719 data.GetU64(&offset, &segment.vmaddr, 4);
720 // Extract maxprot, initprot, nsects and flags all at once
721 data.GetU32(&offset, &segment.maxprot, 4);
Greg Claytondf0b7d52011-07-08 04:11:42 +0000722 image_info.segments.push_back (segment);
Greg Clayton7b242382011-07-08 00:48:09 +0000723 }
724 break;
725
726 case llvm::MachO::LoadCommandUUID:
Greg Claytondf0b7d52011-07-08 04:11:42 +0000727 image_info.uuid.SetBytes(data.GetData (&offset, 16));
Greg Clayton7b242382011-07-08 00:48:09 +0000728 break;
729
730 default:
731 break;
732 }
733 // Set offset to be the beginning of the next load command.
734 offset = load_cmd_offset + load_cmd.cmdsize;
735 }
736 }
737#if 0
738 // No slide in the kernel...
739
740 // All sections listed in the dyld image info structure will all
741 // either be fixed up already, or they will all be off by a single
742 // slide amount that is determined by finding the first segment
743 // that is at file offset zero which also has bytes (a file size
744 // that is greater than zero) in the object file.
745
746 // Determine the slide amount (if any)
Greg Claytondf0b7d52011-07-08 04:11:42 +0000747 const size_t num_sections = image_info.segments.size();
Greg Clayton7b242382011-07-08 00:48:09 +0000748 for (size_t i = 0; i < num_sections; ++i)
749 {
750 // Iterate through the object file sections to find the
751 // first section that starts of file offset zero and that
752 // has bytes in the file...
Greg Claytondf0b7d52011-07-08 04:11:42 +0000753 if (image_info.segments[i].fileoff == 0 && image_info.segments[i].filesize > 0)
Greg Clayton7b242382011-07-08 00:48:09 +0000754 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000755 image_info.slide = image_info.address - image_info.segments[i].vmaddr;
Greg Clayton7b242382011-07-08 00:48:09 +0000756 // We have found the slide amount, so we can exit
757 // this for loop.
758 break;
759 }
760 }
761#endif
Greg Claytondf0b7d52011-07-08 04:11:42 +0000762 if (image_info.uuid.IsValid())
763 {
764 bool did_create = false;
765 if (FindTargetModule(image_info, true, &did_create))
766 {
767 if (did_create)
768 image_info.module_create_stop_id = m_process->GetStopID();
769 }
770 }
Greg Clayton7b242382011-07-08 00:48:09 +0000771 return cmd_idx;
772}
773
774//----------------------------------------------------------------------
775// Dump a Segment to the file handle provided.
776//----------------------------------------------------------------------
777void
Greg Clayton374972e2011-07-09 17:15:55 +0000778DynamicLoaderMacOSXKernel::Segment::PutToLog (Log *log, addr_t slide) const
Greg Clayton7b242382011-07-08 00:48:09 +0000779{
780 if (log)
781 {
782 if (slide == 0)
783 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)",
784 name.AsCString(""),
785 vmaddr + slide,
786 vmaddr + slide + vmsize);
787 else
788 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx",
789 name.AsCString(""),
790 vmaddr + slide,
791 vmaddr + slide + vmsize,
792 slide);
793 }
794}
795
796const DynamicLoaderMacOSXKernel::Segment *
797DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::FindSegment (const ConstString &name) const
798{
799 const size_t num_segments = segments.size();
800 for (size_t i=0; i<num_segments; ++i)
801 {
802 if (segments[i].name == name)
803 return &segments[i];
804 }
805 return NULL;
806}
807
808
809//----------------------------------------------------------------------
810// Dump an image info structure to the file handle provided.
811//----------------------------------------------------------------------
812void
813DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
814{
815 if (log == NULL)
816 return;
817 uint8_t *u = (uint8_t *)uuid.GetBytes();
Greg Clayton7b242382011-07-08 00:48:09 +0000818
819 if (address == LLDB_INVALID_ADDRESS)
820 {
821 if (u)
822 {
823 log->Printf("\t uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name='%s' (UNLOADED)",
824 u[ 0], u[ 1], u[ 2], u[ 3],
825 u[ 4], u[ 5], u[ 6], u[ 7],
826 u[ 8], u[ 9], u[10], u[11],
827 u[12], u[13], u[14], u[15],
828 name);
829 }
830 else
831 log->Printf("\t name='%s' (UNLOADED)", name);
832 }
833 else
834 {
835 if (u)
836 {
837 log->Printf("\taddress=0x%16.16llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name='%s'",
838 address,
839 u[ 0], u[ 1], u[ 2], u[ 3],
840 u[ 4], u[ 5], u[ 6], u[ 7],
841 u[ 8], u[ 9], u[10], u[11],
842 u[12], u[13], u[14], u[15],
843 name);
844 }
845 else
846 {
847 log->Printf("\taddress=0x%16.16llx path='%s/%s'", address, name);
848 }
849 for (uint32_t i=0; i<segments.size(); ++i)
850 segments[i].PutToLog(log, 0);
851 }
852}
853
854//----------------------------------------------------------------------
855// Dump the _dyld_all_image_infos members and all current image infos
856// that we have parsed to the file handle provided.
857//----------------------------------------------------------------------
858void
859DynamicLoaderMacOSXKernel::PutToLog(Log *log) const
860{
861 if (log == NULL)
862 return;
863
864 Mutex::Locker locker(m_mutex);
865 log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u, reserved=%u }",
Greg Clayton0d9fc762011-07-08 03:21:57 +0000866 m_kext_summary_header_addr.GetFileAddress(),
Greg Clayton7b242382011-07-08 00:48:09 +0000867 m_kext_summary_header.version,
868 m_kext_summary_header.entry_size,
869 m_kext_summary_header.entry_count,
870 m_kext_summary_header.reserved);
871
872 size_t i;
873 const size_t count = m_kext_summaries.size();
874 if (count > 0)
875 {
876 log->PutCString("Loaded:");
877 for (i = 0; i<count; i++)
878 m_kext_summaries[i].PutToLog(log);
879 }
880}
881
882void
883DynamicLoaderMacOSXKernel::PrivateInitialize(Process *process)
884{
885 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
886 Clear(true);
887 m_process = process;
888 m_process->GetTarget().GetSectionLoadList().Clear();
889}
890
Greg Clayton374972e2011-07-09 17:15:55 +0000891void
892DynamicLoaderMacOSXKernel::SetNotificationBreakpointIfNeeded ()
Greg Clayton7b242382011-07-08 00:48:09 +0000893{
Greg Clayton374972e2011-07-09 17:15:55 +0000894 if (m_break_id == LLDB_INVALID_BREAK_ID)
895 {
896 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
897
898 const bool internal_bp = false;
899 Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&m_kernel.module_sp->GetFileSpec(),
900 "OSKextLoadedKextSummariesUpdated",
901 eFunctionNameTypeFull,
902 internal_bp).get();
903
904 bp->SetCallback (DynamicLoaderMacOSXKernel::BreakpointHitCallback, this, true);
905 m_break_id = bp->GetID();
906 }
Greg Clayton7b242382011-07-08 00:48:09 +0000907}
908
909//----------------------------------------------------------------------
910// Member function that gets called when the process state changes.
911//----------------------------------------------------------------------
912void
913DynamicLoaderMacOSXKernel::PrivateProcessStateChanged (Process *process, StateType state)
914{
915 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s(%s)\n", __FUNCTION__, StateAsCString(state));
916 switch (state)
917 {
918 case eStateConnected:
919 case eStateAttaching:
920 case eStateLaunching:
921 case eStateInvalid:
922 case eStateUnloaded:
923 case eStateExited:
924 case eStateDetached:
925 Clear(false);
926 break;
927
928 case eStateStopped:
Greg Clayton374972e2011-07-09 17:15:55 +0000929 UpdateIfNeeded();
Greg Clayton7b242382011-07-08 00:48:09 +0000930 break;
931
932 case eStateRunning:
933 case eStateStepping:
934 case eStateCrashed:
935 case eStateSuspended:
936 break;
937
938 default:
939 break;
940 }
941}
942
943ThreadPlanSP
944DynamicLoaderMacOSXKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
945{
946 ThreadPlanSP thread_plan_sp;
Greg Clayton374972e2011-07-09 17:15:55 +0000947 LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
948 if (log)
949 log->Printf ("Could not find symbol for step through.");
Greg Clayton7b242382011-07-08 00:48:09 +0000950 return thread_plan_sp;
951}
952
953Error
954DynamicLoaderMacOSXKernel::CanLoadImage ()
955{
956 Error error;
957 error.SetErrorString("always unsafe to load or unload shared libraries in the darwin kernel");
958 return error;
959}
960
961void
962DynamicLoaderMacOSXKernel::Initialize()
963{
964 PluginManager::RegisterPlugin (GetPluginNameStatic(),
965 GetPluginDescriptionStatic(),
966 CreateInstance);
967}
968
969void
970DynamicLoaderMacOSXKernel::Terminate()
971{
972 PluginManager::UnregisterPlugin (CreateInstance);
973}
974
975
976const char *
977DynamicLoaderMacOSXKernel::GetPluginNameStatic()
978{
979 return "dynamic-loader.macosx-kernel";
980}
981
982const char *
983DynamicLoaderMacOSXKernel::GetPluginDescriptionStatic()
984{
985 return "Dynamic loader plug-in that watches for shared library loads/unloads in the MacOSX kernel.";
986}
987
988
989//------------------------------------------------------------------
990// PluginInterface protocol
991//------------------------------------------------------------------
992const char *
993DynamicLoaderMacOSXKernel::GetPluginName()
994{
995 return "DynamicLoaderMacOSXKernel";
996}
997
998const char *
999DynamicLoaderMacOSXKernel::GetShortPluginName()
1000{
1001 return GetPluginNameStatic();
1002}
1003
1004uint32_t
1005DynamicLoaderMacOSXKernel::GetPluginVersion()
1006{
1007 return 1;
1008}
1009