blob: 8ca30b73faf536e9ced4f76d14d3c973bb5a66e7 [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 {
54 const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
55 if (triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple)
56 create = true;
57 }
58
59 if (create)
60 return new DynamicLoaderMacOSXKernel (process);
61 return NULL;
62}
63
64//----------------------------------------------------------------------
65// Constructor
66//----------------------------------------------------------------------
67DynamicLoaderMacOSXKernel::DynamicLoaderMacOSXKernel (Process* process) :
68 DynamicLoader(process),
69 m_kernel(),
70 m_kext_summary_header_addr (LLDB_INVALID_ADDRESS),
71 m_kext_summary_header (),
72 m_kext_summary_header_stop_id (0),
73 m_break_id (LLDB_INVALID_BREAK_ID),
74 m_kext_summaries(),
75 m_kext_summaries_stop_id (UINT32_MAX),
76 m_mutex(Mutex::eMutexTypeRecursive),
77 m_notification_callbacks ()
78{
79}
80
81//----------------------------------------------------------------------
82// Destructor
83//----------------------------------------------------------------------
84DynamicLoaderMacOSXKernel::~DynamicLoaderMacOSXKernel()
85{
86 Clear(true);
87}
88
89//------------------------------------------------------------------
90/// Called after attaching a process.
91///
92/// Allow DynamicLoader plug-ins to execute some code after
93/// attaching to a process.
94//------------------------------------------------------------------
95void
96DynamicLoaderMacOSXKernel::DidAttach ()
97{
98 PrivateInitialize(m_process);
99 LoadKernelModule();
100 SetNotificationBreakpoint ();
101}
102
103//------------------------------------------------------------------
104/// Called after attaching a process.
105///
106/// Allow DynamicLoader plug-ins to execute some code after
107/// attaching to a process.
108//------------------------------------------------------------------
109void
110DynamicLoaderMacOSXKernel::DidLaunch ()
111{
112 PrivateInitialize(m_process);
113 LoadKernelModule();
114 SetNotificationBreakpoint ();
115}
116
117
118//----------------------------------------------------------------------
119// Clear out the state of this class.
120//----------------------------------------------------------------------
121void
122DynamicLoaderMacOSXKernel::Clear (bool clear_process)
123{
124 Mutex::Locker locker(m_mutex);
125
126 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
127 m_process->ClearBreakpointSiteByID(m_break_id);
128
129 if (clear_process)
130 m_process = NULL;
131 m_kernel.Clear(false);
132 m_kext_summary_header_addr = LLDB_INVALID_ADDRESS;
133 m_kext_summaries.clear();
134 m_kext_summaries_stop_id = 0;
135 m_break_id = LLDB_INVALID_BREAK_ID;
136}
137
138//----------------------------------------------------------------------
139// Check if we have found DYLD yet
140//----------------------------------------------------------------------
141bool
142DynamicLoaderMacOSXKernel::DidSetNotificationBreakpoint() const
143{
144 return LLDB_BREAK_ID_IS_VALID (m_break_id);
145}
146
147//----------------------------------------------------------------------
148// Load the kernel module and initialize the "m_kernel" member. Return
149// true _only_ if the kernel is loaded the first time through (subsequent
150// calls to this function should return false after the kernel has been
151// already loaded).
152//----------------------------------------------------------------------
153bool
154DynamicLoaderMacOSXKernel::LoadKernelModule()
155{
156 if (m_kext_summary_header_addr == LLDB_INVALID_ADDRESS)
157 {
158 m_kernel.Clear(false);
159 m_kernel.module_sp = m_process->GetTarget().GetExecutableModule();
160 if (m_kernel.module_sp)
161 {
162 static ConstString mach_header_name ("_mh_execute_header");
163 const Symbol *symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute);
164 if (symbol)
165 {
166 m_kernel.address = symbol->GetValue().GetFileAddress();
167 DataExtractor data; // Load command data
168 if (ReadMachHeader (m_kernel.address, &m_kernel.header, &data))
169 {
170 if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor)
171 {
172 if (ParseLoadCommands (data, m_kernel))
173 UpdateImageLoadAddress (m_kernel);
174
175 // Update all image infos
176 ReadAllKextSummaries (false);
177 return true;
178 }
179 }
180 else
181 {
182 m_kernel.Clear(false);
183 }
184 return false;
185 }
186 }
187 }
188 return false;
189}
190
191bool
192DynamicLoaderMacOSXKernel::FindTargetModule (OSKextLoadedKextSummary &image_info, bool can_create, bool *did_create_ptr)
193{
194 if (did_create_ptr)
195 *did_create_ptr = false;
196
197 const bool image_info_uuid_is_valid = image_info.uuid.IsValid();
198
199 if (image_info.module_sp)
200 {
201 if (image_info_uuid_is_valid)
202 {
203 if (image_info.module_sp->GetUUID() == image_info.uuid)
204 return true;
205 else
206 image_info.module_sp.reset();
207 }
208 else
209 return true;
210 }
211
212 ModuleList &target_images = m_process->GetTarget().GetImages();
213 if (image_info_uuid_is_valid)
214 image_info.module_sp = target_images.FindModule(image_info.uuid);
215
216 if (image_info.module_sp)
217 return true;
218
219 ArchSpec arch (image_info.GetArchitecture ());
220 if (can_create)
221 {
222 if (image_info_uuid_is_valid)
223 {
224 image_info.module_sp = m_process->GetTarget().GetSharedModule (FileSpec(),
225 arch,
226 &image_info.uuid);
227 if (did_create_ptr)
228 *did_create_ptr = image_info.module_sp;
229 }
230 }
231 return image_info.module_sp;
232}
233
234bool
235DynamicLoaderMacOSXKernel::UpdateCommPageLoadAddress(Module *module)
236{
237 bool changed = false;
238 if (module)
239 {
240 ObjectFile *image_object_file = module->GetObjectFile();
241 if (image_object_file)
242 {
243 SectionList *section_list = image_object_file->GetSectionList ();
244 if (section_list)
245 {
246 uint32_t num_sections = section_list->GetSize();
247 for (uint32_t i=0; i<num_sections; ++i)
248 {
249 Section* section = section_list->GetSectionAtIndex (i).get();
250 if (section)
251 {
252 const addr_t new_section_load_addr = section->GetFileAddress ();
253 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section);
254 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
255 old_section_load_addr != new_section_load_addr)
256 {
257 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ()))
258 changed = true;
259 }
260 }
261 }
262 }
263 }
264 }
265 return changed;
266}
267
268//----------------------------------------------------------------------
269// Update the load addresses for all segments in MODULE using the
270// updated INFO that is passed in.
271//----------------------------------------------------------------------
272bool
273DynamicLoaderMacOSXKernel::UpdateImageLoadAddress (OSKextLoadedKextSummary& info)
274{
275 Module *module = info.module_sp.get();
276 bool changed = false;
277 if (module)
278 {
279 ObjectFile *image_object_file = module->GetObjectFile();
280 if (image_object_file)
281 {
282 SectionList *section_list = image_object_file->GetSectionList ();
283 if (section_list)
284 {
285 // We now know the slide amount, so go through all sections
286 // and update the load addresses with the correct values.
287 uint32_t num_segments = info.segments.size();
288 for (uint32_t i=0; i<num_segments; ++i)
289 {
290 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
291 const addr_t new_section_load_addr = info.segments[i].vmaddr;
292 if (section_sp)
293 {
294 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
295 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
296 old_section_load_addr != new_section_load_addr)
297 {
298 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
299 changed = true;
300 }
301 }
302 else
303 {
304 fprintf (stderr,
305 "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
306 info.segments[i].name.AsCString("<invalid>"),
307 (uint64_t)new_section_load_addr,
308 image_object_file->GetFileSpec().GetDirectory().AsCString(),
309 image_object_file->GetFileSpec().GetFilename().AsCString());
310 }
311 }
312 }
313 }
314 }
315 return changed;
316}
317
318//----------------------------------------------------------------------
319// Update the load addresses for all segments in MODULE using the
320// updated INFO that is passed in.
321//----------------------------------------------------------------------
322bool
323DynamicLoaderMacOSXKernel::UnloadImageLoadAddress (OSKextLoadedKextSummary& info)
324{
325 Module *module = info.module_sp.get();
326 bool changed = false;
327 if (module)
328 {
329 ObjectFile *image_object_file = module->GetObjectFile();
330 if (image_object_file)
331 {
332 SectionList *section_list = image_object_file->GetSectionList ();
333 if (section_list)
334 {
335 uint32_t num_segments = info.segments.size();
336 for (uint32_t i=0; i<num_segments; ++i)
337 {
338 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
339 if (section_sp)
340 {
341 const addr_t old_section_load_addr = info.segments[i].vmaddr;
342 if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
343 changed = true;
344 }
345 else
346 {
347 fprintf (stderr,
348 "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n",
349 info.segments[i].name.AsCString("<invalid>"),
350 image_object_file->GetFileSpec().GetDirectory().AsCString(),
351 image_object_file->GetFileSpec().GetFilename().AsCString());
352 }
353 }
354 }
355 }
356 }
357 return changed;
358}
359
360
361//----------------------------------------------------------------------
362// Static callback function that gets called when our DYLD notification
363// breakpoint gets hit. We update all of our image infos and then
364// let our super class DynamicLoader class decide if we should stop
365// or not (based on global preference).
366//----------------------------------------------------------------------
367bool
368DynamicLoaderMacOSXKernel::NotifyBreakpointHit (void *baton,
369 StoppointCallbackContext *context,
370 lldb::user_id_t break_id,
371 lldb::user_id_t break_loc_id)
372{
373 // Let the event know that the images have changed
374 // DYLD passes three arguments to the notification breakpoint.
375 // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing
376 // Arg2: uint32_t infoCount - Number of shared libraries added
377 // Arg3: dyld_image_info info[] - Array of structs of the form:
378 // const struct mach_header *imageLoadAddress
379 // const char *imageFilePath
380 // uintptr_t imageFileModDate (a time_t)
381
382 DynamicLoaderMacOSXKernel* dyld_instance = (DynamicLoaderMacOSXKernel*) baton;
383
384 // First step is to see if we've already initialized the all image infos. If we haven't then this function
385 // will do so and return true. In the course of initializing the all_image_infos it will read the complete
386 // current state, so we don't need to figure out what has changed from the data passed in to us.
387
388 if (!dyld_instance->ReadAllKextSummaries(false))
389 {
390 Process *process = context->exe_ctx.process;
391 const lldb::ABISP &abi = process->GetABI();
392 if (abi != NULL)
393 {
394 // Build up the value array to store the three arguments given above, then get the values from the ABI:
395
396 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
397 ValueList argument_values;
398 Value input_value;
399
400 void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
401 void *clang_uint32_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32);
402 input_value.SetValueType (Value::eValueTypeScalar);
403 input_value.SetContext (Value::eContextTypeClangType, clang_uint32_type);
404 argument_values.PushValue(input_value);
405 argument_values.PushValue(input_value);
406 input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
407 argument_values.PushValue (input_value);
408
409 if (abi->GetArgumentValues (*context->exe_ctx.thread, argument_values))
410 {
411 uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1);
412 if (dyld_mode != -1)
413 {
414 // Okay the mode was right, now get the number of elements, and the array of new elements...
415 uint32_t image_infos_count = argument_values.GetValueAtIndex(1)->GetScalar().UInt (-1);
416 if (image_infos_count != -1)
417 {
418 // Got the number added, now go through the array of added elements, putting out the mach header
419 // address, and adding the image.
420 // Note, I'm not putting in logging here, since the AddModules & RemoveModules functions do
421 // all the logging internally.
422
423 lldb::addr_t kext_summary_addr = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong();
424 if (dyld_mode == 0)
425 {
426 // This is add:
427 dyld_instance->ParseKextSummaries (kext_summary_addr, image_infos_count);
428 }
429 else
430 {
431 // This is remove:
432 dyld_instance->RemoveModulesUsingImageInfosAddress (kext_summary_addr, image_infos_count);
433 }
434
435 }
436 }
437 }
438 }
439 }
440 // Return true to stop the target, false to just let the target run
441 return dyld_instance->GetStopWhenImagesChange();
442}
443
444bool
445DynamicLoaderMacOSXKernel::ReadKextSummaryHeader ()
446{
447 Mutex::Locker locker(m_mutex);
448
449 // the all image infos is already valid for this process stop ID
450 if (m_process->GetStopID() == m_kext_summaries_stop_id)
451 return true;
452
453 m_kext_summaries.clear();
454 if (m_kext_summary_header_addr != LLDB_INVALID_ADDRESS)
455 {
456 const uint32_t addr_size = m_kernel.GetAddressByteSize ();
457 const ByteOrder byte_order = m_kernel.GetByteOrder();
458 Error error;
459 // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure
460 // which is currenty 4 uint32_t and a pointer.
461 uint8_t buf[24];
462 DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
463 const size_t count = 4 * sizeof(uint32_t) + addr_size;
464 const size_t bytes_read = m_process->ReadMemory (m_kext_summary_header_addr, buf, count, error);
465 if (bytes_read == count)
466 {
467 uint32_t offset = 0;
468 m_kext_summary_header.version = data.GetU32(&offset);
469 m_kext_summary_header.entry_size = data.GetU32(&offset);
470 m_kext_summary_header.entry_count = data.GetU32(&offset);
471 m_kext_summary_header.reserved = data.GetU32(&offset);
472 m_kext_summary_header_stop_id = m_process->GetStopID();
473 return true;
474 }
475 }
476 return false;
477}
478
479
480bool
481DynamicLoaderMacOSXKernel::ParseKextSummaries (lldb::addr_t kext_summary_addr, uint32_t count)
482{
483 OSKextLoadedKextSummary::collection kext_summaries;
484 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
485 if (log)
486 log->Printf ("Adding %d modules.\n");
487
488 Mutex::Locker locker(m_mutex);
489 if (m_process->GetStopID() == m_kext_summaries_stop_id)
490 return true;
491
492 if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
493 return false;
494
495 for (uint32_t i = 0; i < count; i++)
496 {
497 if (!kext_summaries[i].UUIDValid())
498 {
499 DataExtractor data; // Load command data
500 if (!ReadMachHeader (kext_summaries[i].address, &kext_summaries[i].header, &data))
501 continue;
502
503 ParseLoadCommands (data, kext_summaries[i]);
504 }
505 }
506 bool return_value = AddModulesUsingImageInfos (kext_summaries);
507 m_kext_summaries_stop_id = m_process->GetStopID();
508 return return_value;
509}
510
511// Adds the modules in image_infos to m_kext_summaries.
512// NB don't call this passing in m_kext_summaries.
513
514bool
515DynamicLoaderMacOSXKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos)
516{
517 // Now add these images to the main list.
518 ModuleList loaded_module_list;
519 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
520
521 for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
522 {
523 if (log)
524 {
525 log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address);
526 image_infos[idx].PutToLog (log.get());
527 }
528
529 m_kext_summaries.push_back(image_infos[idx]);
530
531 if (FindTargetModule (image_infos[idx], true, NULL))
532 {
533 // UpdateImageLoadAddress will return true if any segments
534 // change load address. We need to check this so we don't
535 // mention that all loaded shared libraries are newly loaded
536 // each time we hit out dyld breakpoint since dyld will list all
537 // shared libraries each time.
538 if (UpdateImageLoadAddress (image_infos[idx]))
539 {
540 loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
541 }
542 }
543 }
544
545 if (loaded_module_list.GetSize() > 0)
546 {
547 // FIXME: This should really be in the Runtime handlers class, which should get
548 // called by the target's ModulesDidLoad, but we're doing it all locally for now
549 // to save time.
550 // Also, I'm assuming there can be only one libobjc dylib loaded...
551
552 ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
553 if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
554 {
555 size_t num_modules = loaded_module_list.GetSize();
556 for (int i = 0; i < num_modules; i++)
557 {
558 if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
559 {
560 objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
561 break;
562 }
563 }
564 }
565 if (log)
566 loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidLoad");
567 m_process->GetTarget().ModulesDidLoad (loaded_module_list);
568 }
569 return true;
570}
571
572bool
573DynamicLoaderMacOSXKernel::RemoveModulesUsingImageInfosAddress (lldb::addr_t kext_summary_addr, uint32_t image_infos_count)
574{
575 OSKextLoadedKextSummary::collection image_infos;
576 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
577
578 Mutex::Locker locker(m_mutex);
579 if (m_process->GetStopID() == m_kext_summaries_stop_id)
580 return true;
581
582 // First read in the image_infos for the removed modules, and their headers & load commands.
583 if (!ReadKextSummaries (kext_summary_addr, image_infos_count, image_infos))
584 {
585 if (log)
586 log->PutCString ("Failed reading image infos array.");
587 return false;
588 }
589
590 if (log)
591 log->Printf ("Removing %d modules.", image_infos_count);
592
593 ModuleList unloaded_module_list;
594 for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
595 {
596 if (log)
597 {
598 log->Printf ("Removing module at address=0x%16.16llx.", image_infos[idx].address);
599 image_infos[idx].PutToLog (log.get());
600 }
601
602 // Remove this image_infos from the m_all_image_infos. We do the comparision by address
603 // rather than by file spec because we can have many modules with the same "file spec" in the
604 // case that they are modules loaded from memory.
605 //
606 // Also copy over the uuid from the old entry to the removed entry so we can
607 // use it to lookup the module in the module list.
608
609 OSKextLoadedKextSummary::collection::iterator pos, end = m_kext_summaries.end();
610 for (pos = m_kext_summaries.begin(); pos != end; pos++)
611 {
612 if (image_infos[idx].address == (*pos).address)
613 {
614 image_infos[idx].uuid = (*pos).uuid;
615
616 // Add the module from this image_info to the "unloaded_module_list". We'll remove them all at
617 // one go later on.
618
619 if (FindTargetModule (image_infos[idx], false, NULL))
620 {
621 UnloadImageLoadAddress (image_infos[idx]);
622 unloaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
623 }
624 else
625 {
626 if (log)
627 {
628 log->Printf ("Could not find module for unloading info entry:");
629 image_infos[idx].PutToLog(log.get());
630 }
631 }
632
633 // Then remove it from the m_kext_summaries:
634
635 m_kext_summaries.erase(pos);
636 break;
637 }
638 }
639
640 if (pos == end)
641 {
642 if (log)
643 {
644 log->Printf ("Could not find image_info entry for unloading image:");
645 image_infos[idx].PutToLog(log.get());
646 }
647 }
648 }
649 if (unloaded_module_list.GetSize() > 0)
650 {
651 if (log)
652 {
653 log->PutCString("Unloaded:");
654 unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidUnload");
655 }
656 m_process->GetTarget().ModulesDidUnload (unloaded_module_list);
657 }
658 m_kext_summaries_stop_id = m_process->GetStopID();
659 return true;
660}
661
662uint32_t
663DynamicLoaderMacOSXKernel::ReadKextSummaries (lldb::addr_t kext_summary_addr,
664 uint32_t image_infos_count,
665 OSKextLoadedKextSummary::collection &image_infos)
666{
667 const ByteOrder endian = m_kernel.GetByteOrder();
668 const uint32_t addr_size = m_kernel.GetAddressByteSize();
669
670 image_infos.resize(image_infos_count);
671 const size_t count = image_infos.size() * m_kext_summary_header.entry_size;
672 DataBufferHeap data(count, 0);
673 Error error;
674 const size_t bytes_read = m_process->ReadMemory (kext_summary_addr,
675 data.GetBytes(),
676 data.GetByteSize(),
677 error);
678 if (bytes_read == count)
679 {
680 uint32_t offset = 0;
681 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size);
682 uint32_t i=0;
683 for (; i < image_infos.size() && extractor.ValidOffsetForDataOfSize(offset, m_kext_summary_header.entry_size); ++i)
684 {
685 const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
686 if (name_data == NULL)
687 break;
688 memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME);
689 image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16));
690 image_infos[i].address = extractor.GetU64(&offset);
691 image_infos[i].size = extractor.GetU64(&offset);
692 image_infos[i].version = extractor.GetU64(&offset);
693 image_infos[i].load_tag = extractor.GetU32(&offset);
694 image_infos[i].flags = extractor.GetU32(&offset);
695 image_infos[i].reference_list = extractor.GetU64(&offset);
696 }
697 if (i < image_infos.size())
698 image_infos.resize(i);
699 }
700 else
701 {
702 image_infos.clear();
703 }
704 return image_infos.size();
705}
706
707bool
708DynamicLoaderMacOSXKernel::ReadAllKextSummaries (bool force)
709{
710 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
711
712 Mutex::Locker locker(m_mutex);
713 if (!force)
714 {
715 if (m_process->GetStopID() == m_kext_summaries_stop_id || m_kext_summaries.size() != 0)
716 return false;
717 }
718
719 if (ReadKextSummaryHeader ())
720 {
721 if (m_kext_summary_header.entry_count > 0)
722 {
723 if (!ParseKextSummaries (m_kext_summary_header_addr + 16, m_kext_summary_header.entry_count))
724 {
725 DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
726 m_kext_summaries.clear();
727 }
728 return true;
729 }
730 }
731 return false;
732}
733
734//----------------------------------------------------------------------
735// Read a mach_header at ADDR into HEADER, and also fill in the load
736// command data into LOAD_COMMAND_DATA if it is non-NULL.
737//
738// Returns true if we succeed, false if we fail for any reason.
739//----------------------------------------------------------------------
740bool
741DynamicLoaderMacOSXKernel::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data)
742{
743 DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
744 Error error;
745 size_t bytes_read = m_process->ReadMemory (addr,
746 header_bytes.GetBytes(),
747 header_bytes.GetByteSize(),
748 error);
749 if (bytes_read == sizeof(llvm::MachO::mach_header))
750 {
751 uint32_t offset = 0;
752 ::memset (header, 0, sizeof(header));
753
754 // Get the magic byte unswapped so we can figure out what we are dealing with
755 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4);
756 header->magic = data.GetU32(&offset);
757 lldb::addr_t load_cmd_addr = addr;
758 data.SetByteOrder(DynamicLoaderMacOSXKernel::GetByteOrderFromMagic(header->magic));
759 switch (header->magic)
760 {
761 case llvm::MachO::HeaderMagic32:
762 case llvm::MachO::HeaderMagic32Swapped:
763 data.SetAddressByteSize(4);
764 load_cmd_addr += sizeof(llvm::MachO::mach_header);
765 break;
766
767 case llvm::MachO::HeaderMagic64:
768 case llvm::MachO::HeaderMagic64Swapped:
769 data.SetAddressByteSize(8);
770 load_cmd_addr += sizeof(llvm::MachO::mach_header_64);
771 break;
772
773 default:
774 return false;
775 }
776
777 // Read the rest of dyld's mach header
778 if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
779 {
780 if (load_command_data == NULL)
781 return true; // We were able to read the mach_header and weren't asked to read the load command bytes
782
783 DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));
784
785 size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr,
786 load_cmd_data_sp->GetBytes(),
787 load_cmd_data_sp->GetByteSize(),
788 error);
789
790 if (load_cmd_bytes_read == header->sizeofcmds)
791 {
792 // Set the load command data and also set the correct endian
793 // swap settings and the correct address size
794 load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
795 load_command_data->SetByteOrder(data.GetByteOrder());
796 load_command_data->SetAddressByteSize(data.GetAddressByteSize());
797 return true; // We successfully read the mach_header and the load command data
798 }
799
800 return false; // We weren't able to read the load command data
801 }
802 }
803 return false; // We failed the read the mach_header
804}
805
806
807//----------------------------------------------------------------------
808// Parse the load commands for an image
809//----------------------------------------------------------------------
810uint32_t
811DynamicLoaderMacOSXKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& dylib_info)
812{
813 uint32_t offset = 0;
814 uint32_t cmd_idx;
815 Segment segment;
816 dylib_info.Clear (true);
817
818 for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++)
819 {
820 // Clear out any load command specific data from DYLIB_INFO since
821 // we are about to read it.
822
823 if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
824 {
825 llvm::MachO::load_command load_cmd;
826 uint32_t load_cmd_offset = offset;
827 load_cmd.cmd = data.GetU32 (&offset);
828 load_cmd.cmdsize = data.GetU32 (&offset);
829 switch (load_cmd.cmd)
830 {
831 case llvm::MachO::LoadCommandSegment32:
832 {
833 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
834 // We are putting 4 uint32_t values 4 uint64_t values so
835 // we have to use multiple 32 bit gets below.
836 segment.vmaddr = data.GetU32 (&offset);
837 segment.vmsize = data.GetU32 (&offset);
838 segment.fileoff = data.GetU32 (&offset);
839 segment.filesize = data.GetU32 (&offset);
840 // Extract maxprot, initprot, nsects and flags all at once
841 data.GetU32(&offset, &segment.maxprot, 4);
842 dylib_info.segments.push_back (segment);
843 }
844 break;
845
846 case llvm::MachO::LoadCommandSegment64:
847 {
848 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
849 // Extract vmaddr, vmsize, fileoff, and filesize all at once
850 data.GetU64(&offset, &segment.vmaddr, 4);
851 // Extract maxprot, initprot, nsects and flags all at once
852 data.GetU32(&offset, &segment.maxprot, 4);
853 dylib_info.segments.push_back (segment);
854 }
855 break;
856
857 case llvm::MachO::LoadCommandUUID:
858 dylib_info.uuid.SetBytes(data.GetData (&offset, 16));
859 break;
860
861 default:
862 break;
863 }
864 // Set offset to be the beginning of the next load command.
865 offset = load_cmd_offset + load_cmd.cmdsize;
866 }
867 }
868#if 0
869 // No slide in the kernel...
870
871 // All sections listed in the dyld image info structure will all
872 // either be fixed up already, or they will all be off by a single
873 // slide amount that is determined by finding the first segment
874 // that is at file offset zero which also has bytes (a file size
875 // that is greater than zero) in the object file.
876
877 // Determine the slide amount (if any)
878 const size_t num_sections = dylib_info.segments.size();
879 for (size_t i = 0; i < num_sections; ++i)
880 {
881 // Iterate through the object file sections to find the
882 // first section that starts of file offset zero and that
883 // has bytes in the file...
884 if (dylib_info.segments[i].fileoff == 0 && dylib_info.segments[i].filesize > 0)
885 {
886 dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
887 // We have found the slide amount, so we can exit
888 // this for loop.
889 break;
890 }
891 }
892#endif
893 return cmd_idx;
894}
895
896//----------------------------------------------------------------------
897// Dump a Segment to the file handle provided.
898//----------------------------------------------------------------------
899void
900DynamicLoaderMacOSXKernel::Segment::PutToLog (Log *log, lldb::addr_t slide) const
901{
902 if (log)
903 {
904 if (slide == 0)
905 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)",
906 name.AsCString(""),
907 vmaddr + slide,
908 vmaddr + slide + vmsize);
909 else
910 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx",
911 name.AsCString(""),
912 vmaddr + slide,
913 vmaddr + slide + vmsize,
914 slide);
915 }
916}
917
918const DynamicLoaderMacOSXKernel::Segment *
919DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::FindSegment (const ConstString &name) const
920{
921 const size_t num_segments = segments.size();
922 for (size_t i=0; i<num_segments; ++i)
923 {
924 if (segments[i].name == name)
925 return &segments[i];
926 }
927 return NULL;
928}
929
930
931//----------------------------------------------------------------------
932// Dump an image info structure to the file handle provided.
933//----------------------------------------------------------------------
934void
935DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
936{
937 if (log == NULL)
938 return;
939 uint8_t *u = (uint8_t *)uuid.GetBytes();
940//
941// char name[KERNEL_MODULE_MAX_NAME];
942// lldb::ModuleSP module_sp;
943// lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
944// uint64_t address;
945// uint64_t size;
946// uint64_t version;
947// uint32_t load_tag;
948// uint32_t flags;
949// uint64_t reference_list;
950// llvm::MachO::mach_header header; // The mach header for this image
951// std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
952
953 if (address == LLDB_INVALID_ADDRESS)
954 {
955 if (u)
956 {
957 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)",
958 u[ 0], u[ 1], u[ 2], u[ 3],
959 u[ 4], u[ 5], u[ 6], u[ 7],
960 u[ 8], u[ 9], u[10], u[11],
961 u[12], u[13], u[14], u[15],
962 name);
963 }
964 else
965 log->Printf("\t name='%s' (UNLOADED)", name);
966 }
967 else
968 {
969 if (u)
970 {
971 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'",
972 address,
973 u[ 0], u[ 1], u[ 2], u[ 3],
974 u[ 4], u[ 5], u[ 6], u[ 7],
975 u[ 8], u[ 9], u[10], u[11],
976 u[12], u[13], u[14], u[15],
977 name);
978 }
979 else
980 {
981 log->Printf("\taddress=0x%16.16llx path='%s/%s'", address, name);
982 }
983 for (uint32_t i=0; i<segments.size(); ++i)
984 segments[i].PutToLog(log, 0);
985 }
986}
987
988//----------------------------------------------------------------------
989// Dump the _dyld_all_image_infos members and all current image infos
990// that we have parsed to the file handle provided.
991//----------------------------------------------------------------------
992void
993DynamicLoaderMacOSXKernel::PutToLog(Log *log) const
994{
995 if (log == NULL)
996 return;
997
998 Mutex::Locker locker(m_mutex);
999 log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u, reserved=%u }",
1000 m_kext_summary_header_addr,
1001 m_kext_summary_header.version,
1002 m_kext_summary_header.entry_size,
1003 m_kext_summary_header.entry_count,
1004 m_kext_summary_header.reserved);
1005
1006 size_t i;
1007 const size_t count = m_kext_summaries.size();
1008 if (count > 0)
1009 {
1010 log->PutCString("Loaded:");
1011 for (i = 0; i<count; i++)
1012 m_kext_summaries[i].PutToLog(log);
1013 }
1014}
1015
1016void
1017DynamicLoaderMacOSXKernel::PrivateInitialize(Process *process)
1018{
1019 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1020 Clear(true);
1021 m_process = process;
1022 m_process->GetTarget().GetSectionLoadList().Clear();
1023}
1024
1025bool
1026DynamicLoaderMacOSXKernel::SetNotificationBreakpoint ()
1027{
1028 // TODO: Add breakpoint to detected dynamic kext loads/unloads. We aren't
1029 // doing any live dynamic checks for kernel kexts being loaded or unloaded
1030 // on the fly yet.
1031// DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1032// if (m_break_id == LLDB_INVALID_BREAK_ID)
1033// {
1034// if (m_kext_summaries.notification != LLDB_INVALID_ADDRESS)
1035// {
1036// Address so_addr;
1037// // Set the notification breakpoint and install a breakpoint
1038// // callback function that will get called each time the
1039// // breakpoint gets hit. We will use this to track when shared
1040// // libraries get loaded/unloaded.
1041//
1042// if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_kext_summaries.notification, so_addr))
1043// {
1044// Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
1045// dyld_break->SetCallback (DynamicLoaderMacOSXKernel::NotifyBreakpointHit, this, true);
1046// m_break_id = dyld_break->GetID();
1047// }
1048// }
1049// }
1050 return m_break_id != LLDB_INVALID_BREAK_ID;
1051}
1052
1053//----------------------------------------------------------------------
1054// Member function that gets called when the process state changes.
1055//----------------------------------------------------------------------
1056void
1057DynamicLoaderMacOSXKernel::PrivateProcessStateChanged (Process *process, StateType state)
1058{
1059 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s(%s)\n", __FUNCTION__, StateAsCString(state));
1060 switch (state)
1061 {
1062 case eStateConnected:
1063 case eStateAttaching:
1064 case eStateLaunching:
1065 case eStateInvalid:
1066 case eStateUnloaded:
1067 case eStateExited:
1068 case eStateDetached:
1069 Clear(false);
1070 break;
1071
1072 case eStateStopped:
1073 // Keep trying find dyld and set our notification breakpoint each time
1074 // we stop until we succeed
1075 if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
1076 {
1077 if (LoadKernelModule())
1078 {
1079 }
1080
1081 SetNotificationBreakpoint ();
1082 }
1083 break;
1084
1085 case eStateRunning:
1086 case eStateStepping:
1087 case eStateCrashed:
1088 case eStateSuspended:
1089 break;
1090
1091 default:
1092 break;
1093 }
1094}
1095
1096ThreadPlanSP
1097DynamicLoaderMacOSXKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
1098{
1099 ThreadPlanSP thread_plan_sp;
1100 StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
1101 const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
1102 Symbol *current_symbol = current_context.symbol;
1103 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
1104
1105 if (current_symbol != NULL)
1106 {
1107 if (current_symbol->IsTrampoline())
1108 {
1109 const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
1110
1111 if (trampoline_name)
1112 {
1113 SymbolContextList target_symbols;
1114 ModuleList &images = thread.GetProcess().GetTarget().GetImages();
1115 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
1116 // FIXME - Make the Run to Address take multiple addresses, and
1117 // run to any of them.
1118 uint32_t num_symbols = target_symbols.GetSize();
1119 if (num_symbols == 1)
1120 {
1121 SymbolContext context;
1122 AddressRange addr_range;
1123 if (target_symbols.GetContextAtIndex(0, context))
1124 {
1125 context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1126 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others));
1127 }
1128 else
1129 {
1130 if (log)
1131 log->Printf ("Couldn't resolve the symbol context.");
1132 }
1133 }
1134 else if (num_symbols > 1)
1135 {
1136 std::vector<lldb::addr_t> addresses;
1137 addresses.resize (num_symbols);
1138 for (uint32_t i = 0; i < num_symbols; i++)
1139 {
1140 SymbolContext context;
1141 AddressRange addr_range;
1142 if (target_symbols.GetContextAtIndex(i, context))
1143 {
1144 context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1145 lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
1146 addresses[i] = load_addr;
1147 }
1148 }
1149 if (addresses.size() > 0)
1150 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others));
1151 else
1152 {
1153 if (log)
1154 log->Printf ("Couldn't resolve the symbol contexts.");
1155 }
1156 }
1157 else
1158 {
1159 if (log)
1160 {
1161 log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
1162 }
1163 }
1164 }
1165 }
1166 }
1167 else
1168 {
1169 if (log)
1170 log->Printf ("Could not find symbol for step through.");
1171 }
1172
1173 return thread_plan_sp;
1174}
1175
1176Error
1177DynamicLoaderMacOSXKernel::CanLoadImage ()
1178{
1179 Error error;
1180 error.SetErrorString("always unsafe to load or unload shared libraries in the darwin kernel");
1181 return error;
1182}
1183
1184void
1185DynamicLoaderMacOSXKernel::Initialize()
1186{
1187 PluginManager::RegisterPlugin (GetPluginNameStatic(),
1188 GetPluginDescriptionStatic(),
1189 CreateInstance);
1190}
1191
1192void
1193DynamicLoaderMacOSXKernel::Terminate()
1194{
1195 PluginManager::UnregisterPlugin (CreateInstance);
1196}
1197
1198
1199const char *
1200DynamicLoaderMacOSXKernel::GetPluginNameStatic()
1201{
1202 return "dynamic-loader.macosx-kernel";
1203}
1204
1205const char *
1206DynamicLoaderMacOSXKernel::GetPluginDescriptionStatic()
1207{
1208 return "Dynamic loader plug-in that watches for shared library loads/unloads in the MacOSX kernel.";
1209}
1210
1211
1212//------------------------------------------------------------------
1213// PluginInterface protocol
1214//------------------------------------------------------------------
1215const char *
1216DynamicLoaderMacOSXKernel::GetPluginName()
1217{
1218 return "DynamicLoaderMacOSXKernel";
1219}
1220
1221const char *
1222DynamicLoaderMacOSXKernel::GetShortPluginName()
1223{
1224 return GetPluginNameStatic();
1225}
1226
1227uint32_t
1228DynamicLoaderMacOSXKernel::GetPluginVersion()
1229{
1230 return 1;
1231}
1232