blob: bd1ea64eddd4bff4fc20797a096f5c1130699037 [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(),
Greg Clayton0d9fc762011-07-08 03:21:57 +000070 m_kext_summary_header_addr (),
Greg Clayton7b242382011-07-08 00:48:09 +000071 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);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000132 m_kext_summary_header_addr.Clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000133 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{
Greg Clayton0d9fc762011-07-08 03:21:57 +0000156 if (!m_kext_summary_header_addr.IsValid())
Greg Clayton7b242382011-07-08 00:48:09 +0000157 {
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 {
Greg Clayton0d9fc762011-07-08 03:21:57 +0000166 m_kernel.so_address = symbol->GetValue();
Greg Clayton7b242382011-07-08 00:48:09 +0000167 DataExtractor data; // Load command data
Greg Clayton0d9fc762011-07-08 03:21:57 +0000168 if (ReadMachHeader (m_kernel, &data))
Greg Clayton7b242382011-07-08 00:48:09 +0000169 {
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,
Greg Clayton0d9fc762011-07-08 03:21:57 +0000369 StoppointCallbackContext *context,
370 lldb::user_id_t break_id,
371 lldb::user_id_t break_loc_id)
372{
Greg Clayton7b242382011-07-08 00:48:09 +0000373 DynamicLoaderMacOSXKernel* dyld_instance = (DynamicLoaderMacOSXKernel*) baton;
374
Greg Clayton7b242382011-07-08 00:48:09 +0000375 // Return true to stop the target, false to just let the target run
376 return dyld_instance->GetStopWhenImagesChange();
377}
378
379bool
380DynamicLoaderMacOSXKernel::ReadKextSummaryHeader ()
381{
382 Mutex::Locker locker(m_mutex);
383
384 // the all image infos is already valid for this process stop ID
385 if (m_process->GetStopID() == m_kext_summaries_stop_id)
386 return true;
387
388 m_kext_summaries.clear();
Greg Clayton0d9fc762011-07-08 03:21:57 +0000389 if (m_kext_summary_header_addr.IsValid())
Greg Clayton7b242382011-07-08 00:48:09 +0000390 {
391 const uint32_t addr_size = m_kernel.GetAddressByteSize ();
392 const ByteOrder byte_order = m_kernel.GetByteOrder();
393 Error error;
394 // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure
395 // which is currenty 4 uint32_t and a pointer.
396 uint8_t buf[24];
397 DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
398 const size_t count = 4 * sizeof(uint32_t) + addr_size;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000399 const bool prefer_file_cache = false;
400 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 +0000401 if (bytes_read == count)
402 {
403 uint32_t offset = 0;
404 m_kext_summary_header.version = data.GetU32(&offset);
405 m_kext_summary_header.entry_size = data.GetU32(&offset);
406 m_kext_summary_header.entry_count = data.GetU32(&offset);
407 m_kext_summary_header.reserved = data.GetU32(&offset);
408 m_kext_summary_header_stop_id = m_process->GetStopID();
409 return true;
410 }
411 }
412 return false;
413}
414
415
416bool
Greg Clayton0d9fc762011-07-08 03:21:57 +0000417DynamicLoaderMacOSXKernel::ParseKextSummaries (const lldb_private::Address &kext_summary_addr,
418 uint32_t count)
Greg Clayton7b242382011-07-08 00:48:09 +0000419{
420 OSKextLoadedKextSummary::collection kext_summaries;
421 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
422 if (log)
423 log->Printf ("Adding %d modules.\n");
424
425 Mutex::Locker locker(m_mutex);
426 if (m_process->GetStopID() == m_kext_summaries_stop_id)
427 return true;
428
429 if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
430 return false;
431
432 for (uint32_t i = 0; i < count; i++)
433 {
434 if (!kext_summaries[i].UUIDValid())
435 {
436 DataExtractor data; // Load command data
Greg Clayton0d9fc762011-07-08 03:21:57 +0000437 if (!ReadMachHeader (kext_summaries[i], &data))
Greg Clayton7b242382011-07-08 00:48:09 +0000438 continue;
439
440 ParseLoadCommands (data, kext_summaries[i]);
441 }
442 }
443 bool return_value = AddModulesUsingImageInfos (kext_summaries);
444 m_kext_summaries_stop_id = m_process->GetStopID();
445 return return_value;
446}
447
448// Adds the modules in image_infos to m_kext_summaries.
449// NB don't call this passing in m_kext_summaries.
450
451bool
452DynamicLoaderMacOSXKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos)
453{
454 // Now add these images to the main list.
455 ModuleList loaded_module_list;
456 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
457
458 for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
459 {
460 if (log)
461 {
462 log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address);
463 image_infos[idx].PutToLog (log.get());
464 }
465
466 m_kext_summaries.push_back(image_infos[idx]);
467
468 if (FindTargetModule (image_infos[idx], true, NULL))
469 {
470 // UpdateImageLoadAddress will return true if any segments
471 // change load address. We need to check this so we don't
472 // mention that all loaded shared libraries are newly loaded
473 // each time we hit out dyld breakpoint since dyld will list all
474 // shared libraries each time.
475 if (UpdateImageLoadAddress (image_infos[idx]))
476 {
477 loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
478 }
479 }
480 }
481
482 if (loaded_module_list.GetSize() > 0)
483 {
484 // FIXME: This should really be in the Runtime handlers class, which should get
485 // called by the target's ModulesDidLoad, but we're doing it all locally for now
486 // to save time.
487 // Also, I'm assuming there can be only one libobjc dylib loaded...
488
489 ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
490 if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
491 {
492 size_t num_modules = loaded_module_list.GetSize();
493 for (int i = 0; i < num_modules; i++)
494 {
495 if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
496 {
497 objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
498 break;
499 }
500 }
501 }
502 if (log)
503 loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidLoad");
504 m_process->GetTarget().ModulesDidLoad (loaded_module_list);
505 }
506 return true;
507}
508
Greg Clayton7b242382011-07-08 00:48:09 +0000509
510uint32_t
Greg Clayton0d9fc762011-07-08 03:21:57 +0000511DynamicLoaderMacOSXKernel::ReadKextSummaries (const lldb_private::Address &kext_summary_addr,
Greg Clayton7b242382011-07-08 00:48:09 +0000512 uint32_t image_infos_count,
513 OSKextLoadedKextSummary::collection &image_infos)
514{
515 const ByteOrder endian = m_kernel.GetByteOrder();
516 const uint32_t addr_size = m_kernel.GetAddressByteSize();
517
518 image_infos.resize(image_infos_count);
519 const size_t count = image_infos.size() * m_kext_summary_header.entry_size;
520 DataBufferHeap data(count, 0);
521 Error error;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000522 const bool prefer_file_cache = false;
523 const size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary_addr,
524 prefer_file_cache,
525 data.GetBytes(),
526 data.GetByteSize(),
527 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000528 if (bytes_read == count)
529 {
530 uint32_t offset = 0;
531 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size);
532 uint32_t i=0;
533 for (; i < image_infos.size() && extractor.ValidOffsetForDataOfSize(offset, m_kext_summary_header.entry_size); ++i)
534 {
535 const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
536 if (name_data == NULL)
537 break;
538 memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME);
539 image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16));
540 image_infos[i].address = extractor.GetU64(&offset);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000541 if (!image_infos[i].so_address.SetLoadAddress (image_infos[i].address, &m_process->GetTarget()))
542 m_process->GetTarget().GetImages().ResolveFileAddress (image_infos[i].address, image_infos[i].so_address);
Greg Clayton7b242382011-07-08 00:48:09 +0000543 image_infos[i].size = extractor.GetU64(&offset);
544 image_infos[i].version = extractor.GetU64(&offset);
545 image_infos[i].load_tag = extractor.GetU32(&offset);
546 image_infos[i].flags = extractor.GetU32(&offset);
547 image_infos[i].reference_list = extractor.GetU64(&offset);
548 }
549 if (i < image_infos.size())
550 image_infos.resize(i);
551 }
552 else
553 {
554 image_infos.clear();
555 }
556 return image_infos.size();
557}
558
559bool
560DynamicLoaderMacOSXKernel::ReadAllKextSummaries (bool force)
561{
562 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
563
564 Mutex::Locker locker(m_mutex);
565 if (!force)
566 {
567 if (m_process->GetStopID() == m_kext_summaries_stop_id || m_kext_summaries.size() != 0)
568 return false;
569 }
570
571 if (ReadKextSummaryHeader ())
572 {
573 if (m_kext_summary_header.entry_count > 0)
574 {
Greg Clayton0d9fc762011-07-08 03:21:57 +0000575 Address summary_addr (m_kext_summary_header_addr);
576 summary_addr.Slide(16);
577 if (!ParseKextSummaries (summary_addr, m_kext_summary_header.entry_count))
Greg Clayton7b242382011-07-08 00:48:09 +0000578 {
579 DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
580 m_kext_summaries.clear();
581 }
582 return true;
583 }
584 }
585 return false;
586}
587
588//----------------------------------------------------------------------
589// Read a mach_header at ADDR into HEADER, and also fill in the load
590// command data into LOAD_COMMAND_DATA if it is non-NULL.
591//
592// Returns true if we succeed, false if we fail for any reason.
593//----------------------------------------------------------------------
594bool
Greg Clayton0d9fc762011-07-08 03:21:57 +0000595DynamicLoaderMacOSXKernel::ReadMachHeader (OSKextLoadedKextSummary& kext_summary, DataExtractor *load_command_data)
Greg Clayton7b242382011-07-08 00:48:09 +0000596{
597 DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
598 Error error;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000599 const bool prefer_file_cache = false;
600 size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary.so_address,
601 prefer_file_cache,
602 header_bytes.GetBytes(),
603 header_bytes.GetByteSize(),
604 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000605 if (bytes_read == sizeof(llvm::MachO::mach_header))
606 {
607 uint32_t offset = 0;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000608 ::memset (&kext_summary.header, 0, sizeof(kext_summary.header));
Greg Clayton7b242382011-07-08 00:48:09 +0000609
610 // Get the magic byte unswapped so we can figure out what we are dealing with
611 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000612 kext_summary.header.magic = data.GetU32(&offset);
613 Address load_cmd_addr = kext_summary.so_address;
614 data.SetByteOrder(DynamicLoaderMacOSXKernel::GetByteOrderFromMagic(kext_summary.header.magic));
615 switch (kext_summary.header.magic)
Greg Clayton7b242382011-07-08 00:48:09 +0000616 {
617 case llvm::MachO::HeaderMagic32:
618 case llvm::MachO::HeaderMagic32Swapped:
619 data.SetAddressByteSize(4);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000620 load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header));
Greg Clayton7b242382011-07-08 00:48:09 +0000621 break;
622
623 case llvm::MachO::HeaderMagic64:
624 case llvm::MachO::HeaderMagic64Swapped:
625 data.SetAddressByteSize(8);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000626 load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header_64));
Greg Clayton7b242382011-07-08 00:48:09 +0000627 break;
628
629 default:
630 return false;
631 }
632
633 // Read the rest of dyld's mach header
Greg Clayton0d9fc762011-07-08 03:21:57 +0000634 if (data.GetU32(&offset, &kext_summary.header.cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
Greg Clayton7b242382011-07-08 00:48:09 +0000635 {
636 if (load_command_data == NULL)
637 return true; // We were able to read the mach_header and weren't asked to read the load command bytes
638
Greg Clayton0d9fc762011-07-08 03:21:57 +0000639 DataBufferSP load_cmd_data_sp(new DataBufferHeap(kext_summary.header.sizeofcmds, 0));
Greg Clayton7b242382011-07-08 00:48:09 +0000640
Greg Clayton0d9fc762011-07-08 03:21:57 +0000641 size_t load_cmd_bytes_read = m_process->GetTarget().ReadMemory (load_cmd_addr,
642 prefer_file_cache,
643 load_cmd_data_sp->GetBytes(),
644 load_cmd_data_sp->GetByteSize(),
645 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000646
Greg Clayton0d9fc762011-07-08 03:21:57 +0000647 if (load_cmd_bytes_read == kext_summary.header.sizeofcmds)
Greg Clayton7b242382011-07-08 00:48:09 +0000648 {
649 // Set the load command data and also set the correct endian
650 // swap settings and the correct address size
Greg Clayton0d9fc762011-07-08 03:21:57 +0000651 load_command_data->SetData(load_cmd_data_sp, 0, kext_summary.header.sizeofcmds);
Greg Clayton7b242382011-07-08 00:48:09 +0000652 load_command_data->SetByteOrder(data.GetByteOrder());
653 load_command_data->SetAddressByteSize(data.GetAddressByteSize());
654 return true; // We successfully read the mach_header and the load command data
655 }
656
657 return false; // We weren't able to read the load command data
658 }
659 }
660 return false; // We failed the read the mach_header
661}
662
663
664//----------------------------------------------------------------------
665// Parse the load commands for an image
666//----------------------------------------------------------------------
667uint32_t
668DynamicLoaderMacOSXKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& dylib_info)
669{
670 uint32_t offset = 0;
671 uint32_t cmd_idx;
672 Segment segment;
673 dylib_info.Clear (true);
674
675 for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++)
676 {
677 // Clear out any load command specific data from DYLIB_INFO since
678 // we are about to read it.
679
680 if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
681 {
682 llvm::MachO::load_command load_cmd;
683 uint32_t load_cmd_offset = offset;
684 load_cmd.cmd = data.GetU32 (&offset);
685 load_cmd.cmdsize = data.GetU32 (&offset);
686 switch (load_cmd.cmd)
687 {
688 case llvm::MachO::LoadCommandSegment32:
689 {
690 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
691 // We are putting 4 uint32_t values 4 uint64_t values so
692 // we have to use multiple 32 bit gets below.
693 segment.vmaddr = data.GetU32 (&offset);
694 segment.vmsize = data.GetU32 (&offset);
695 segment.fileoff = data.GetU32 (&offset);
696 segment.filesize = data.GetU32 (&offset);
697 // Extract maxprot, initprot, nsects and flags all at once
698 data.GetU32(&offset, &segment.maxprot, 4);
699 dylib_info.segments.push_back (segment);
700 }
701 break;
702
703 case llvm::MachO::LoadCommandSegment64:
704 {
705 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
706 // Extract vmaddr, vmsize, fileoff, and filesize all at once
707 data.GetU64(&offset, &segment.vmaddr, 4);
708 // Extract maxprot, initprot, nsects and flags all at once
709 data.GetU32(&offset, &segment.maxprot, 4);
710 dylib_info.segments.push_back (segment);
711 }
712 break;
713
714 case llvm::MachO::LoadCommandUUID:
715 dylib_info.uuid.SetBytes(data.GetData (&offset, 16));
716 break;
717
718 default:
719 break;
720 }
721 // Set offset to be the beginning of the next load command.
722 offset = load_cmd_offset + load_cmd.cmdsize;
723 }
724 }
725#if 0
726 // No slide in the kernel...
727
728 // All sections listed in the dyld image info structure will all
729 // either be fixed up already, or they will all be off by a single
730 // slide amount that is determined by finding the first segment
731 // that is at file offset zero which also has bytes (a file size
732 // that is greater than zero) in the object file.
733
734 // Determine the slide amount (if any)
735 const size_t num_sections = dylib_info.segments.size();
736 for (size_t i = 0; i < num_sections; ++i)
737 {
738 // Iterate through the object file sections to find the
739 // first section that starts of file offset zero and that
740 // has bytes in the file...
741 if (dylib_info.segments[i].fileoff == 0 && dylib_info.segments[i].filesize > 0)
742 {
743 dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
744 // We have found the slide amount, so we can exit
745 // this for loop.
746 break;
747 }
748 }
749#endif
750 return cmd_idx;
751}
752
753//----------------------------------------------------------------------
754// Dump a Segment to the file handle provided.
755//----------------------------------------------------------------------
756void
757DynamicLoaderMacOSXKernel::Segment::PutToLog (Log *log, lldb::addr_t slide) const
758{
759 if (log)
760 {
761 if (slide == 0)
762 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)",
763 name.AsCString(""),
764 vmaddr + slide,
765 vmaddr + slide + vmsize);
766 else
767 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx",
768 name.AsCString(""),
769 vmaddr + slide,
770 vmaddr + slide + vmsize,
771 slide);
772 }
773}
774
775const DynamicLoaderMacOSXKernel::Segment *
776DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::FindSegment (const ConstString &name) const
777{
778 const size_t num_segments = segments.size();
779 for (size_t i=0; i<num_segments; ++i)
780 {
781 if (segments[i].name == name)
782 return &segments[i];
783 }
784 return NULL;
785}
786
787
788//----------------------------------------------------------------------
789// Dump an image info structure to the file handle provided.
790//----------------------------------------------------------------------
791void
792DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
793{
794 if (log == NULL)
795 return;
796 uint8_t *u = (uint8_t *)uuid.GetBytes();
797//
798// char name[KERNEL_MODULE_MAX_NAME];
799// lldb::ModuleSP module_sp;
800// lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
801// uint64_t address;
802// uint64_t size;
803// uint64_t version;
804// uint32_t load_tag;
805// uint32_t flags;
806// uint64_t reference_list;
807// llvm::MachO::mach_header header; // The mach header for this image
808// std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
809
810 if (address == LLDB_INVALID_ADDRESS)
811 {
812 if (u)
813 {
814 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)",
815 u[ 0], u[ 1], u[ 2], u[ 3],
816 u[ 4], u[ 5], u[ 6], u[ 7],
817 u[ 8], u[ 9], u[10], u[11],
818 u[12], u[13], u[14], u[15],
819 name);
820 }
821 else
822 log->Printf("\t name='%s' (UNLOADED)", name);
823 }
824 else
825 {
826 if (u)
827 {
828 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'",
829 address,
830 u[ 0], u[ 1], u[ 2], u[ 3],
831 u[ 4], u[ 5], u[ 6], u[ 7],
832 u[ 8], u[ 9], u[10], u[11],
833 u[12], u[13], u[14], u[15],
834 name);
835 }
836 else
837 {
838 log->Printf("\taddress=0x%16.16llx path='%s/%s'", address, name);
839 }
840 for (uint32_t i=0; i<segments.size(); ++i)
841 segments[i].PutToLog(log, 0);
842 }
843}
844
845//----------------------------------------------------------------------
846// Dump the _dyld_all_image_infos members and all current image infos
847// that we have parsed to the file handle provided.
848//----------------------------------------------------------------------
849void
850DynamicLoaderMacOSXKernel::PutToLog(Log *log) const
851{
852 if (log == NULL)
853 return;
854
855 Mutex::Locker locker(m_mutex);
856 log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u, reserved=%u }",
Greg Clayton0d9fc762011-07-08 03:21:57 +0000857 m_kext_summary_header_addr.GetFileAddress(),
Greg Clayton7b242382011-07-08 00:48:09 +0000858 m_kext_summary_header.version,
859 m_kext_summary_header.entry_size,
860 m_kext_summary_header.entry_count,
861 m_kext_summary_header.reserved);
862
863 size_t i;
864 const size_t count = m_kext_summaries.size();
865 if (count > 0)
866 {
867 log->PutCString("Loaded:");
868 for (i = 0; i<count; i++)
869 m_kext_summaries[i].PutToLog(log);
870 }
871}
872
873void
874DynamicLoaderMacOSXKernel::PrivateInitialize(Process *process)
875{
876 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
877 Clear(true);
878 m_process = process;
879 m_process->GetTarget().GetSectionLoadList().Clear();
880}
881
882bool
883DynamicLoaderMacOSXKernel::SetNotificationBreakpoint ()
884{
885 // TODO: Add breakpoint to detected dynamic kext loads/unloads. We aren't
886 // doing any live dynamic checks for kernel kexts being loaded or unloaded
887 // on the fly yet.
888// DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
889// if (m_break_id == LLDB_INVALID_BREAK_ID)
890// {
891// if (m_kext_summaries.notification != LLDB_INVALID_ADDRESS)
892// {
893// Address so_addr;
894// // Set the notification breakpoint and install a breakpoint
895// // callback function that will get called each time the
896// // breakpoint gets hit. We will use this to track when shared
897// // libraries get loaded/unloaded.
898//
899// if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_kext_summaries.notification, so_addr))
900// {
901// Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
902// dyld_break->SetCallback (DynamicLoaderMacOSXKernel::NotifyBreakpointHit, this, true);
903// m_break_id = dyld_break->GetID();
904// }
905// }
906// }
907 return m_break_id != LLDB_INVALID_BREAK_ID;
908}
909
910//----------------------------------------------------------------------
911// Member function that gets called when the process state changes.
912//----------------------------------------------------------------------
913void
914DynamicLoaderMacOSXKernel::PrivateProcessStateChanged (Process *process, StateType state)
915{
916 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s(%s)\n", __FUNCTION__, StateAsCString(state));
917 switch (state)
918 {
919 case eStateConnected:
920 case eStateAttaching:
921 case eStateLaunching:
922 case eStateInvalid:
923 case eStateUnloaded:
924 case eStateExited:
925 case eStateDetached:
926 Clear(false);
927 break;
928
929 case eStateStopped:
930 // Keep trying find dyld and set our notification breakpoint each time
931 // we stop until we succeed
932 if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
933 {
934 if (LoadKernelModule())
935 {
936 }
937
938 SetNotificationBreakpoint ();
939 }
940 break;
941
942 case eStateRunning:
943 case eStateStepping:
944 case eStateCrashed:
945 case eStateSuspended:
946 break;
947
948 default:
949 break;
950 }
951}
952
953ThreadPlanSP
954DynamicLoaderMacOSXKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
955{
956 ThreadPlanSP thread_plan_sp;
957 StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
958 const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
959 Symbol *current_symbol = current_context.symbol;
960 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
961
962 if (current_symbol != NULL)
963 {
964 if (current_symbol->IsTrampoline())
965 {
966 const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
967
968 if (trampoline_name)
969 {
970 SymbolContextList target_symbols;
971 ModuleList &images = thread.GetProcess().GetTarget().GetImages();
972 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
973 // FIXME - Make the Run to Address take multiple addresses, and
974 // run to any of them.
975 uint32_t num_symbols = target_symbols.GetSize();
976 if (num_symbols == 1)
977 {
978 SymbolContext context;
979 AddressRange addr_range;
980 if (target_symbols.GetContextAtIndex(0, context))
981 {
982 context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
983 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others));
984 }
985 else
986 {
987 if (log)
988 log->Printf ("Couldn't resolve the symbol context.");
989 }
990 }
991 else if (num_symbols > 1)
992 {
993 std::vector<lldb::addr_t> addresses;
994 addresses.resize (num_symbols);
995 for (uint32_t i = 0; i < num_symbols; i++)
996 {
997 SymbolContext context;
998 AddressRange addr_range;
999 if (target_symbols.GetContextAtIndex(i, context))
1000 {
1001 context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1002 lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
1003 addresses[i] = load_addr;
1004 }
1005 }
1006 if (addresses.size() > 0)
1007 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others));
1008 else
1009 {
1010 if (log)
1011 log->Printf ("Couldn't resolve the symbol contexts.");
1012 }
1013 }
1014 else
1015 {
1016 if (log)
1017 {
1018 log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
1019 }
1020 }
1021 }
1022 }
1023 }
1024 else
1025 {
1026 if (log)
1027 log->Printf ("Could not find symbol for step through.");
1028 }
1029
1030 return thread_plan_sp;
1031}
1032
1033Error
1034DynamicLoaderMacOSXKernel::CanLoadImage ()
1035{
1036 Error error;
1037 error.SetErrorString("always unsafe to load or unload shared libraries in the darwin kernel");
1038 return error;
1039}
1040
1041void
1042DynamicLoaderMacOSXKernel::Initialize()
1043{
1044 PluginManager::RegisterPlugin (GetPluginNameStatic(),
1045 GetPluginDescriptionStatic(),
1046 CreateInstance);
1047}
1048
1049void
1050DynamicLoaderMacOSXKernel::Terminate()
1051{
1052 PluginManager::UnregisterPlugin (CreateInstance);
1053}
1054
1055
1056const char *
1057DynamicLoaderMacOSXKernel::GetPluginNameStatic()
1058{
1059 return "dynamic-loader.macosx-kernel";
1060}
1061
1062const char *
1063DynamicLoaderMacOSXKernel::GetPluginDescriptionStatic()
1064{
1065 return "Dynamic loader plug-in that watches for shared library loads/unloads in the MacOSX kernel.";
1066}
1067
1068
1069//------------------------------------------------------------------
1070// PluginInterface protocol
1071//------------------------------------------------------------------
1072const char *
1073DynamicLoaderMacOSXKernel::GetPluginName()
1074{
1075 return "DynamicLoaderMacOSXKernel";
1076}
1077
1078const char *
1079DynamicLoaderMacOSXKernel::GetShortPluginName()
1080{
1081 return GetPluginNameStatic();
1082}
1083
1084uint32_t
1085DynamicLoaderMacOSXKernel::GetPluginVersion()
1086{
1087 return 1;
1088}
1089