blob: f4a38dd494e1dc6ca1563cd3825dfbec9ace1988 [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 (),
92 m_kext_summary_header_stop_id (0),
93 m_break_id (LLDB_INVALID_BREAK_ID),
94 m_kext_summaries(),
95 m_kext_summaries_stop_id (UINT32_MAX),
96 m_mutex(Mutex::eMutexTypeRecursive),
97 m_notification_callbacks ()
98{
99}
100
101//----------------------------------------------------------------------
102// Destructor
103//----------------------------------------------------------------------
104DynamicLoaderMacOSXKernel::~DynamicLoaderMacOSXKernel()
105{
106 Clear(true);
107}
108
109//------------------------------------------------------------------
110/// Called after attaching a process.
111///
112/// Allow DynamicLoader plug-ins to execute some code after
113/// attaching to a process.
114//------------------------------------------------------------------
115void
116DynamicLoaderMacOSXKernel::DidAttach ()
117{
118 PrivateInitialize(m_process);
119 LoadKernelModule();
120 SetNotificationBreakpoint ();
121}
122
123//------------------------------------------------------------------
124/// Called after attaching a process.
125///
126/// Allow DynamicLoader plug-ins to execute some code after
127/// attaching to a process.
128//------------------------------------------------------------------
129void
130DynamicLoaderMacOSXKernel::DidLaunch ()
131{
132 PrivateInitialize(m_process);
133 LoadKernelModule();
134 SetNotificationBreakpoint ();
135}
136
137
138//----------------------------------------------------------------------
139// Clear out the state of this class.
140//----------------------------------------------------------------------
141void
142DynamicLoaderMacOSXKernel::Clear (bool clear_process)
143{
144 Mutex::Locker locker(m_mutex);
145
146 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
147 m_process->ClearBreakpointSiteByID(m_break_id);
148
149 if (clear_process)
150 m_process = NULL;
151 m_kernel.Clear(false);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000152 m_kext_summary_header_addr.Clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000153 m_kext_summaries.clear();
154 m_kext_summaries_stop_id = 0;
155 m_break_id = LLDB_INVALID_BREAK_ID;
156}
157
158//----------------------------------------------------------------------
159// Check if we have found DYLD yet
160//----------------------------------------------------------------------
161bool
162DynamicLoaderMacOSXKernel::DidSetNotificationBreakpoint() const
163{
164 return LLDB_BREAK_ID_IS_VALID (m_break_id);
165}
166
167//----------------------------------------------------------------------
168// Load the kernel module and initialize the "m_kernel" member. Return
169// true _only_ if the kernel is loaded the first time through (subsequent
170// calls to this function should return false after the kernel has been
171// already loaded).
172//----------------------------------------------------------------------
173bool
174DynamicLoaderMacOSXKernel::LoadKernelModule()
175{
Greg Clayton0d9fc762011-07-08 03:21:57 +0000176 if (!m_kext_summary_header_addr.IsValid())
Greg Clayton7b242382011-07-08 00:48:09 +0000177 {
178 m_kernel.Clear(false);
179 m_kernel.module_sp = m_process->GetTarget().GetExecutableModule();
180 if (m_kernel.module_sp)
181 {
182 static ConstString mach_header_name ("_mh_execute_header");
Greg Claytondf0b7d52011-07-08 04:11:42 +0000183 static ConstString kext_summary_symbol ("gLoadedKextSummaries");
184 const Symbol *symbol = NULL;
185 symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData);
186 if (symbol)
187 m_kext_summary_header_addr = symbol->GetValue();
188
189 symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute);
Greg Clayton7b242382011-07-08 00:48:09 +0000190 if (symbol)
191 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000192 // The "_mh_execute_header" symbol is absolute and not a section based
193 // symbol that will have a valid address, so we need to resolve it...
194 m_process->GetTarget().GetImages().ResolveFileAddress (symbol->GetValue().GetFileAddress(), m_kernel.so_address);
Greg Clayton7b242382011-07-08 00:48:09 +0000195 DataExtractor data; // Load command data
Greg Clayton0d9fc762011-07-08 03:21:57 +0000196 if (ReadMachHeader (m_kernel, &data))
Greg Clayton7b242382011-07-08 00:48:09 +0000197 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000198 if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeExecutable)
Greg Clayton7b242382011-07-08 00:48:09 +0000199 {
200 if (ParseLoadCommands (data, m_kernel))
201 UpdateImageLoadAddress (m_kernel);
202
203 // Update all image infos
204 ReadAllKextSummaries (false);
205 return true;
206 }
207 }
208 else
209 {
210 m_kernel.Clear(false);
211 }
212 return false;
213 }
214 }
215 }
216 return false;
217}
218
219bool
220DynamicLoaderMacOSXKernel::FindTargetModule (OSKextLoadedKextSummary &image_info, bool can_create, bool *did_create_ptr)
221{
222 if (did_create_ptr)
223 *did_create_ptr = false;
224
225 const bool image_info_uuid_is_valid = image_info.uuid.IsValid();
226
227 if (image_info.module_sp)
228 {
229 if (image_info_uuid_is_valid)
230 {
231 if (image_info.module_sp->GetUUID() == image_info.uuid)
232 return true;
233 else
234 image_info.module_sp.reset();
235 }
236 else
237 return true;
238 }
239
240 ModuleList &target_images = m_process->GetTarget().GetImages();
241 if (image_info_uuid_is_valid)
242 image_info.module_sp = target_images.FindModule(image_info.uuid);
243
244 if (image_info.module_sp)
245 return true;
246
247 ArchSpec arch (image_info.GetArchitecture ());
248 if (can_create)
249 {
250 if (image_info_uuid_is_valid)
251 {
252 image_info.module_sp = m_process->GetTarget().GetSharedModule (FileSpec(),
253 arch,
254 &image_info.uuid);
255 if (did_create_ptr)
256 *did_create_ptr = image_info.module_sp;
257 }
258 }
259 return image_info.module_sp;
260}
261
262bool
263DynamicLoaderMacOSXKernel::UpdateCommPageLoadAddress(Module *module)
264{
265 bool changed = false;
266 if (module)
267 {
268 ObjectFile *image_object_file = module->GetObjectFile();
269 if (image_object_file)
270 {
271 SectionList *section_list = image_object_file->GetSectionList ();
272 if (section_list)
273 {
274 uint32_t num_sections = section_list->GetSize();
275 for (uint32_t i=0; i<num_sections; ++i)
276 {
277 Section* section = section_list->GetSectionAtIndex (i).get();
278 if (section)
279 {
280 const addr_t new_section_load_addr = section->GetFileAddress ();
281 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section);
282 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
283 old_section_load_addr != new_section_load_addr)
284 {
285 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ()))
286 changed = true;
287 }
288 }
289 }
290 }
291 }
292 }
293 return changed;
294}
295
296//----------------------------------------------------------------------
297// Update the load addresses for all segments in MODULE using the
298// updated INFO that is passed in.
299//----------------------------------------------------------------------
300bool
301DynamicLoaderMacOSXKernel::UpdateImageLoadAddress (OSKextLoadedKextSummary& info)
302{
303 Module *module = info.module_sp.get();
304 bool changed = false;
305 if (module)
306 {
307 ObjectFile *image_object_file = module->GetObjectFile();
308 if (image_object_file)
309 {
310 SectionList *section_list = image_object_file->GetSectionList ();
311 if (section_list)
312 {
313 // We now know the slide amount, so go through all sections
314 // and update the load addresses with the correct values.
315 uint32_t num_segments = info.segments.size();
316 for (uint32_t i=0; i<num_segments; ++i)
317 {
318 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
319 const addr_t new_section_load_addr = info.segments[i].vmaddr;
320 if (section_sp)
321 {
322 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
323 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
324 old_section_load_addr != new_section_load_addr)
325 {
326 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
327 changed = true;
328 }
329 }
330 else
331 {
332 fprintf (stderr,
333 "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
334 info.segments[i].name.AsCString("<invalid>"),
335 (uint64_t)new_section_load_addr,
336 image_object_file->GetFileSpec().GetDirectory().AsCString(),
337 image_object_file->GetFileSpec().GetFilename().AsCString());
338 }
339 }
340 }
341 }
342 }
343 return changed;
344}
345
346//----------------------------------------------------------------------
347// Update the load addresses for all segments in MODULE using the
348// updated INFO that is passed in.
349//----------------------------------------------------------------------
350bool
351DynamicLoaderMacOSXKernel::UnloadImageLoadAddress (OSKextLoadedKextSummary& info)
352{
353 Module *module = info.module_sp.get();
354 bool changed = false;
355 if (module)
356 {
357 ObjectFile *image_object_file = module->GetObjectFile();
358 if (image_object_file)
359 {
360 SectionList *section_list = image_object_file->GetSectionList ();
361 if (section_list)
362 {
363 uint32_t num_segments = info.segments.size();
364 for (uint32_t i=0; i<num_segments; ++i)
365 {
366 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
367 if (section_sp)
368 {
369 const addr_t old_section_load_addr = info.segments[i].vmaddr;
370 if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
371 changed = true;
372 }
373 else
374 {
375 fprintf (stderr,
376 "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n",
377 info.segments[i].name.AsCString("<invalid>"),
378 image_object_file->GetFileSpec().GetDirectory().AsCString(),
379 image_object_file->GetFileSpec().GetFilename().AsCString());
380 }
381 }
382 }
383 }
384 }
385 return changed;
386}
387
388
389//----------------------------------------------------------------------
390// Static callback function that gets called when our DYLD notification
391// breakpoint gets hit. We update all of our image infos and then
392// let our super class DynamicLoader class decide if we should stop
393// or not (based on global preference).
394//----------------------------------------------------------------------
395bool
396DynamicLoaderMacOSXKernel::NotifyBreakpointHit (void *baton,
Greg Clayton0d9fc762011-07-08 03:21:57 +0000397 StoppointCallbackContext *context,
398 lldb::user_id_t break_id,
399 lldb::user_id_t break_loc_id)
400{
Greg Clayton7b242382011-07-08 00:48:09 +0000401 DynamicLoaderMacOSXKernel* dyld_instance = (DynamicLoaderMacOSXKernel*) baton;
402
Greg Clayton7b242382011-07-08 00:48:09 +0000403 // Return true to stop the target, false to just let the target run
404 return dyld_instance->GetStopWhenImagesChange();
405}
406
407bool
408DynamicLoaderMacOSXKernel::ReadKextSummaryHeader ()
409{
410 Mutex::Locker locker(m_mutex);
411
412 // the all image infos is already valid for this process stop ID
413 if (m_process->GetStopID() == m_kext_summaries_stop_id)
414 return true;
415
416 m_kext_summaries.clear();
Greg Clayton0d9fc762011-07-08 03:21:57 +0000417 if (m_kext_summary_header_addr.IsValid())
Greg Clayton7b242382011-07-08 00:48:09 +0000418 {
419 const uint32_t addr_size = m_kernel.GetAddressByteSize ();
420 const ByteOrder byte_order = m_kernel.GetByteOrder();
421 Error error;
422 // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure
423 // which is currenty 4 uint32_t and a pointer.
424 uint8_t buf[24];
425 DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
426 const size_t count = 4 * sizeof(uint32_t) + addr_size;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000427 const bool prefer_file_cache = false;
428 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 +0000429 if (bytes_read == count)
430 {
431 uint32_t offset = 0;
432 m_kext_summary_header.version = data.GetU32(&offset);
433 m_kext_summary_header.entry_size = data.GetU32(&offset);
434 m_kext_summary_header.entry_count = data.GetU32(&offset);
435 m_kext_summary_header.reserved = data.GetU32(&offset);
436 m_kext_summary_header_stop_id = m_process->GetStopID();
437 return true;
438 }
439 }
440 return false;
441}
442
443
444bool
Greg Clayton0d9fc762011-07-08 03:21:57 +0000445DynamicLoaderMacOSXKernel::ParseKextSummaries (const lldb_private::Address &kext_summary_addr,
446 uint32_t count)
Greg Clayton7b242382011-07-08 00:48:09 +0000447{
448 OSKextLoadedKextSummary::collection kext_summaries;
449 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
450 if (log)
451 log->Printf ("Adding %d modules.\n");
452
453 Mutex::Locker locker(m_mutex);
454 if (m_process->GetStopID() == m_kext_summaries_stop_id)
455 return true;
456
457 if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
458 return false;
459
460 for (uint32_t i = 0; i < count; i++)
461 {
462 if (!kext_summaries[i].UUIDValid())
463 {
464 DataExtractor data; // Load command data
Greg Clayton0d9fc762011-07-08 03:21:57 +0000465 if (!ReadMachHeader (kext_summaries[i], &data))
Greg Clayton7b242382011-07-08 00:48:09 +0000466 continue;
467
468 ParseLoadCommands (data, kext_summaries[i]);
469 }
470 }
471 bool return_value = AddModulesUsingImageInfos (kext_summaries);
472 m_kext_summaries_stop_id = m_process->GetStopID();
473 return return_value;
474}
475
476// Adds the modules in image_infos to m_kext_summaries.
477// NB don't call this passing in m_kext_summaries.
478
479bool
480DynamicLoaderMacOSXKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos)
481{
482 // Now add these images to the main list.
483 ModuleList loaded_module_list;
484 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
485
486 for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
487 {
488 if (log)
489 {
490 log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address);
491 image_infos[idx].PutToLog (log.get());
492 }
493
494 m_kext_summaries.push_back(image_infos[idx]);
495
496 if (FindTargetModule (image_infos[idx], true, NULL))
497 {
498 // UpdateImageLoadAddress will return true if any segments
499 // change load address. We need to check this so we don't
500 // mention that all loaded shared libraries are newly loaded
501 // each time we hit out dyld breakpoint since dyld will list all
502 // shared libraries each time.
503 if (UpdateImageLoadAddress (image_infos[idx]))
504 {
505 loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
506 }
507 }
508 }
509
510 if (loaded_module_list.GetSize() > 0)
511 {
512 // FIXME: This should really be in the Runtime handlers class, which should get
513 // called by the target's ModulesDidLoad, but we're doing it all locally for now
514 // to save time.
515 // Also, I'm assuming there can be only one libobjc dylib loaded...
516
517 ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
518 if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
519 {
520 size_t num_modules = loaded_module_list.GetSize();
521 for (int i = 0; i < num_modules; i++)
522 {
523 if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
524 {
525 objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
526 break;
527 }
528 }
529 }
530 if (log)
531 loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidLoad");
532 m_process->GetTarget().ModulesDidLoad (loaded_module_list);
533 }
534 return true;
535}
536
Greg Clayton7b242382011-07-08 00:48:09 +0000537
538uint32_t
Greg Clayton0d9fc762011-07-08 03:21:57 +0000539DynamicLoaderMacOSXKernel::ReadKextSummaries (const lldb_private::Address &kext_summary_addr,
Greg Clayton7b242382011-07-08 00:48:09 +0000540 uint32_t image_infos_count,
541 OSKextLoadedKextSummary::collection &image_infos)
542{
543 const ByteOrder endian = m_kernel.GetByteOrder();
544 const uint32_t addr_size = m_kernel.GetAddressByteSize();
545
546 image_infos.resize(image_infos_count);
547 const size_t count = image_infos.size() * m_kext_summary_header.entry_size;
548 DataBufferHeap data(count, 0);
549 Error error;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000550 const bool prefer_file_cache = false;
551 const size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary_addr,
552 prefer_file_cache,
553 data.GetBytes(),
554 data.GetByteSize(),
555 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000556 if (bytes_read == count)
557 {
558 uint32_t offset = 0;
559 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size);
560 uint32_t i=0;
561 for (; i < image_infos.size() && extractor.ValidOffsetForDataOfSize(offset, m_kext_summary_header.entry_size); ++i)
562 {
563 const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
564 if (name_data == NULL)
565 break;
566 memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME);
567 image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16));
568 image_infos[i].address = extractor.GetU64(&offset);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000569 if (!image_infos[i].so_address.SetLoadAddress (image_infos[i].address, &m_process->GetTarget()))
570 m_process->GetTarget().GetImages().ResolveFileAddress (image_infos[i].address, image_infos[i].so_address);
Greg Clayton7b242382011-07-08 00:48:09 +0000571 image_infos[i].size = extractor.GetU64(&offset);
572 image_infos[i].version = extractor.GetU64(&offset);
573 image_infos[i].load_tag = extractor.GetU32(&offset);
574 image_infos[i].flags = extractor.GetU32(&offset);
575 image_infos[i].reference_list = extractor.GetU64(&offset);
576 }
577 if (i < image_infos.size())
578 image_infos.resize(i);
579 }
580 else
581 {
582 image_infos.clear();
583 }
584 return image_infos.size();
585}
586
587bool
588DynamicLoaderMacOSXKernel::ReadAllKextSummaries (bool force)
589{
590 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
591
592 Mutex::Locker locker(m_mutex);
593 if (!force)
594 {
595 if (m_process->GetStopID() == m_kext_summaries_stop_id || m_kext_summaries.size() != 0)
596 return false;
597 }
598
599 if (ReadKextSummaryHeader ())
600 {
601 if (m_kext_summary_header.entry_count > 0)
602 {
Greg Clayton0d9fc762011-07-08 03:21:57 +0000603 Address summary_addr (m_kext_summary_header_addr);
604 summary_addr.Slide(16);
605 if (!ParseKextSummaries (summary_addr, m_kext_summary_header.entry_count))
Greg Clayton7b242382011-07-08 00:48:09 +0000606 {
607 DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
608 m_kext_summaries.clear();
609 }
610 return true;
611 }
612 }
613 return false;
614}
615
616//----------------------------------------------------------------------
617// Read a mach_header at ADDR into HEADER, and also fill in the load
618// command data into LOAD_COMMAND_DATA if it is non-NULL.
619//
620// Returns true if we succeed, false if we fail for any reason.
621//----------------------------------------------------------------------
622bool
Greg Clayton0d9fc762011-07-08 03:21:57 +0000623DynamicLoaderMacOSXKernel::ReadMachHeader (OSKextLoadedKextSummary& kext_summary, DataExtractor *load_command_data)
Greg Clayton7b242382011-07-08 00:48:09 +0000624{
625 DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
626 Error error;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000627 const bool prefer_file_cache = false;
628 size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary.so_address,
629 prefer_file_cache,
630 header_bytes.GetBytes(),
631 header_bytes.GetByteSize(),
632 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000633 if (bytes_read == sizeof(llvm::MachO::mach_header))
634 {
635 uint32_t offset = 0;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000636 ::memset (&kext_summary.header, 0, sizeof(kext_summary.header));
Greg Clayton7b242382011-07-08 00:48:09 +0000637
638 // Get the magic byte unswapped so we can figure out what we are dealing with
639 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000640 kext_summary.header.magic = data.GetU32(&offset);
641 Address load_cmd_addr = kext_summary.so_address;
642 data.SetByteOrder(DynamicLoaderMacOSXKernel::GetByteOrderFromMagic(kext_summary.header.magic));
643 switch (kext_summary.header.magic)
Greg Clayton7b242382011-07-08 00:48:09 +0000644 {
645 case llvm::MachO::HeaderMagic32:
646 case llvm::MachO::HeaderMagic32Swapped:
647 data.SetAddressByteSize(4);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000648 load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header));
Greg Clayton7b242382011-07-08 00:48:09 +0000649 break;
650
651 case llvm::MachO::HeaderMagic64:
652 case llvm::MachO::HeaderMagic64Swapped:
653 data.SetAddressByteSize(8);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000654 load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header_64));
Greg Clayton7b242382011-07-08 00:48:09 +0000655 break;
656
657 default:
658 return false;
659 }
660
661 // Read the rest of dyld's mach header
Greg Clayton0d9fc762011-07-08 03:21:57 +0000662 if (data.GetU32(&offset, &kext_summary.header.cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
Greg Clayton7b242382011-07-08 00:48:09 +0000663 {
664 if (load_command_data == NULL)
665 return true; // We were able to read the mach_header and weren't asked to read the load command bytes
666
Greg Clayton0d9fc762011-07-08 03:21:57 +0000667 DataBufferSP load_cmd_data_sp(new DataBufferHeap(kext_summary.header.sizeofcmds, 0));
Greg Clayton7b242382011-07-08 00:48:09 +0000668
Greg Clayton0d9fc762011-07-08 03:21:57 +0000669 size_t load_cmd_bytes_read = m_process->GetTarget().ReadMemory (load_cmd_addr,
670 prefer_file_cache,
671 load_cmd_data_sp->GetBytes(),
672 load_cmd_data_sp->GetByteSize(),
673 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000674
Greg Clayton0d9fc762011-07-08 03:21:57 +0000675 if (load_cmd_bytes_read == kext_summary.header.sizeofcmds)
Greg Clayton7b242382011-07-08 00:48:09 +0000676 {
677 // Set the load command data and also set the correct endian
678 // swap settings and the correct address size
Greg Clayton0d9fc762011-07-08 03:21:57 +0000679 load_command_data->SetData(load_cmd_data_sp, 0, kext_summary.header.sizeofcmds);
Greg Clayton7b242382011-07-08 00:48:09 +0000680 load_command_data->SetByteOrder(data.GetByteOrder());
681 load_command_data->SetAddressByteSize(data.GetAddressByteSize());
682 return true; // We successfully read the mach_header and the load command data
683 }
684
685 return false; // We weren't able to read the load command data
686 }
687 }
688 return false; // We failed the read the mach_header
689}
690
691
692//----------------------------------------------------------------------
693// Parse the load commands for an image
694//----------------------------------------------------------------------
695uint32_t
Greg Claytondf0b7d52011-07-08 04:11:42 +0000696DynamicLoaderMacOSXKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& image_info)
Greg Clayton7b242382011-07-08 00:48:09 +0000697{
698 uint32_t offset = 0;
699 uint32_t cmd_idx;
700 Segment segment;
Greg Claytondf0b7d52011-07-08 04:11:42 +0000701 image_info.Clear (true);
Greg Clayton7b242382011-07-08 00:48:09 +0000702
Greg Claytondf0b7d52011-07-08 04:11:42 +0000703 for (cmd_idx = 0; cmd_idx < image_info.header.ncmds; cmd_idx++)
Greg Clayton7b242382011-07-08 00:48:09 +0000704 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000705 // Clear out any load command specific data from image_info since
Greg Clayton7b242382011-07-08 00:48:09 +0000706 // we are about to read it.
707
708 if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
709 {
710 llvm::MachO::load_command load_cmd;
711 uint32_t load_cmd_offset = offset;
712 load_cmd.cmd = data.GetU32 (&offset);
713 load_cmd.cmdsize = data.GetU32 (&offset);
714 switch (load_cmd.cmd)
715 {
716 case llvm::MachO::LoadCommandSegment32:
717 {
718 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
719 // We are putting 4 uint32_t values 4 uint64_t values so
720 // we have to use multiple 32 bit gets below.
721 segment.vmaddr = data.GetU32 (&offset);
722 segment.vmsize = data.GetU32 (&offset);
723 segment.fileoff = data.GetU32 (&offset);
724 segment.filesize = data.GetU32 (&offset);
725 // Extract maxprot, initprot, nsects and flags all at once
726 data.GetU32(&offset, &segment.maxprot, 4);
Greg Claytondf0b7d52011-07-08 04:11:42 +0000727 image_info.segments.push_back (segment);
Greg Clayton7b242382011-07-08 00:48:09 +0000728 }
729 break;
730
731 case llvm::MachO::LoadCommandSegment64:
732 {
733 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
734 // Extract vmaddr, vmsize, fileoff, and filesize all at once
735 data.GetU64(&offset, &segment.vmaddr, 4);
736 // Extract maxprot, initprot, nsects and flags all at once
737 data.GetU32(&offset, &segment.maxprot, 4);
Greg Claytondf0b7d52011-07-08 04:11:42 +0000738 image_info.segments.push_back (segment);
Greg Clayton7b242382011-07-08 00:48:09 +0000739 }
740 break;
741
742 case llvm::MachO::LoadCommandUUID:
Greg Claytondf0b7d52011-07-08 04:11:42 +0000743 image_info.uuid.SetBytes(data.GetData (&offset, 16));
Greg Clayton7b242382011-07-08 00:48:09 +0000744 break;
745
746 default:
747 break;
748 }
749 // Set offset to be the beginning of the next load command.
750 offset = load_cmd_offset + load_cmd.cmdsize;
751 }
752 }
753#if 0
754 // No slide in the kernel...
755
756 // All sections listed in the dyld image info structure will all
757 // either be fixed up already, or they will all be off by a single
758 // slide amount that is determined by finding the first segment
759 // that is at file offset zero which also has bytes (a file size
760 // that is greater than zero) in the object file.
761
762 // Determine the slide amount (if any)
Greg Claytondf0b7d52011-07-08 04:11:42 +0000763 const size_t num_sections = image_info.segments.size();
Greg Clayton7b242382011-07-08 00:48:09 +0000764 for (size_t i = 0; i < num_sections; ++i)
765 {
766 // Iterate through the object file sections to find the
767 // first section that starts of file offset zero and that
768 // has bytes in the file...
Greg Claytondf0b7d52011-07-08 04:11:42 +0000769 if (image_info.segments[i].fileoff == 0 && image_info.segments[i].filesize > 0)
Greg Clayton7b242382011-07-08 00:48:09 +0000770 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000771 image_info.slide = image_info.address - image_info.segments[i].vmaddr;
Greg Clayton7b242382011-07-08 00:48:09 +0000772 // We have found the slide amount, so we can exit
773 // this for loop.
774 break;
775 }
776 }
777#endif
Greg Claytondf0b7d52011-07-08 04:11:42 +0000778 if (image_info.uuid.IsValid())
779 {
780 bool did_create = false;
781 if (FindTargetModule(image_info, true, &did_create))
782 {
783 if (did_create)
784 image_info.module_create_stop_id = m_process->GetStopID();
785 }
786 }
Greg Clayton7b242382011-07-08 00:48:09 +0000787 return cmd_idx;
788}
789
790//----------------------------------------------------------------------
791// Dump a Segment to the file handle provided.
792//----------------------------------------------------------------------
793void
794DynamicLoaderMacOSXKernel::Segment::PutToLog (Log *log, lldb::addr_t slide) const
795{
796 if (log)
797 {
798 if (slide == 0)
799 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)",
800 name.AsCString(""),
801 vmaddr + slide,
802 vmaddr + slide + vmsize);
803 else
804 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx",
805 name.AsCString(""),
806 vmaddr + slide,
807 vmaddr + slide + vmsize,
808 slide);
809 }
810}
811
812const DynamicLoaderMacOSXKernel::Segment *
813DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::FindSegment (const ConstString &name) const
814{
815 const size_t num_segments = segments.size();
816 for (size_t i=0; i<num_segments; ++i)
817 {
818 if (segments[i].name == name)
819 return &segments[i];
820 }
821 return NULL;
822}
823
824
825//----------------------------------------------------------------------
826// Dump an image info structure to the file handle provided.
827//----------------------------------------------------------------------
828void
829DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
830{
831 if (log == NULL)
832 return;
833 uint8_t *u = (uint8_t *)uuid.GetBytes();
834//
835// char name[KERNEL_MODULE_MAX_NAME];
836// lldb::ModuleSP module_sp;
837// lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
838// uint64_t address;
839// uint64_t size;
840// uint64_t version;
841// uint32_t load_tag;
842// uint32_t flags;
843// uint64_t reference_list;
844// llvm::MachO::mach_header header; // The mach header for this image
845// std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
846
847 if (address == LLDB_INVALID_ADDRESS)
848 {
849 if (u)
850 {
851 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)",
852 u[ 0], u[ 1], u[ 2], u[ 3],
853 u[ 4], u[ 5], u[ 6], u[ 7],
854 u[ 8], u[ 9], u[10], u[11],
855 u[12], u[13], u[14], u[15],
856 name);
857 }
858 else
859 log->Printf("\t name='%s' (UNLOADED)", name);
860 }
861 else
862 {
863 if (u)
864 {
865 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'",
866 address,
867 u[ 0], u[ 1], u[ 2], u[ 3],
868 u[ 4], u[ 5], u[ 6], u[ 7],
869 u[ 8], u[ 9], u[10], u[11],
870 u[12], u[13], u[14], u[15],
871 name);
872 }
873 else
874 {
875 log->Printf("\taddress=0x%16.16llx path='%s/%s'", address, name);
876 }
877 for (uint32_t i=0; i<segments.size(); ++i)
878 segments[i].PutToLog(log, 0);
879 }
880}
881
882//----------------------------------------------------------------------
883// Dump the _dyld_all_image_infos members and all current image infos
884// that we have parsed to the file handle provided.
885//----------------------------------------------------------------------
886void
887DynamicLoaderMacOSXKernel::PutToLog(Log *log) const
888{
889 if (log == NULL)
890 return;
891
892 Mutex::Locker locker(m_mutex);
893 log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u, reserved=%u }",
Greg Clayton0d9fc762011-07-08 03:21:57 +0000894 m_kext_summary_header_addr.GetFileAddress(),
Greg Clayton7b242382011-07-08 00:48:09 +0000895 m_kext_summary_header.version,
896 m_kext_summary_header.entry_size,
897 m_kext_summary_header.entry_count,
898 m_kext_summary_header.reserved);
899
900 size_t i;
901 const size_t count = m_kext_summaries.size();
902 if (count > 0)
903 {
904 log->PutCString("Loaded:");
905 for (i = 0; i<count; i++)
906 m_kext_summaries[i].PutToLog(log);
907 }
908}
909
910void
911DynamicLoaderMacOSXKernel::PrivateInitialize(Process *process)
912{
913 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
914 Clear(true);
915 m_process = process;
916 m_process->GetTarget().GetSectionLoadList().Clear();
917}
918
919bool
920DynamicLoaderMacOSXKernel::SetNotificationBreakpoint ()
921{
922 // TODO: Add breakpoint to detected dynamic kext loads/unloads. We aren't
923 // doing any live dynamic checks for kernel kexts being loaded or unloaded
924 // on the fly yet.
925// DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
926// if (m_break_id == LLDB_INVALID_BREAK_ID)
927// {
928// if (m_kext_summaries.notification != LLDB_INVALID_ADDRESS)
929// {
930// Address so_addr;
931// // Set the notification breakpoint and install a breakpoint
932// // callback function that will get called each time the
933// // breakpoint gets hit. We will use this to track when shared
934// // libraries get loaded/unloaded.
935//
936// if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_kext_summaries.notification, so_addr))
937// {
938// Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
939// dyld_break->SetCallback (DynamicLoaderMacOSXKernel::NotifyBreakpointHit, this, true);
940// m_break_id = dyld_break->GetID();
941// }
942// }
943// }
944 return m_break_id != LLDB_INVALID_BREAK_ID;
945}
946
947//----------------------------------------------------------------------
948// Member function that gets called when the process state changes.
949//----------------------------------------------------------------------
950void
951DynamicLoaderMacOSXKernel::PrivateProcessStateChanged (Process *process, StateType state)
952{
953 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s(%s)\n", __FUNCTION__, StateAsCString(state));
954 switch (state)
955 {
956 case eStateConnected:
957 case eStateAttaching:
958 case eStateLaunching:
959 case eStateInvalid:
960 case eStateUnloaded:
961 case eStateExited:
962 case eStateDetached:
963 Clear(false);
964 break;
965
966 case eStateStopped:
967 // Keep trying find dyld and set our notification breakpoint each time
968 // we stop until we succeed
969 if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
970 {
971 if (LoadKernelModule())
972 {
973 }
974
975 SetNotificationBreakpoint ();
976 }
977 break;
978
979 case eStateRunning:
980 case eStateStepping:
981 case eStateCrashed:
982 case eStateSuspended:
983 break;
984
985 default:
986 break;
987 }
988}
989
990ThreadPlanSP
991DynamicLoaderMacOSXKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
992{
993 ThreadPlanSP thread_plan_sp;
994 StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
995 const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
996 Symbol *current_symbol = current_context.symbol;
997 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
998
999 if (current_symbol != NULL)
1000 {
1001 if (current_symbol->IsTrampoline())
1002 {
1003 const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
1004
1005 if (trampoline_name)
1006 {
1007 SymbolContextList target_symbols;
1008 ModuleList &images = thread.GetProcess().GetTarget().GetImages();
1009 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
1010 // FIXME - Make the Run to Address take multiple addresses, and
1011 // run to any of them.
1012 uint32_t num_symbols = target_symbols.GetSize();
1013 if (num_symbols == 1)
1014 {
1015 SymbolContext context;
1016 AddressRange addr_range;
1017 if (target_symbols.GetContextAtIndex(0, context))
1018 {
1019 context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1020 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others));
1021 }
1022 else
1023 {
1024 if (log)
1025 log->Printf ("Couldn't resolve the symbol context.");
1026 }
1027 }
1028 else if (num_symbols > 1)
1029 {
1030 std::vector<lldb::addr_t> addresses;
1031 addresses.resize (num_symbols);
1032 for (uint32_t i = 0; i < num_symbols; i++)
1033 {
1034 SymbolContext context;
1035 AddressRange addr_range;
1036 if (target_symbols.GetContextAtIndex(i, context))
1037 {
1038 context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1039 lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
1040 addresses[i] = load_addr;
1041 }
1042 }
1043 if (addresses.size() > 0)
1044 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others));
1045 else
1046 {
1047 if (log)
1048 log->Printf ("Couldn't resolve the symbol contexts.");
1049 }
1050 }
1051 else
1052 {
1053 if (log)
1054 {
1055 log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
1056 }
1057 }
1058 }
1059 }
1060 }
1061 else
1062 {
1063 if (log)
1064 log->Printf ("Could not find symbol for step through.");
1065 }
1066
1067 return thread_plan_sp;
1068}
1069
1070Error
1071DynamicLoaderMacOSXKernel::CanLoadImage ()
1072{
1073 Error error;
1074 error.SetErrorString("always unsafe to load or unload shared libraries in the darwin kernel");
1075 return error;
1076}
1077
1078void
1079DynamicLoaderMacOSXKernel::Initialize()
1080{
1081 PluginManager::RegisterPlugin (GetPluginNameStatic(),
1082 GetPluginDescriptionStatic(),
1083 CreateInstance);
1084}
1085
1086void
1087DynamicLoaderMacOSXKernel::Terminate()
1088{
1089 PluginManager::UnregisterPlugin (CreateInstance);
1090}
1091
1092
1093const char *
1094DynamicLoaderMacOSXKernel::GetPluginNameStatic()
1095{
1096 return "dynamic-loader.macosx-kernel";
1097}
1098
1099const char *
1100DynamicLoaderMacOSXKernel::GetPluginDescriptionStatic()
1101{
1102 return "Dynamic loader plug-in that watches for shared library loads/unloads in the MacOSX kernel.";
1103}
1104
1105
1106//------------------------------------------------------------------
1107// PluginInterface protocol
1108//------------------------------------------------------------------
1109const char *
1110DynamicLoaderMacOSXKernel::GetPluginName()
1111{
1112 return "DynamicLoaderMacOSXKernel";
1113}
1114
1115const char *
1116DynamicLoaderMacOSXKernel::GetShortPluginName()
1117{
1118 return GetPluginNameStatic();
1119}
1120
1121uint32_t
1122DynamicLoaderMacOSXKernel::GetPluginVersion()
1123{
1124 return 1;
1125}
1126