blob: 609e6fc2c3a967696ad853fd01dbe4e13f578aa9 [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 Claytond16e1e52011-07-12 17:06:17 +000090 m_kext_summary_header_ptr_addr (),
Greg Clayton0d9fc762011-07-08 03:21:57 +000091 m_kext_summary_header_addr (),
Greg Clayton7b242382011-07-08 00:48:09 +000092 m_kext_summary_header (),
Greg Clayton7b242382011-07-08 00:48:09 +000093 m_break_id (LLDB_INVALID_BREAK_ID),
94 m_kext_summaries(),
Greg Clayton374972e2011-07-09 17:15:55 +000095 m_mutex(Mutex::eMutexTypeRecursive)
Greg Clayton7b242382011-07-08 00:48:09 +000096{
97}
98
99//----------------------------------------------------------------------
100// Destructor
101//----------------------------------------------------------------------
102DynamicLoaderMacOSXKernel::~DynamicLoaderMacOSXKernel()
103{
104 Clear(true);
105}
106
Greg Clayton374972e2011-07-09 17:15:55 +0000107void
108DynamicLoaderMacOSXKernel::UpdateIfNeeded()
109{
110 LoadKernelModuleIfNeeded();
111 SetNotificationBreakpointIfNeeded ();
112}
Greg Clayton7b242382011-07-08 00:48:09 +0000113//------------------------------------------------------------------
114/// Called after attaching a process.
115///
116/// Allow DynamicLoader plug-ins to execute some code after
117/// attaching to a process.
118//------------------------------------------------------------------
119void
120DynamicLoaderMacOSXKernel::DidAttach ()
121{
122 PrivateInitialize(m_process);
Greg Clayton374972e2011-07-09 17:15:55 +0000123 UpdateIfNeeded();
Greg Clayton7b242382011-07-08 00:48:09 +0000124}
125
126//------------------------------------------------------------------
127/// Called after attaching a process.
128///
129/// Allow DynamicLoader plug-ins to execute some code after
130/// attaching to a process.
131//------------------------------------------------------------------
132void
133DynamicLoaderMacOSXKernel::DidLaunch ()
134{
135 PrivateInitialize(m_process);
Greg Clayton374972e2011-07-09 17:15:55 +0000136 UpdateIfNeeded();
Greg Clayton7b242382011-07-08 00:48:09 +0000137}
138
139
140//----------------------------------------------------------------------
141// Clear out the state of this class.
142//----------------------------------------------------------------------
143void
144DynamicLoaderMacOSXKernel::Clear (bool clear_process)
145{
146 Mutex::Locker locker(m_mutex);
147
148 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
149 m_process->ClearBreakpointSiteByID(m_break_id);
150
151 if (clear_process)
152 m_process = NULL;
153 m_kernel.Clear(false);
Greg Claytond16e1e52011-07-12 17:06:17 +0000154 m_kext_summary_header_ptr_addr.Clear();
Greg Clayton0d9fc762011-07-08 03:21:57 +0000155 m_kext_summary_header_addr.Clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000156 m_kext_summaries.clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000157 m_break_id = LLDB_INVALID_BREAK_ID;
158}
159
Greg Clayton7b242382011-07-08 00:48:09 +0000160
161//----------------------------------------------------------------------
162// Load the kernel module and initialize the "m_kernel" member. Return
163// true _only_ if the kernel is loaded the first time through (subsequent
164// calls to this function should return false after the kernel has been
165// already loaded).
166//----------------------------------------------------------------------
Greg Clayton374972e2011-07-09 17:15:55 +0000167void
168DynamicLoaderMacOSXKernel::LoadKernelModuleIfNeeded()
Greg Clayton7b242382011-07-08 00:48:09 +0000169{
Greg Claytond16e1e52011-07-12 17:06:17 +0000170 if (!m_kext_summary_header_ptr_addr.IsValid())
Greg Clayton7b242382011-07-08 00:48:09 +0000171 {
172 m_kernel.Clear(false);
173 m_kernel.module_sp = m_process->GetTarget().GetExecutableModule();
174 if (m_kernel.module_sp)
175 {
176 static ConstString mach_header_name ("_mh_execute_header");
Greg Claytondf0b7d52011-07-08 04:11:42 +0000177 static ConstString kext_summary_symbol ("gLoadedKextSummaries");
178 const Symbol *symbol = NULL;
179 symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData);
180 if (symbol)
Greg Claytond16e1e52011-07-12 17:06:17 +0000181 m_kext_summary_header_ptr_addr = symbol->GetValue();
Greg Claytondf0b7d52011-07-08 04:11:42 +0000182
183 symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute);
Greg Clayton7b242382011-07-08 00:48:09 +0000184 if (symbol)
185 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000186 // The "_mh_execute_header" symbol is absolute and not a section based
187 // symbol that will have a valid address, so we need to resolve it...
188 m_process->GetTarget().GetImages().ResolveFileAddress (symbol->GetValue().GetFileAddress(), m_kernel.so_address);
Greg Clayton7b242382011-07-08 00:48:09 +0000189 DataExtractor data; // Load command data
Greg Clayton0d9fc762011-07-08 03:21:57 +0000190 if (ReadMachHeader (m_kernel, &data))
Greg Clayton7b242382011-07-08 00:48:09 +0000191 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000192 if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeExecutable)
Greg Clayton7b242382011-07-08 00:48:09 +0000193 {
194 if (ParseLoadCommands (data, m_kernel))
195 UpdateImageLoadAddress (m_kernel);
196
197 // Update all image infos
Greg Clayton374972e2011-07-09 17:15:55 +0000198 ReadAllKextSummaries ();
Greg Clayton7b242382011-07-08 00:48:09 +0000199 }
200 }
201 else
202 {
203 m_kernel.Clear(false);
204 }
Greg Clayton7b242382011-07-08 00:48:09 +0000205 }
206 }
207 }
Greg Clayton7b242382011-07-08 00:48:09 +0000208}
209
210bool
211DynamicLoaderMacOSXKernel::FindTargetModule (OSKextLoadedKextSummary &image_info, bool can_create, bool *did_create_ptr)
212{
213 if (did_create_ptr)
214 *did_create_ptr = false;
215
216 const bool image_info_uuid_is_valid = image_info.uuid.IsValid();
217
218 if (image_info.module_sp)
219 {
220 if (image_info_uuid_is_valid)
221 {
222 if (image_info.module_sp->GetUUID() == image_info.uuid)
223 return true;
224 else
225 image_info.module_sp.reset();
226 }
227 else
228 return true;
229 }
230
231 ModuleList &target_images = m_process->GetTarget().GetImages();
232 if (image_info_uuid_is_valid)
233 image_info.module_sp = target_images.FindModule(image_info.uuid);
234
235 if (image_info.module_sp)
236 return true;
237
238 ArchSpec arch (image_info.GetArchitecture ());
239 if (can_create)
240 {
241 if (image_info_uuid_is_valid)
242 {
243 image_info.module_sp = m_process->GetTarget().GetSharedModule (FileSpec(),
244 arch,
245 &image_info.uuid);
246 if (did_create_ptr)
247 *did_create_ptr = image_info.module_sp;
248 }
249 }
250 return image_info.module_sp;
251}
252
253bool
254DynamicLoaderMacOSXKernel::UpdateCommPageLoadAddress(Module *module)
255{
256 bool changed = false;
257 if (module)
258 {
259 ObjectFile *image_object_file = module->GetObjectFile();
260 if (image_object_file)
261 {
262 SectionList *section_list = image_object_file->GetSectionList ();
263 if (section_list)
264 {
265 uint32_t num_sections = section_list->GetSize();
266 for (uint32_t i=0; i<num_sections; ++i)
267 {
268 Section* section = section_list->GetSectionAtIndex (i).get();
269 if (section)
270 {
271 const addr_t new_section_load_addr = section->GetFileAddress ();
272 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section);
273 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
274 old_section_load_addr != new_section_load_addr)
275 {
276 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ()))
277 changed = true;
278 }
279 }
280 }
281 }
282 }
283 }
284 return changed;
285}
286
287//----------------------------------------------------------------------
288// Update the load addresses for all segments in MODULE using the
289// updated INFO that is passed in.
290//----------------------------------------------------------------------
291bool
292DynamicLoaderMacOSXKernel::UpdateImageLoadAddress (OSKextLoadedKextSummary& info)
293{
294 Module *module = info.module_sp.get();
295 bool changed = false;
296 if (module)
297 {
298 ObjectFile *image_object_file = module->GetObjectFile();
299 if (image_object_file)
300 {
301 SectionList *section_list = image_object_file->GetSectionList ();
302 if (section_list)
303 {
304 // We now know the slide amount, so go through all sections
305 // and update the load addresses with the correct values.
306 uint32_t num_segments = info.segments.size();
307 for (uint32_t i=0; i<num_segments; ++i)
308 {
309 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
310 const addr_t new_section_load_addr = info.segments[i].vmaddr;
311 if (section_sp)
312 {
313 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
314 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
315 old_section_load_addr != new_section_load_addr)
316 {
317 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
318 changed = true;
319 }
320 }
321 else
322 {
323 fprintf (stderr,
324 "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
325 info.segments[i].name.AsCString("<invalid>"),
326 (uint64_t)new_section_load_addr,
327 image_object_file->GetFileSpec().GetDirectory().AsCString(),
328 image_object_file->GetFileSpec().GetFilename().AsCString());
329 }
330 }
331 }
332 }
333 }
334 return changed;
335}
336
337//----------------------------------------------------------------------
338// Update the load addresses for all segments in MODULE using the
339// updated INFO that is passed in.
340//----------------------------------------------------------------------
341bool
342DynamicLoaderMacOSXKernel::UnloadImageLoadAddress (OSKextLoadedKextSummary& info)
343{
344 Module *module = info.module_sp.get();
345 bool changed = false;
346 if (module)
347 {
348 ObjectFile *image_object_file = module->GetObjectFile();
349 if (image_object_file)
350 {
351 SectionList *section_list = image_object_file->GetSectionList ();
352 if (section_list)
353 {
354 uint32_t num_segments = info.segments.size();
355 for (uint32_t i=0; i<num_segments; ++i)
356 {
357 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
358 if (section_sp)
359 {
360 const addr_t old_section_load_addr = info.segments[i].vmaddr;
361 if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
362 changed = true;
363 }
364 else
365 {
366 fprintf (stderr,
367 "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n",
368 info.segments[i].name.AsCString("<invalid>"),
369 image_object_file->GetFileSpec().GetDirectory().AsCString(),
370 image_object_file->GetFileSpec().GetFilename().AsCString());
371 }
372 }
373 }
374 }
375 }
376 return changed;
377}
378
379
380//----------------------------------------------------------------------
381// Static callback function that gets called when our DYLD notification
382// breakpoint gets hit. We update all of our image infos and then
383// let our super class DynamicLoader class decide if we should stop
384// or not (based on global preference).
385//----------------------------------------------------------------------
386bool
Greg Clayton374972e2011-07-09 17:15:55 +0000387DynamicLoaderMacOSXKernel::BreakpointHitCallback (void *baton,
388 StoppointCallbackContext *context,
389 user_id_t break_id,
390 user_id_t break_loc_id)
Greg Clayton0d9fc762011-07-08 03:21:57 +0000391{
Greg Clayton374972e2011-07-09 17:15:55 +0000392 return static_cast<DynamicLoaderMacOSXKernel*>(baton)->BreakpointHit (context, break_id, break_loc_id);
Greg Clayton7b242382011-07-08 00:48:09 +0000393}
394
395bool
Greg Clayton374972e2011-07-09 17:15:55 +0000396DynamicLoaderMacOSXKernel::BreakpointHit (StoppointCallbackContext *context,
397 user_id_t break_id,
398 user_id_t break_loc_id)
399{
Greg Claytond16e1e52011-07-12 17:06:17 +0000400 LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
401 if (log)
402 log->Printf ("DynamicLoaderMacOSXKernel::BreakpointHit (...)\n");
403
Greg Clayton374972e2011-07-09 17:15:55 +0000404 ReadAllKextSummaries ();
Greg Claytond16e1e52011-07-12 17:06:17 +0000405
406 if (log)
407 PutToLog(log.get());
408
Greg Clayton374972e2011-07-09 17:15:55 +0000409 return GetStopWhenImagesChange();
410}
411
412
413bool
Greg Clayton7b242382011-07-08 00:48:09 +0000414DynamicLoaderMacOSXKernel::ReadKextSummaryHeader ()
415{
416 Mutex::Locker locker(m_mutex);
417
418 // the all image infos is already valid for this process stop ID
Greg Clayton7b242382011-07-08 00:48:09 +0000419
420 m_kext_summaries.clear();
Greg Claytond16e1e52011-07-12 17:06:17 +0000421 if (m_kext_summary_header_ptr_addr.IsValid())
Greg Clayton7b242382011-07-08 00:48:09 +0000422 {
423 const uint32_t addr_size = m_kernel.GetAddressByteSize ();
424 const ByteOrder byte_order = m_kernel.GetByteOrder();
425 Error error;
426 // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure
427 // which is currenty 4 uint32_t and a pointer.
428 uint8_t buf[24];
429 DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
430 const size_t count = 4 * sizeof(uint32_t) + addr_size;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000431 const bool prefer_file_cache = false;
Greg Claytond16e1e52011-07-12 17:06:17 +0000432 if (m_process->GetTarget().ReadPointerFromMemory (m_kext_summary_header_ptr_addr,
433 prefer_file_cache,
434 error,
435 m_kext_summary_header_addr))
Greg Clayton7b242382011-07-08 00:48:09 +0000436 {
Greg Claytond16e1e52011-07-12 17:06:17 +0000437 // We got a valid address for our kext summary header and make sure it isn't NULL
438 if (m_kext_summary_header_addr.IsValid() &&
439 m_kext_summary_header_addr.GetFileAddress() != 0)
440 {
441 const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error);
442 if (bytes_read == count)
443 {
444 uint32_t offset = 0;
445 m_kext_summary_header.version = data.GetU32(&offset);
446 m_kext_summary_header.entry_size = data.GetU32(&offset);
447 m_kext_summary_header.entry_count = data.GetU32(&offset);
448 m_kext_summary_header.reserved = data.GetU32(&offset);
449 return true;
450 }
451 }
Greg Clayton7b242382011-07-08 00:48:09 +0000452 }
453 }
Greg Claytond16e1e52011-07-12 17:06:17 +0000454 m_kext_summary_header_addr.Clear();
Greg Clayton7b242382011-07-08 00:48:09 +0000455 return false;
456}
457
458
459bool
Greg Clayton374972e2011-07-09 17:15:55 +0000460DynamicLoaderMacOSXKernel::ParseKextSummaries (const Address &kext_summary_addr,
Greg Clayton0d9fc762011-07-08 03:21:57 +0000461 uint32_t count)
Greg Clayton7b242382011-07-08 00:48:09 +0000462{
463 OSKextLoadedKextSummary::collection kext_summaries;
Greg Clayton374972e2011-07-09 17:15:55 +0000464 LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
Greg Clayton7b242382011-07-08 00:48:09 +0000465 if (log)
466 log->Printf ("Adding %d modules.\n");
467
468 Mutex::Locker locker(m_mutex);
Greg Clayton7b242382011-07-08 00:48:09 +0000469
470 if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
471 return false;
472
473 for (uint32_t i = 0; i < count; i++)
474 {
475 if (!kext_summaries[i].UUIDValid())
476 {
477 DataExtractor data; // Load command data
Greg Clayton0d9fc762011-07-08 03:21:57 +0000478 if (!ReadMachHeader (kext_summaries[i], &data))
Greg Clayton7b242382011-07-08 00:48:09 +0000479 continue;
480
481 ParseLoadCommands (data, kext_summaries[i]);
482 }
483 }
484 bool return_value = AddModulesUsingImageInfos (kext_summaries);
Greg Clayton7b242382011-07-08 00:48:09 +0000485 return return_value;
486}
487
488// Adds the modules in image_infos to m_kext_summaries.
489// NB don't call this passing in m_kext_summaries.
490
491bool
492DynamicLoaderMacOSXKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos)
493{
494 // Now add these images to the main list.
495 ModuleList loaded_module_list;
Greg Clayton7b242382011-07-08 00:48:09 +0000496
497 for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
498 {
Greg Clayton7b242382011-07-08 00:48:09 +0000499 m_kext_summaries.push_back(image_infos[idx]);
500
501 if (FindTargetModule (image_infos[idx], true, NULL))
502 {
503 // UpdateImageLoadAddress will return true if any segments
504 // change load address. We need to check this so we don't
505 // mention that all loaded shared libraries are newly loaded
506 // each time we hit out dyld breakpoint since dyld will list all
507 // shared libraries each time.
508 if (UpdateImageLoadAddress (image_infos[idx]))
509 {
510 loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
511 }
512 }
513 }
514
515 if (loaded_module_list.GetSize() > 0)
516 {
517 // FIXME: This should really be in the Runtime handlers class, which should get
518 // called by the target's ModulesDidLoad, but we're doing it all locally for now
519 // to save time.
520 // Also, I'm assuming there can be only one libobjc dylib loaded...
521
522 ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
523 if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
524 {
525 size_t num_modules = loaded_module_list.GetSize();
526 for (int i = 0; i < num_modules; i++)
527 {
528 if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
529 {
530 objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
531 break;
532 }
533 }
534 }
Greg Claytond16e1e52011-07-12 17:06:17 +0000535// if (log)
536// loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidLoad");
Greg Clayton7b242382011-07-08 00:48:09 +0000537 m_process->GetTarget().ModulesDidLoad (loaded_module_list);
538 }
539 return true;
540}
541
Greg Clayton7b242382011-07-08 00:48:09 +0000542
543uint32_t
Greg Clayton374972e2011-07-09 17:15:55 +0000544DynamicLoaderMacOSXKernel::ReadKextSummaries (const Address &kext_summary_addr,
Greg Clayton7b242382011-07-08 00:48:09 +0000545 uint32_t image_infos_count,
546 OSKextLoadedKextSummary::collection &image_infos)
547{
548 const ByteOrder endian = m_kernel.GetByteOrder();
549 const uint32_t addr_size = m_kernel.GetAddressByteSize();
550
551 image_infos.resize(image_infos_count);
552 const size_t count = image_infos.size() * m_kext_summary_header.entry_size;
553 DataBufferHeap data(count, 0);
554 Error error;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000555 const bool prefer_file_cache = false;
556 const size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary_addr,
557 prefer_file_cache,
558 data.GetBytes(),
559 data.GetByteSize(),
560 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000561 if (bytes_read == count)
562 {
563 uint32_t offset = 0;
564 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size);
565 uint32_t i=0;
566 for (; i < image_infos.size() && extractor.ValidOffsetForDataOfSize(offset, m_kext_summary_header.entry_size); ++i)
567 {
568 const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
569 if (name_data == NULL)
570 break;
571 memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME);
572 image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16));
573 image_infos[i].address = extractor.GetU64(&offset);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000574 if (!image_infos[i].so_address.SetLoadAddress (image_infos[i].address, &m_process->GetTarget()))
575 m_process->GetTarget().GetImages().ResolveFileAddress (image_infos[i].address, image_infos[i].so_address);
Greg Clayton7b242382011-07-08 00:48:09 +0000576 image_infos[i].size = extractor.GetU64(&offset);
577 image_infos[i].version = extractor.GetU64(&offset);
578 image_infos[i].load_tag = extractor.GetU32(&offset);
579 image_infos[i].flags = extractor.GetU32(&offset);
580 image_infos[i].reference_list = extractor.GetU64(&offset);
581 }
582 if (i < image_infos.size())
583 image_infos.resize(i);
584 }
585 else
586 {
587 image_infos.clear();
588 }
589 return image_infos.size();
590}
591
592bool
Greg Clayton374972e2011-07-09 17:15:55 +0000593DynamicLoaderMacOSXKernel::ReadAllKextSummaries ()
Greg Clayton7b242382011-07-08 00:48:09 +0000594{
Greg Clayton374972e2011-07-09 17:15:55 +0000595 LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
Greg Clayton7b242382011-07-08 00:48:09 +0000596
597 Mutex::Locker locker(m_mutex);
Greg Clayton374972e2011-07-09 17:15:55 +0000598
Greg Clayton7b242382011-07-08 00:48:09 +0000599 if (ReadKextSummaryHeader ())
600 {
Greg Clayton374972e2011-07-09 17:15:55 +0000601 if (m_kext_summary_header.entry_count > 0 && m_kext_summary_header_addr.IsValid())
Greg Clayton7b242382011-07-08 00:48:09 +0000602 {
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 {
Greg Clayton7b242382011-07-08 00:48:09 +0000607 m_kext_summaries.clear();
608 }
609 return true;
610 }
611 }
612 return false;
613}
614
615//----------------------------------------------------------------------
616// Read a mach_header at ADDR into HEADER, and also fill in the load
617// command data into LOAD_COMMAND_DATA if it is non-NULL.
618//
619// Returns true if we succeed, false if we fail for any reason.
620//----------------------------------------------------------------------
621bool
Greg Clayton0d9fc762011-07-08 03:21:57 +0000622DynamicLoaderMacOSXKernel::ReadMachHeader (OSKextLoadedKextSummary& kext_summary, DataExtractor *load_command_data)
Greg Clayton7b242382011-07-08 00:48:09 +0000623{
624 DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
625 Error error;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000626 const bool prefer_file_cache = false;
627 size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary.so_address,
628 prefer_file_cache,
629 header_bytes.GetBytes(),
630 header_bytes.GetByteSize(),
631 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000632 if (bytes_read == sizeof(llvm::MachO::mach_header))
633 {
634 uint32_t offset = 0;
Greg Clayton0d9fc762011-07-08 03:21:57 +0000635 ::memset (&kext_summary.header, 0, sizeof(kext_summary.header));
Greg Clayton7b242382011-07-08 00:48:09 +0000636
637 // Get the magic byte unswapped so we can figure out what we are dealing with
Greg Clayton374972e2011-07-09 17:15:55 +0000638 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), endian::InlHostByteOrder(), 4);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000639 kext_summary.header.magic = data.GetU32(&offset);
640 Address load_cmd_addr = kext_summary.so_address;
641 data.SetByteOrder(DynamicLoaderMacOSXKernel::GetByteOrderFromMagic(kext_summary.header.magic));
642 switch (kext_summary.header.magic)
Greg Clayton7b242382011-07-08 00:48:09 +0000643 {
644 case llvm::MachO::HeaderMagic32:
645 case llvm::MachO::HeaderMagic32Swapped:
646 data.SetAddressByteSize(4);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000647 load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header));
Greg Clayton7b242382011-07-08 00:48:09 +0000648 break;
649
650 case llvm::MachO::HeaderMagic64:
651 case llvm::MachO::HeaderMagic64Swapped:
652 data.SetAddressByteSize(8);
Greg Clayton0d9fc762011-07-08 03:21:57 +0000653 load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header_64));
Greg Clayton7b242382011-07-08 00:48:09 +0000654 break;
655
656 default:
657 return false;
658 }
659
660 // Read the rest of dyld's mach header
Greg Clayton0d9fc762011-07-08 03:21:57 +0000661 if (data.GetU32(&offset, &kext_summary.header.cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
Greg Clayton7b242382011-07-08 00:48:09 +0000662 {
663 if (load_command_data == NULL)
664 return true; // We were able to read the mach_header and weren't asked to read the load command bytes
665
Greg Clayton0d9fc762011-07-08 03:21:57 +0000666 DataBufferSP load_cmd_data_sp(new DataBufferHeap(kext_summary.header.sizeofcmds, 0));
Greg Clayton7b242382011-07-08 00:48:09 +0000667
Greg Clayton0d9fc762011-07-08 03:21:57 +0000668 size_t load_cmd_bytes_read = m_process->GetTarget().ReadMemory (load_cmd_addr,
669 prefer_file_cache,
670 load_cmd_data_sp->GetBytes(),
671 load_cmd_data_sp->GetByteSize(),
672 error);
Greg Clayton7b242382011-07-08 00:48:09 +0000673
Greg Clayton0d9fc762011-07-08 03:21:57 +0000674 if (load_cmd_bytes_read == kext_summary.header.sizeofcmds)
Greg Clayton7b242382011-07-08 00:48:09 +0000675 {
676 // Set the load command data and also set the correct endian
677 // swap settings and the correct address size
Greg Clayton0d9fc762011-07-08 03:21:57 +0000678 load_command_data->SetData(load_cmd_data_sp, 0, kext_summary.header.sizeofcmds);
Greg Clayton7b242382011-07-08 00:48:09 +0000679 load_command_data->SetByteOrder(data.GetByteOrder());
680 load_command_data->SetAddressByteSize(data.GetAddressByteSize());
681 return true; // We successfully read the mach_header and the load command data
682 }
683
684 return false; // We weren't able to read the load command data
685 }
686 }
687 return false; // We failed the read the mach_header
688}
689
690
691//----------------------------------------------------------------------
692// Parse the load commands for an image
693//----------------------------------------------------------------------
694uint32_t
Greg Claytondf0b7d52011-07-08 04:11:42 +0000695DynamicLoaderMacOSXKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& image_info)
Greg Clayton7b242382011-07-08 00:48:09 +0000696{
697 uint32_t offset = 0;
698 uint32_t cmd_idx;
699 Segment segment;
Greg Claytondf0b7d52011-07-08 04:11:42 +0000700 image_info.Clear (true);
Greg Clayton7b242382011-07-08 00:48:09 +0000701
Greg Claytondf0b7d52011-07-08 04:11:42 +0000702 for (cmd_idx = 0; cmd_idx < image_info.header.ncmds; cmd_idx++)
Greg Clayton7b242382011-07-08 00:48:09 +0000703 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000704 // Clear out any load command specific data from image_info since
Greg Clayton7b242382011-07-08 00:48:09 +0000705 // we are about to read it.
706
707 if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
708 {
709 llvm::MachO::load_command load_cmd;
710 uint32_t load_cmd_offset = offset;
711 load_cmd.cmd = data.GetU32 (&offset);
712 load_cmd.cmdsize = data.GetU32 (&offset);
713 switch (load_cmd.cmd)
714 {
715 case llvm::MachO::LoadCommandSegment32:
716 {
717 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
718 // We are putting 4 uint32_t values 4 uint64_t values so
719 // we have to use multiple 32 bit gets below.
720 segment.vmaddr = data.GetU32 (&offset);
721 segment.vmsize = data.GetU32 (&offset);
722 segment.fileoff = data.GetU32 (&offset);
723 segment.filesize = data.GetU32 (&offset);
724 // Extract maxprot, initprot, nsects and flags all at once
725 data.GetU32(&offset, &segment.maxprot, 4);
Greg Claytondf0b7d52011-07-08 04:11:42 +0000726 image_info.segments.push_back (segment);
Greg Clayton7b242382011-07-08 00:48:09 +0000727 }
728 break;
729
730 case llvm::MachO::LoadCommandSegment64:
731 {
732 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
733 // Extract vmaddr, vmsize, fileoff, and filesize all at once
734 data.GetU64(&offset, &segment.vmaddr, 4);
735 // Extract maxprot, initprot, nsects and flags all at once
736 data.GetU32(&offset, &segment.maxprot, 4);
Greg Claytondf0b7d52011-07-08 04:11:42 +0000737 image_info.segments.push_back (segment);
Greg Clayton7b242382011-07-08 00:48:09 +0000738 }
739 break;
740
741 case llvm::MachO::LoadCommandUUID:
Greg Claytondf0b7d52011-07-08 04:11:42 +0000742 image_info.uuid.SetBytes(data.GetData (&offset, 16));
Greg Clayton7b242382011-07-08 00:48:09 +0000743 break;
744
745 default:
746 break;
747 }
748 // Set offset to be the beginning of the next load command.
749 offset = load_cmd_offset + load_cmd.cmdsize;
750 }
751 }
752#if 0
753 // No slide in the kernel...
754
755 // All sections listed in the dyld image info structure will all
756 // either be fixed up already, or they will all be off by a single
757 // slide amount that is determined by finding the first segment
758 // that is at file offset zero which also has bytes (a file size
759 // that is greater than zero) in the object file.
760
761 // Determine the slide amount (if any)
Greg Claytondf0b7d52011-07-08 04:11:42 +0000762 const size_t num_sections = image_info.segments.size();
Greg Clayton7b242382011-07-08 00:48:09 +0000763 for (size_t i = 0; i < num_sections; ++i)
764 {
765 // Iterate through the object file sections to find the
766 // first section that starts of file offset zero and that
767 // has bytes in the file...
Greg Claytondf0b7d52011-07-08 04:11:42 +0000768 if (image_info.segments[i].fileoff == 0 && image_info.segments[i].filesize > 0)
Greg Clayton7b242382011-07-08 00:48:09 +0000769 {
Greg Claytondf0b7d52011-07-08 04:11:42 +0000770 image_info.slide = image_info.address - image_info.segments[i].vmaddr;
Greg Clayton7b242382011-07-08 00:48:09 +0000771 // We have found the slide amount, so we can exit
772 // this for loop.
773 break;
774 }
775 }
776#endif
Greg Claytondf0b7d52011-07-08 04:11:42 +0000777 if (image_info.uuid.IsValid())
778 {
779 bool did_create = false;
780 if (FindTargetModule(image_info, true, &did_create))
781 {
782 if (did_create)
783 image_info.module_create_stop_id = m_process->GetStopID();
784 }
785 }
Greg Clayton7b242382011-07-08 00:48:09 +0000786 return cmd_idx;
787}
788
789//----------------------------------------------------------------------
790// Dump a Segment to the file handle provided.
791//----------------------------------------------------------------------
792void
Greg Clayton374972e2011-07-09 17:15:55 +0000793DynamicLoaderMacOSXKernel::Segment::PutToLog (Log *log, addr_t slide) const
Greg Clayton7b242382011-07-08 00:48:09 +0000794{
795 if (log)
796 {
797 if (slide == 0)
798 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)",
799 name.AsCString(""),
800 vmaddr + slide,
801 vmaddr + slide + vmsize);
802 else
803 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx",
804 name.AsCString(""),
805 vmaddr + slide,
806 vmaddr + slide + vmsize,
807 slide);
808 }
809}
810
811const DynamicLoaderMacOSXKernel::Segment *
812DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::FindSegment (const ConstString &name) const
813{
814 const size_t num_segments = segments.size();
815 for (size_t i=0; i<num_segments; ++i)
816 {
817 if (segments[i].name == name)
818 return &segments[i];
819 }
820 return NULL;
821}
822
823
824//----------------------------------------------------------------------
825// Dump an image info structure to the file handle provided.
826//----------------------------------------------------------------------
827void
828DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
829{
830 if (log == NULL)
831 return;
832 uint8_t *u = (uint8_t *)uuid.GetBytes();
Greg Clayton7b242382011-07-08 00:48:09 +0000833
834 if (address == LLDB_INVALID_ADDRESS)
835 {
836 if (u)
837 {
838 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)",
839 u[ 0], u[ 1], u[ 2], u[ 3],
840 u[ 4], u[ 5], u[ 6], u[ 7],
841 u[ 8], u[ 9], u[10], u[11],
842 u[12], u[13], u[14], u[15],
843 name);
844 }
845 else
846 log->Printf("\t name='%s' (UNLOADED)", name);
847 }
848 else
849 {
850 if (u)
851 {
852 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'",
853 address,
854 u[ 0], u[ 1], u[ 2], u[ 3],
855 u[ 4], u[ 5], u[ 6], u[ 7],
856 u[ 8], u[ 9], u[10], u[11],
857 u[12], u[13], u[14], u[15],
858 name);
859 }
860 else
861 {
862 log->Printf("\taddress=0x%16.16llx path='%s/%s'", address, name);
863 }
864 for (uint32_t i=0; i<segments.size(); ++i)
865 segments[i].PutToLog(log, 0);
866 }
867}
868
869//----------------------------------------------------------------------
870// Dump the _dyld_all_image_infos members and all current image infos
871// that we have parsed to the file handle provided.
872//----------------------------------------------------------------------
873void
874DynamicLoaderMacOSXKernel::PutToLog(Log *log) const
875{
876 if (log == NULL)
877 return;
878
879 Mutex::Locker locker(m_mutex);
880 log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u, reserved=%u }",
Greg Clayton0d9fc762011-07-08 03:21:57 +0000881 m_kext_summary_header_addr.GetFileAddress(),
Greg Clayton7b242382011-07-08 00:48:09 +0000882 m_kext_summary_header.version,
883 m_kext_summary_header.entry_size,
884 m_kext_summary_header.entry_count,
885 m_kext_summary_header.reserved);
886
887 size_t i;
888 const size_t count = m_kext_summaries.size();
889 if (count > 0)
890 {
891 log->PutCString("Loaded:");
892 for (i = 0; i<count; i++)
893 m_kext_summaries[i].PutToLog(log);
894 }
895}
896
897void
898DynamicLoaderMacOSXKernel::PrivateInitialize(Process *process)
899{
900 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
901 Clear(true);
902 m_process = process;
903 m_process->GetTarget().GetSectionLoadList().Clear();
904}
905
Greg Clayton374972e2011-07-09 17:15:55 +0000906void
907DynamicLoaderMacOSXKernel::SetNotificationBreakpointIfNeeded ()
Greg Clayton7b242382011-07-08 00:48:09 +0000908{
Greg Clayton374972e2011-07-09 17:15:55 +0000909 if (m_break_id == LLDB_INVALID_BREAK_ID)
910 {
911 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
912
Greg Claytond16e1e52011-07-12 17:06:17 +0000913
Greg Clayton374972e2011-07-09 17:15:55 +0000914 const bool internal_bp = false;
Greg Claytond16e1e52011-07-12 17:06:17 +0000915 const LazyBool skip_prologue = eLazyBoolNo;
Greg Clayton374972e2011-07-09 17:15:55 +0000916 Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&m_kernel.module_sp->GetFileSpec(),
917 "OSKextLoadedKextSummariesUpdated",
918 eFunctionNameTypeFull,
Greg Claytond16e1e52011-07-12 17:06:17 +0000919 internal_bp,
920 skip_prologue).get();
Greg Clayton374972e2011-07-09 17:15:55 +0000921
922 bp->SetCallback (DynamicLoaderMacOSXKernel::BreakpointHitCallback, this, true);
923 m_break_id = bp->GetID();
924 }
Greg Clayton7b242382011-07-08 00:48:09 +0000925}
926
927//----------------------------------------------------------------------
928// Member function that gets called when the process state changes.
929//----------------------------------------------------------------------
930void
931DynamicLoaderMacOSXKernel::PrivateProcessStateChanged (Process *process, StateType state)
932{
933 DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s(%s)\n", __FUNCTION__, StateAsCString(state));
934 switch (state)
935 {
936 case eStateConnected:
937 case eStateAttaching:
938 case eStateLaunching:
939 case eStateInvalid:
940 case eStateUnloaded:
941 case eStateExited:
942 case eStateDetached:
943 Clear(false);
944 break;
945
946 case eStateStopped:
Greg Clayton374972e2011-07-09 17:15:55 +0000947 UpdateIfNeeded();
Greg Clayton7b242382011-07-08 00:48:09 +0000948 break;
949
950 case eStateRunning:
951 case eStateStepping:
952 case eStateCrashed:
953 case eStateSuspended:
954 break;
955
956 default:
957 break;
958 }
959}
960
961ThreadPlanSP
962DynamicLoaderMacOSXKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
963{
964 ThreadPlanSP thread_plan_sp;
Greg Clayton374972e2011-07-09 17:15:55 +0000965 LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
966 if (log)
967 log->Printf ("Could not find symbol for step through.");
Greg Clayton7b242382011-07-08 00:48:09 +0000968 return thread_plan_sp;
969}
970
971Error
972DynamicLoaderMacOSXKernel::CanLoadImage ()
973{
974 Error error;
975 error.SetErrorString("always unsafe to load or unload shared libraries in the darwin kernel");
976 return error;
977}
978
979void
980DynamicLoaderMacOSXKernel::Initialize()
981{
982 PluginManager::RegisterPlugin (GetPluginNameStatic(),
983 GetPluginDescriptionStatic(),
984 CreateInstance);
985}
986
987void
988DynamicLoaderMacOSXKernel::Terminate()
989{
990 PluginManager::UnregisterPlugin (CreateInstance);
991}
992
993
994const char *
995DynamicLoaderMacOSXKernel::GetPluginNameStatic()
996{
997 return "dynamic-loader.macosx-kernel";
998}
999
1000const char *
1001DynamicLoaderMacOSXKernel::GetPluginDescriptionStatic()
1002{
1003 return "Dynamic loader plug-in that watches for shared library loads/unloads in the MacOSX kernel.";
1004}
1005
1006
1007//------------------------------------------------------------------
1008// PluginInterface protocol
1009//------------------------------------------------------------------
1010const char *
1011DynamicLoaderMacOSXKernel::GetPluginName()
1012{
1013 return "DynamicLoaderMacOSXKernel";
1014}
1015
1016const char *
1017DynamicLoaderMacOSXKernel::GetShortPluginName()
1018{
1019 return GetPluginNameStatic();
1020}
1021
1022uint32_t
1023DynamicLoaderMacOSXKernel::GetPluginVersion()
1024{
1025 return 1;
1026}
1027