blob: bdfc47c48ff7be4f99b0272e0ba5698fc68936ae [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- DynamicLoaderMacOSXDYLD.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"
Jim Inghamb66cd072010-09-28 01:25:32 +000018#include "lldb/Target/ObjCLanguageRuntime.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#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 "DynamicLoaderMacOSXDYLD.h"
Chris Lattner24943d22010-06-08 16:52:24 +000026
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;
Greg Clayton1674b122010-07-21 22:12:05 +000037using namespace llvm::MachO;
Chris Lattner24943d22010-06-08 16:52:24 +000038
39/// FIXME - The ObjC Runtime trampoline handler doesn't really belong here.
40/// I am putting it here so I can invoke it in the Trampoline code here, but
41/// it should be moved to the ObjC Runtime support when it is set up.
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 *
49DynamicLoaderMacOSXDYLD::CreateInstance (Process* process)
50{
51 return new DynamicLoaderMacOSXDYLD (process);
52}
53
54//----------------------------------------------------------------------
55// Constructor
56//----------------------------------------------------------------------
57DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) :
58 DynamicLoader(process),
59 m_dyld(),
60 m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
61 m_dyld_all_image_infos(),
62 m_break_id(LLDB_INVALID_BREAK_ID),
63 m_dyld_image_infos(),
Jim Inghamb66cd072010-09-28 01:25:32 +000064 m_mutex(Mutex::eMutexTypeRecursive)
Chris Lattner24943d22010-06-08 16:52:24 +000065{
66}
67
68//----------------------------------------------------------------------
69// Destructor
70//----------------------------------------------------------------------
71DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD()
72{
73 Clear(true);
74}
75
76//------------------------------------------------------------------
77/// Called after attaching a process.
78///
79/// Allow DynamicLoader plug-ins to execute some code after
80/// attaching to a process.
81//------------------------------------------------------------------
82void
83DynamicLoaderMacOSXDYLD::DidAttach ()
84{
85 PrivateInitialize(m_process);
86 if (NeedToLocateDYLD ())
87 LocateDYLD ();
88 SetNotificationBreakpoint ();
89 UpdateAllImageInfos();
90}
91
92//------------------------------------------------------------------
93/// Called after attaching a process.
94///
95/// Allow DynamicLoader plug-ins to execute some code after
96/// attaching to a process.
97//------------------------------------------------------------------
98void
99DynamicLoaderMacOSXDYLD::DidLaunch ()
100{
101 PrivateInitialize(m_process);
102 if (NeedToLocateDYLD ())
103 LocateDYLD ();
104 SetNotificationBreakpoint ();
105 UpdateAllImageInfos();
106}
107
108
109//----------------------------------------------------------------------
110// Clear out the state of this class.
111//----------------------------------------------------------------------
112void
113DynamicLoaderMacOSXDYLD::Clear (bool clear_process)
114{
115 Mutex::Locker locker(m_mutex);
116
117 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
118 m_process->ClearBreakpointSiteByID(m_break_id);
119
120 if (clear_process)
121 m_process = NULL;
122 m_dyld.Clear(false);
123 m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;
124 m_dyld_all_image_infos.Clear();
125 m_break_id = LLDB_INVALID_BREAK_ID;
126 m_dyld_image_infos.clear();
127}
128
129//----------------------------------------------------------------------
130// Check if we have found DYLD yet
131//----------------------------------------------------------------------
132bool
133DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() const
134{
135 return LLDB_BREAK_ID_IS_VALID (m_break_id);
136}
137
138//----------------------------------------------------------------------
139// Try and figure out where dyld is by first asking the Process
140// if it knows (which currently calls down in the the lldb::Process
141// to get the DYLD info (available on SnowLeopard only). If that fails,
142// then check in the default addresses.
143//----------------------------------------------------------------------
144bool
145DynamicLoaderMacOSXDYLD::LocateDYLD()
146{
147 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS)
148 m_dyld_all_image_infos_addr = m_process->GetImageInfoAddress ();
149
150 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
151 {
152 if (ReadAllImageInfosStructure ())
153 {
154 if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
155 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress);
156 else
157 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
158 }
159 }
160
161 // Check some default values
162 Module *executable = m_process->GetTarget().GetExecutableModule().get();
163
164 if (executable)
165 {
166 if (executable->GetArchitecture().GetAddressByteSize() == 8)
167 {
168 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
169 }
170#if defined (__arm__)
171 else
172 {
173 ArchSpec arm_arch("arm");
174 if (arm_arch == executable->Arch())
175 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
176 }
177#endif
178 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
179 }
180 return false;
181}
182
183//----------------------------------------------------------------------
184// Assume that dyld is in memory at ADDR and try to parse it's load
185// commands
186//----------------------------------------------------------------------
187bool
188DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr)
189{
190 DataExtractor data; // Load command data
191 if (ReadMachHeader (addr, &m_dyld.header, &data))
192 {
Greg Clayton1674b122010-07-21 22:12:05 +0000193 if (m_dyld.header.filetype == HeaderFileTypeDynamicLinkEditor)
Chris Lattner24943d22010-06-08 16:52:24 +0000194 {
195 m_dyld.address = addr;
196 ModuleSP dyld_module_sp;
197 if (ParseLoadCommands (data, m_dyld, &m_dyld.file_spec))
198 {
199 if (m_dyld.file_spec)
200 {
Greg Claytoncf015052010-06-11 03:25:34 +0000201 ArchSpec dyld_arch(eArchTypeMachO, m_dyld.header.cputype, m_dyld.header.cpusubtype);
Chris Lattner24943d22010-06-08 16:52:24 +0000202 dyld_module_sp = m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld.file_spec);
203
204 if (dyld_module_sp.get() == NULL || dyld_module_sp->GetArchitecture() != dyld_arch)
205 {
206 dyld_module_sp = m_process->GetTarget().GetSharedModule (m_dyld.file_spec,
207 dyld_arch,
208 &m_dyld.uuid);
209 }
210
211 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
212 }
213 }
214
215 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get())
216 {
217 static ConstString g_dyld_all_image_infos ("dyld_all_image_infos");
218 const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData);
219 if (symbol)
Greg Claytoneea26402010-09-14 23:36:40 +0000220 m_dyld_all_image_infos_addr = symbol->GetValue().GetLoadAddress(&m_process->GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +0000221 }
222
223 // Update all image infos
224 UpdateAllImageInfos();
225
226 // If we didn't have an executable before, but now we do, then the
227 // dyld module shared pointer might be unique and we may need to add
228 // it again (since Target::SetExecutableModule() will clear the
229 // images). So append the dyld module back to the list if it is
230 /// unique!
231 if (m_process->GetTarget().GetImages().AppendInNeeded (dyld_module_sp))
232 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
233
234 return true;
235 }
236 }
237 return false;
238}
239
240bool
241DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const
242{
243 return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
244}
245
246bool
247DynamicLoaderMacOSXDYLD::UpdateCommPageLoadAddress(Module *module)
248{
249 bool changed = false;
250 if (module)
251 {
252 ObjectFile *image_object_file = module->GetObjectFile();
253 if (image_object_file)
254 {
255 SectionList *section_list = image_object_file->GetSectionList ();
256 if (section_list)
257 {
258 uint32_t num_sections = section_list->GetSize();
259 for (uint32_t i=0; i<num_sections; ++i)
260 {
261 Section* section = section_list->GetSectionAtIndex (i).get();
262 if (section)
263 {
264 const addr_t new_section_load_addr = section->GetFileAddress ();
Greg Claytoneea26402010-09-14 23:36:40 +0000265 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section);
Chris Lattner24943d22010-06-08 16:52:24 +0000266 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
267 old_section_load_addr != new_section_load_addr)
268 {
Greg Claytoneea26402010-09-14 23:36:40 +0000269 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ()))
Chris Lattner24943d22010-06-08 16:52:24 +0000270 changed = true;
271 }
272 }
273 }
274 }
275 }
276 }
277 return changed;
278}
279
280//----------------------------------------------------------------------
281// Update the load addresses for all segments in MODULE using the
282// updated INFO that is passed in.
283//----------------------------------------------------------------------
284bool
285DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, struct DYLDImageInfo& info)
286{
287 bool changed = false;
288 if (module)
289 {
290 ObjectFile *image_object_file = module->GetObjectFile();
291 if (image_object_file)
292 {
293 SectionList *section_list = image_object_file->GetSectionList ();
294 if (section_list)
295 {
296 // All sections listed in the dyld image info structure will all
297 // either be fixed up already, or they will all be off by a single
298 // slide amount that is determined by finding the first segment
299 // that is at file offset zero which also has bytes (a file size
300 // that is greater than zero) in the object file.
301
302 // Determine the slide amount (if any)
303 info.slide = 0;
304 const size_t num_sections = section_list->GetSize();
305 size_t sect_idx = 0;
306 for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
307 {
308 // Iterate through the object file sections to find the
309 // first section that starts of file offset zero and that
310 // has bytes in the file...
311 Section *section = section_list->GetSectionAtIndex (sect_idx).get();
312 if (section)
313 {
314 // Find the first section that begins at file offset zero
315 // a file size (skip page zero).
316 if (section->GetFileOffset() == 0 && section->GetFileSize() > 0)
317 {
318 // We have now found the section, lets match it up
319 // with the section in the dyld image info structure.
320 const Segment *dyld_segment = info.FindSegment (section->GetName());
321 if (dyld_segment)
322 info.slide = info.address - dyld_segment->addr;
323 // We have found the slide amount, so we can exit
324 // this for loop.
325 break;
326 }
327 }
328 }
329
330 // We now know the slide amount, so go through all sections
331 // and update the load addresses with the correct values.
332 uint32_t num_segments = info.segments.size();
333 for (uint32_t i=0; i<num_segments; ++i)
334 {
335 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
336 assert (section_sp.get() != NULL);
337 const addr_t new_section_load_addr = info.segments[i].addr + info.slide;
Greg Claytoneea26402010-09-14 23:36:40 +0000338 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
Chris Lattner24943d22010-06-08 16:52:24 +0000339 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
340 old_section_load_addr != new_section_load_addr)
341 {
Greg Claytoneea26402010-09-14 23:36:40 +0000342 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
Chris Lattner24943d22010-06-08 16:52:24 +0000343 changed = true;
344 }
345 }
346 }
347 }
348 }
349 return changed;
350}
351
352//----------------------------------------------------------------------
353// Update the load addresses for all segments in MODULE using the
354// updated INFO that is passed in.
355//----------------------------------------------------------------------
356bool
357DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, struct DYLDImageInfo& info)
358{
359 bool changed = false;
360 if (module)
361 {
362 ObjectFile *image_object_file = module->GetObjectFile();
363 if (image_object_file)
364 {
365 SectionList *section_list = image_object_file->GetSectionList ();
366 if (section_list)
367 {
368 uint32_t num_segments = info.segments.size();
369 for (uint32_t i=0; i<num_segments; ++i)
370 {
371 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
372 assert (section_sp.get() != NULL);
373 const addr_t old_section_load_addr = info.segments[i].addr + info.slide;
Greg Claytoneea26402010-09-14 23:36:40 +0000374 if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
Chris Lattner24943d22010-06-08 16:52:24 +0000375 changed = true;
376 }
377 }
378 }
379 }
380 return changed;
381}
382
383
384//----------------------------------------------------------------------
385// Static callback function that gets called when our DYLD notification
386// breakpoint gets hit. We update all of our image infos and then
387// let our super class DynamicLoader class decide if we should stop
388// or not (based on global preference).
389//----------------------------------------------------------------------
390bool
391DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
392{
393 // Let the event know that the images have changed
394 DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton;
395 dyld_instance->UpdateAllImageInfos();
396 // Return true to stop the target, false to just let the target run
397 return dyld_instance->GetStopWhenImagesChange();
398}
399
400bool
401DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
402{
403 Mutex::Locker locker(m_mutex);
404 m_dyld_all_image_infos.Clear();
405 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
406 {
407 const ByteOrder endian = m_process->GetByteOrder();
408 const uint32_t addr_size = m_process->GetAddressByteSize();
409 uint8_t buf[256];
Jason Molenda1f3af542010-06-10 01:21:21 +0000410 const size_t count_v2 = sizeof (uint32_t) + // version
411 sizeof (uint32_t) + // infoArrayCount
412 addr_size + // infoArray
413 addr_size + // notification
414 addr_size + // processDetachedFromSharedRegion + libSystemInitialized + pad
415 addr_size; // dyldImageLoadAddress
416 const size_t count_v11 = count_v2 +
417 addr_size + // jitInfo
418 addr_size + // dyldVersion
419 addr_size + // errorMessage
420 addr_size + // terminationFlags
421 addr_size + // coreSymbolicationShmPage
422 addr_size + // systemOrderFlag
423 addr_size + // uuidArrayCount
424 addr_size + // uuidArray
425 addr_size + // dyldAllImageInfosAddress
426 addr_size + // initialImageCount
427 addr_size + // errorKind
428 addr_size + // errorClientOfDylibPath
429 addr_size + // errorTargetDylibPath
430 addr_size; // errorSymbol
431 assert (sizeof (buf) > count_v11);
432
433 int count;
Chris Lattner24943d22010-06-08 16:52:24 +0000434 Error error;
Jason Molenda1f3af542010-06-10 01:21:21 +0000435 if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4)
436 {
437 DataExtractor data(buf, 4, endian, addr_size);
438 uint32_t offset = 0;
439 m_dyld_all_image_infos.version = data.GetU32(&offset);
440 }
441 else
442 {
443 return false;
444 }
445
446 if (m_dyld_all_image_infos.version >= 11)
447 count = count_v11;
448 else
449 count = count_v2;
450
Chris Lattner24943d22010-06-08 16:52:24 +0000451 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error);
452 if (bytes_read == count)
453 {
454 DataExtractor data(buf, count, endian, addr_size);
455 uint32_t offset = 0;
456 m_dyld_all_image_infos.version = data.GetU32(&offset);
457 m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
458 m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset);
459 m_dyld_all_image_infos.notification = data.GetPointer(&offset);
460 m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset);
Jason Molenda1f3af542010-06-10 01:21:21 +0000461 m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
462 // Adjust for padding.
463 offset += addr_size - 2;
464 m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset);
465 if (m_dyld_all_image_infos.version >= 11)
Chris Lattner24943d22010-06-08 16:52:24 +0000466 {
Jason Molenda1f3af542010-06-10 01:21:21 +0000467 offset += addr_size * 8;
468 uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset);
469
470 // When we started, we were given the actual address of the all_image_infos
471 // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in
472 // m_dyld_all_image_infos_addr and is the most accurate address we have.
473
474 // We read the dyld_all_image_infos struct from memory; it contains its own address.
475 // If the address in the struct does not match the actual address,
476 // the dyld we're looking at has been loaded at a different location (slid) from
477 // where it intended to load. The addresses in the dyld_all_image_infos struct
478 // are the original, non-slid addresses, and need to be adjusted. Most importantly
479 // the address of dyld and the notification address need to be adjusted.
480
481 if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr)
482 {
483 uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress;
484 uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress;
485 m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset;
486 m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
487 }
Chris Lattner24943d22010-06-08 16:52:24 +0000488 }
489 return true;
490 }
491 }
492 return false;
493}
494
495//----------------------------------------------------------------------
496// If we have found where the "_dyld_all_image_infos" lives in memory,
497// read the current info from it, and then update all image load
498// addresses (or lack thereof).
499//----------------------------------------------------------------------
500uint32_t
501DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
502{
Greg Clayton9d2993d2010-11-03 04:08:06 +0000503 Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER);
Chris Lattner24943d22010-06-08 16:52:24 +0000504 if (ReadAllImageInfosStructure ())
505 {
506 Mutex::Locker locker(m_mutex);
507 uint32_t idx;
Chris Lattner24943d22010-06-08 16:52:24 +0000508 uint32_t i = 0;
509 DYLDImageInfo::collection old_dyld_all_image_infos;
510 old_dyld_all_image_infos.swap(m_dyld_image_infos);
511
512 // If we made it here, we are assuming that the all dylib info data should
513 // be valid, lets read the info array.
514 const ByteOrder endian = m_process->GetByteOrder();
515 const uint32_t addr_size = m_process->GetAddressByteSize();
516
517 if (m_dyld_all_image_infos.dylib_info_count > 0)
518 {
519 if (m_dyld_all_image_infos.dylib_info_addr == 0)
520 {
521 // DYLD is updating the images right now...
522 }
523 else
524 {
525 m_dyld_image_infos.resize(m_dyld_all_image_infos.dylib_info_count);
526 const size_t count = m_dyld_image_infos.size() * 3 * addr_size;
527 DataBufferHeap info_data(count, 0);
528 Error error;
529 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos.dylib_info_addr,
530 info_data.GetBytes(),
531 info_data.GetByteSize(),
532 error);
533 if (bytes_read == count)
534 {
535 uint32_t info_data_offset = 0;
536 DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size);
537 for (i = 0; info_data_ref.ValidOffset(info_data_offset); i++)
538 {
539 assert (i < m_dyld_image_infos.size());
540 m_dyld_image_infos[i].address = info_data_ref.GetPointer(&info_data_offset);
541 lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset);
542 m_dyld_image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset);
543
544 char raw_path[PATH_MAX];
545 m_process->ReadMemory (path_addr, raw_path, sizeof(raw_path), error);
Greg Clayton537a7a82010-10-20 20:54:39 +0000546 m_dyld_image_infos[i].file_spec.SetFile(raw_path, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000547 }
548 assert(i == m_dyld_all_image_infos.dylib_info_count);
549
550 UpdateAllImageInfosHeaderAndLoadCommands();
551 }
552 else
553 {
554 DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
555 m_dyld_image_infos.clear();
556 }
557 }
558 }
559 else
560 {
561 m_dyld_image_infos.clear();
562 }
563
564 // If our new list is smaller than our old list, we have unloaded
565 // some shared libraries
566 if (m_dyld_image_infos.size() < old_dyld_all_image_infos.size())
567 {
568 ModuleList unloaded_module_list;
Greg Clayton9d2993d2010-11-03 04:08:06 +0000569 uint32_t old_idx;
570 for (idx = 0; idx < old_dyld_all_image_infos.size(); ++idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000571 {
Greg Clayton9d2993d2010-11-03 04:08:06 +0000572 for (old_idx = idx; old_idx < old_dyld_all_image_infos.size(); ++old_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000573 {
Greg Clayton9d2993d2010-11-03 04:08:06 +0000574 if (m_dyld_image_infos[idx].file_spec == old_dyld_all_image_infos[old_idx].file_spec)
575 {
576 old_dyld_all_image_infos[old_idx].address = LLDB_INVALID_ADDRESS;
577 break;
578 }
Chris Lattner24943d22010-06-08 16:52:24 +0000579 }
580 }
Greg Clayton9d2993d2010-11-03 04:08:06 +0000581
582 if (log)
583 log->PutCString("Unloaded:");
584
585 for (old_idx = 0; old_idx < old_dyld_all_image_infos.size(); ++old_idx)
586 {
587 if (old_dyld_all_image_infos[old_idx].address != LLDB_INVALID_ADDRESS)
588 {
589 if (log)
590 old_dyld_all_image_infos[old_idx].PutToLog (log);
591 ModuleSP unload_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (old_dyld_all_image_infos[old_idx].file_spec));
592 if (unload_image_module_sp.get())
593 {
594 if (UnloadImageLoadAddress (unload_image_module_sp.get(), old_dyld_all_image_infos[old_idx]))
595 unloaded_module_list.AppendInNeeded (unload_image_module_sp);
596 }
597 }
598 }
599
Chris Lattner24943d22010-06-08 16:52:24 +0000600 if (unloaded_module_list.GetSize() > 0)
601 m_process->GetTarget().ModulesDidUnload (unloaded_module_list);
602 }
Greg Clayton9d2993d2010-11-03 04:08:06 +0000603 else
604 {
605 if (log)
606 PutToLog(log);
607 }
Chris Lattner24943d22010-06-08 16:52:24 +0000608 }
609 else
610 {
611 m_dyld_image_infos.clear();
612 }
613
614 const uint32_t num_dylibs = m_dyld_image_infos.size();
615 if (num_dylibs > 0)
616 {
617 ModuleList loaded_module_list;
618 for (uint32_t idx = 0; idx<num_dylibs; ++idx)
619 {
Greg Claytoncf015052010-06-11 03:25:34 +0000620 ArchSpec arch_spec(eArchTypeMachO, m_dyld_image_infos[idx].header.cputype, m_dyld_image_infos[idx].header.cpusubtype);
Chris Lattner24943d22010-06-08 16:52:24 +0000621 ModuleSP image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld_image_infos[idx].file_spec));
622 if (image_module_sp.get() == NULL || image_module_sp->GetArchitecture() != arch_spec)
623 {
624 image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec,
625 arch_spec,
626 &m_dyld_image_infos[idx].uuid);
627 }
628
629 if (image_module_sp)
630 {
Greg Clayton236c1c72010-09-07 23:40:05 +0000631 if (m_dyld_image_infos[idx].header.filetype == HeaderFileTypeDynamicLinkEditor)
632 image_module_sp->SetIsDynamicLinkEditor (true);
633
Chris Lattner24943d22010-06-08 16:52:24 +0000634 ObjectFile *objfile = image_module_sp->GetObjectFile ();
635 if (objfile)
636 {
637 SectionList *sections = objfile->GetSectionList();
638 if (sections)
639 {
640 ConstString commpage_dbstr("__commpage");
641 Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
642 if (commpage_section)
643 {
644 FileSpec objfile_file_spec(objfile->GetFileSpec());
645 ModuleSP commpage_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (objfile_file_spec, &commpage_dbstr));
646 if (commpage_image_module_sp.get() == NULL)
647 {
648 commpage_image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec,
649 arch_spec,
650 &m_dyld_image_infos[idx].uuid,
651 &commpage_dbstr,
652 objfile->GetOffset() + commpage_section->GetOffset());
653 UpdateCommPageLoadAddress(commpage_image_module_sp.get());
654 }
655 }
656 }
657 }
658
659 // UpdateImageLoadAddress will return true if any segments
660 // change load address. We need to check this so we don't
661 // mention that all loaded shared libraries are newly loaded
662 // each time we hit out dyld breakpoint since dyld will list all
663 // shared libraries each time.
664 if (UpdateImageLoadAddress (image_module_sp.get(), m_dyld_image_infos[idx]))
665 {
666 loaded_module_list.AppendInNeeded (image_module_sp);
667 }
668 }
669 }
Chris Lattner24943d22010-06-08 16:52:24 +0000670 if (loaded_module_list.GetSize() > 0)
671 {
672 // FIXME: This should really be in the Runtime handlers class, which should get
673 // called by the target's ModulesDidLoad, but we're doing it all locally for now
674 // to save time.
675 // Also, I'm assuming there can be only one libobjc dylib loaded...
676
Jim Inghamb66cd072010-09-28 01:25:32 +0000677 ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
678 if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
Chris Lattner24943d22010-06-08 16:52:24 +0000679 {
680 size_t num_modules = loaded_module_list.GetSize();
681 for (int i = 0; i < num_modules; i++)
682 {
Jim Inghamb66cd072010-09-28 01:25:32 +0000683 if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
Chris Lattner24943d22010-06-08 16:52:24 +0000684 {
Jim Inghamb66cd072010-09-28 01:25:32 +0000685 objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
Chris Lattner24943d22010-06-08 16:52:24 +0000686 break;
687 }
688 }
689 }
690 m_process->GetTarget().ModulesDidLoad (loaded_module_list);
691 }
692 }
693 return m_dyld_image_infos.size();
694}
695
696//----------------------------------------------------------------------
697// Read a mach_header at ADDR into HEADER, and also fill in the load
698// command data into LOAD_COMMAND_DATA if it is non-NULL.
699//
700// Returns true if we succeed, false if we fail for any reason.
701//----------------------------------------------------------------------
702bool
Greg Clayton1674b122010-07-21 22:12:05 +0000703DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, mach_header *header, DataExtractor *load_command_data)
Chris Lattner24943d22010-06-08 16:52:24 +0000704{
Greg Clayton1674b122010-07-21 22:12:05 +0000705 DataBufferHeap header_bytes(sizeof(mach_header), 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000706 Error error;
707 size_t bytes_read = m_process->ReadMemory (addr,
708 header_bytes.GetBytes(),
709 header_bytes.GetByteSize(),
710 error);
Greg Clayton1674b122010-07-21 22:12:05 +0000711 if (bytes_read == sizeof(mach_header))
Chris Lattner24943d22010-06-08 16:52:24 +0000712 {
713 uint32_t offset = 0;
714 ::memset (header, 0, sizeof(header));
715
716 // Get the magic byte unswapped so we can figure out what we are dealing with
717 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), eByteOrderHost, 4);
718 header->magic = data.GetU32(&offset);
719 lldb::addr_t load_cmd_addr = addr;
720 data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
721 switch (header->magic)
722 {
Greg Clayton1674b122010-07-21 22:12:05 +0000723 case llvm::MachO::HeaderMagic32:
724 case llvm::MachO::HeaderMagic32Swapped:
Chris Lattner24943d22010-06-08 16:52:24 +0000725 data.SetAddressByteSize(4);
Greg Clayton1674b122010-07-21 22:12:05 +0000726 load_cmd_addr += sizeof(mach_header);
Chris Lattner24943d22010-06-08 16:52:24 +0000727 break;
728
Greg Clayton1674b122010-07-21 22:12:05 +0000729 case llvm::MachO::HeaderMagic64:
730 case llvm::MachO::HeaderMagic64Swapped:
Chris Lattner24943d22010-06-08 16:52:24 +0000731 data.SetAddressByteSize(8);
Greg Clayton1674b122010-07-21 22:12:05 +0000732 load_cmd_addr += sizeof(mach_header_64);
Chris Lattner24943d22010-06-08 16:52:24 +0000733 break;
734
735 default:
736 return false;
737 }
738
739 // Read the rest of dyld's mach header
Greg Clayton1674b122010-07-21 22:12:05 +0000740 if (data.GetU32(&offset, &header->cputype, (sizeof(mach_header)/sizeof(uint32_t)) - 1))
Chris Lattner24943d22010-06-08 16:52:24 +0000741 {
742 if (load_command_data == NULL)
743 return true; // We were able to read the mach_header and weren't asked to read the load command bytes
744
745 DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));
746
747 size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr,
748 load_cmd_data_sp->GetBytes(),
749 load_cmd_data_sp->GetByteSize(),
750 error);
751
752 if (load_cmd_bytes_read == header->sizeofcmds)
753 {
754 // Set the load command data and also set the correct endian
755 // swap settings and the correct address size
756 load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
757 load_command_data->SetByteOrder(data.GetByteOrder());
758 load_command_data->SetAddressByteSize(data.GetAddressByteSize());
759 return true; // We successfully read the mach_header and the load command data
760 }
761
762 return false; // We weren't able to read the load command data
763 }
764 }
765 return false; // We failed the read the mach_header
766}
767
768
769//----------------------------------------------------------------------
770// Parse the load commands for an image
771//----------------------------------------------------------------------
772uint32_t
773DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, struct DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker)
774{
775 uint32_t offset = 0;
776 uint32_t cmd_idx;
777 Segment segment;
778 dylib_info.Clear (true);
779
780 for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++)
781 {
782 // Clear out any load command specific data from DYLIB_INFO since
783 // we are about to read it.
784
Greg Clayton1674b122010-07-21 22:12:05 +0000785 if (data.ValidOffsetForDataOfSize (offset, sizeof(load_command)))
Chris Lattner24943d22010-06-08 16:52:24 +0000786 {
Greg Clayton1674b122010-07-21 22:12:05 +0000787 load_command load_cmd;
Chris Lattner24943d22010-06-08 16:52:24 +0000788 uint32_t load_cmd_offset = offset;
789 load_cmd.cmd = data.GetU32 (&offset);
790 load_cmd.cmdsize = data.GetU32 (&offset);
791 switch (load_cmd.cmd)
792 {
Greg Clayton1674b122010-07-21 22:12:05 +0000793 case LoadCommandSegment32:
Chris Lattner24943d22010-06-08 16:52:24 +0000794 {
795 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
796 segment.addr = data.GetU32 (&offset);
797 segment.size = data.GetU32 (&offset);
798 dylib_info.segments.push_back (segment);
799 }
800 break;
801
Greg Clayton1674b122010-07-21 22:12:05 +0000802 case LoadCommandSegment64:
Chris Lattner24943d22010-06-08 16:52:24 +0000803 {
804 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
805 segment.addr = data.GetU64 (&offset);
806 segment.size = data.GetU64 (&offset);
807 dylib_info.segments.push_back (segment);
808 }
809 break;
810
Greg Clayton1674b122010-07-21 22:12:05 +0000811 case LoadCommandDynamicLinkerIdent:
Chris Lattner24943d22010-06-08 16:52:24 +0000812 if (lc_id_dylinker)
813 {
814 uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset);
815 const char *path = data.PeekCStr (name_offset);
Greg Clayton537a7a82010-10-20 20:54:39 +0000816 lc_id_dylinker->SetFile (path, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000817 }
818 break;
819
Greg Clayton1674b122010-07-21 22:12:05 +0000820 case LoadCommandUUID:
Chris Lattner24943d22010-06-08 16:52:24 +0000821 dylib_info.uuid.SetBytes(data.GetData (&offset, 16));
822 break;
823
824 default:
825 break;
826 }
827 // Set offset to be the beginning of the next load command.
828 offset = load_cmd_offset + load_cmd.cmdsize;
829 }
830 }
831 return cmd_idx;
832}
833
834//----------------------------------------------------------------------
835// Read the mach_header and load commands for each image that the
836// _dyld_all_image_infos structure points to and cache the results.
837//----------------------------------------------------------------------
838void
839DynamicLoaderMacOSXDYLD::UpdateAllImageInfosHeaderAndLoadCommands()
840{
841 uint32_t exe_idx = UINT32_MAX;
842 // Read any UUID values that we can get
843 for (uint32_t i = 0; i < m_dyld_all_image_infos.dylib_info_count; i++)
844 {
845 if (!m_dyld_image_infos[i].UUIDValid())
846 {
847 DataExtractor data; // Load command data
848 if (!ReadMachHeader (m_dyld_image_infos[i].address, &m_dyld_image_infos[i].header, &data))
849 continue;
850
851 ParseLoadCommands (data, m_dyld_image_infos[i], NULL);
852
Greg Clayton1674b122010-07-21 22:12:05 +0000853 if (m_dyld_image_infos[i].header.filetype == HeaderFileTypeExecutable)
Chris Lattner24943d22010-06-08 16:52:24 +0000854 exe_idx = i;
855 }
856 }
857
858 if (exe_idx < m_dyld_image_infos.size())
859 {
860 bool set_executable = false;
Greg Claytoncf015052010-06-11 03:25:34 +0000861 ArchSpec dyld_exe_arch_spec(eArchTypeMachO, m_dyld_image_infos[exe_idx].header.cputype, m_dyld_image_infos[exe_idx].header.cpusubtype);
Chris Lattner24943d22010-06-08 16:52:24 +0000862 ModuleSP exe_module_sp(m_process->GetTarget().GetExecutableModule());
863 if (exe_module_sp.get())
864 {
865 if (exe_module_sp->GetFileSpec() != m_dyld_image_infos[exe_idx].file_spec ||
866 exe_module_sp->GetArchitecture() != dyld_exe_arch_spec)
867 set_executable = true;
868 }
869 else
870 set_executable = true;
871
872 if (set_executable)
873 {
874 exe_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[exe_idx].file_spec,
875 dyld_exe_arch_spec,
876 &m_dyld_image_infos[exe_idx].uuid);
877 if (exe_module_sp.get())
878 {
879 // If we found the file where it purported to be, then it should
880 // be safe to load dependent images.
881 bool get_dependent_images = exe_module_sp->GetFileSpec() == m_dyld_image_infos[exe_idx].file_spec;
882
883 m_process->GetTarget().SetExecutableModule (exe_module_sp, get_dependent_images);
884 }
885 }
886 }
887}
888
889//----------------------------------------------------------------------
890// Dump a Segment to the file handle provided.
891//----------------------------------------------------------------------
892void
893DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const
894{
895 if (log)
896 log->Printf("\t\t%16s [0x%16.16llx - 0x%16.16llx)", name.AsCString(""), addr + slide, addr + slide + size);
897}
898
899const DynamicLoaderMacOSXDYLD::Segment *
900DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const
901{
902 const size_t num_segments = segments.size();
903 for (size_t i=0; i<num_segments; ++i)
904 {
905 if (segments[i].name == name)
906 return &segments[i];
907 }
908 return NULL;
909}
910
911
912//----------------------------------------------------------------------
913// Dump an image info structure to the file handle provided.
914//----------------------------------------------------------------------
915void
916DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const
917{
918 if (log == NULL)
919 return;
920 uint8_t *u = (uint8_t *)uuid.GetBytes();
921
922 if (address == LLDB_INVALID_ADDRESS)
923 {
924 if (u)
925 {
926 log->Printf("\t modtime=0x%8.8llx 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 path='%s/%s' (UNLOADED)",
927 mod_date,
928 u[ 0], u[ 1], u[ 2], u[ 3],
929 u[ 4], u[ 5], u[ 6], u[ 7],
930 u[ 8], u[ 9], u[10], u[11],
931 u[12], u[13], u[14], u[15],
932 file_spec.GetDirectory().AsCString(),
933 file_spec.GetFilename().AsCString());
934 }
935 else
936 log->Printf("\t modtime=0x%8.8llx path='%s/%s' (UNLOADED)",
937 mod_date,
938 file_spec.GetDirectory().AsCString(),
939 file_spec.GetFilename().AsCString());
940 }
941 else
942 {
943 if (u)
944 {
945 log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx 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 path='%s/%s'",
946 address,
947 mod_date,
948 u[ 0], u[ 1], u[ 2], u[ 3],
949 u[ 4], u[ 5], u[ 6], u[ 7],
950 u[ 8], u[ 9], u[10], u[11],
951 u[12], u[13], u[14], u[15],
952 file_spec.GetDirectory().AsCString(),
953 file_spec.GetFilename().AsCString());
954 }
955 else
956 {
957 log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'",
958 address,
959 mod_date,
960 file_spec.GetDirectory().AsCString(),
961 file_spec.GetFilename().AsCString());
962
963 }
964 for (uint32_t i=0; i<segments.size(); ++i)
965 segments[i].PutToLog(log, slide);
966 }
967}
968
969//----------------------------------------------------------------------
970// Dump the _dyld_all_image_infos members and all current image infos
971// that we have parsed to the file handle provided.
972//----------------------------------------------------------------------
973void
974DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const
975{
976 if (log == NULL)
977 return;
978
979 Mutex::Locker locker(m_mutex);
980 log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }",
981 m_dyld_all_image_infos.version,
982 m_dyld_all_image_infos.dylib_info_count,
983 (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
984 (uint64_t)m_dyld_all_image_infos.notification);
985 size_t i;
986 const size_t count = m_dyld_image_infos.size();
987 if (count > 0)
988 {
Greg Clayton9d2993d2010-11-03 04:08:06 +0000989 log->PutCString("Loaded:");
Chris Lattner24943d22010-06-08 16:52:24 +0000990 for (i = 0; i<count; i++)
991 m_dyld_image_infos[i].PutToLog(log);
992 }
993}
994
995//----------------------------------------------------------------------
996// Static callback function that gets called when the process state
997// changes.
998//----------------------------------------------------------------------
999void
1000DynamicLoaderMacOSXDYLD::Initialize(void *baton, Process *process)
1001{
1002 ((DynamicLoaderMacOSXDYLD*)baton)->PrivateInitialize(process);
1003}
1004
1005void
1006DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process)
1007{
1008 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1009 Clear(true);
1010 m_process = process;
1011}
1012
1013
1014//----------------------------------------------------------------------
1015// Static callback function that gets called when the process state
1016// changes.
1017//----------------------------------------------------------------------
1018void
1019DynamicLoaderMacOSXDYLD::ProcessStateChanged(void *baton, Process *process, StateType state)
1020{
1021 ((DynamicLoaderMacOSXDYLD*)baton)->PrivateProcessStateChanged(process, state);
1022}
1023
1024bool
1025DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint ()
1026{
1027 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1028 if (m_break_id == LLDB_INVALID_BREAK_ID)
1029 {
1030 if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS)
1031 {
1032 Address so_addr;
1033 // Set the notification breakpoint and install a breakpoint
1034 // callback function that will get called each time the
1035 // breakpoint gets hit. We will use this to track when shared
1036 // libraries get loaded/unloaded.
1037
Greg Claytoneea26402010-09-14 23:36:40 +00001038 if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr))
Chris Lattner24943d22010-06-08 16:52:24 +00001039 {
1040 Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
1041 dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true);
1042 m_break_id = dyld_break->GetID();
1043 }
1044 }
1045 }
1046 return m_break_id != LLDB_INVALID_BREAK_ID;
1047}
1048
Jim Ingham7508e732010-08-09 23:31:02 +00001049//----------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001050// Member function that gets called when the process state changes.
1051//----------------------------------------------------------------------
1052void
1053DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state)
1054{
1055 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state));
1056 switch (state)
1057 {
1058 case eStateAttaching:
1059 case eStateLaunching:
1060 case eStateInvalid:
1061 case eStateUnloaded:
1062 case eStateExited:
1063 case eStateDetached:
1064 Clear(false);
1065 break;
1066
1067 case eStateStopped:
1068 // Keep trying find dyld and set our notification breakpoint each time
1069 // we stop until we succeed
1070 if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
1071 {
1072 if (NeedToLocateDYLD ())
1073 LocateDYLD ();
1074
1075 SetNotificationBreakpoint ();
1076 }
1077 break;
1078
1079 case eStateRunning:
1080 case eStateStepping:
1081 case eStateCrashed:
1082 case eStateSuspended:
1083 break;
1084
1085 default:
1086 break;
1087 }
1088}
1089
1090ThreadPlanSP
1091DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
1092{
1093 ThreadPlanSP thread_plan_sp;
1094 StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
1095 const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
1096 Symbol *current_symbol = current_context.symbol;
Jim Ingham17454cf2010-09-14 22:03:00 +00001097 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
Chris Lattner24943d22010-06-08 16:52:24 +00001098
1099 if (current_symbol != NULL)
1100 {
1101 if (current_symbol->IsTrampoline())
1102 {
Jim Ingham17454cf2010-09-14 22:03:00 +00001103 const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
1104
Chris Lattner24943d22010-06-08 16:52:24 +00001105 if (trampoline_name)
1106 {
1107 SymbolContextList target_symbols;
1108 ModuleList &images = thread.GetProcess().GetTarget().GetImages();
1109 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
1110 // FIXME - Make the Run to Address take multiple addresses, and
1111 // run to any of them.
Jim Ingham17454cf2010-09-14 22:03:00 +00001112 uint32_t num_symbols = target_symbols.GetSize();
1113 if (num_symbols == 1)
Chris Lattner24943d22010-06-08 16:52:24 +00001114 {
1115 SymbolContext context;
1116 AddressRange addr_range;
1117 if (target_symbols.GetContextAtIndex(0, context))
1118 {
1119 context.GetAddressRange (eSymbolContextEverything, addr_range);
1120 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others));
1121 }
Jim Ingham17454cf2010-09-14 22:03:00 +00001122 else
Chris Lattner24943d22010-06-08 16:52:24 +00001123 {
Jim Ingham17454cf2010-09-14 22:03:00 +00001124 if (log)
1125 log->Printf ("Couldn't resolve the symbol context.");
1126 }
1127 }
1128 else if (num_symbols > 1)
1129 {
1130 std::vector<lldb::addr_t> addresses;
1131 addresses.resize (num_symbols);
1132 for (uint32_t i = 0; i < num_symbols; i++)
1133 {
1134 SymbolContext context;
1135 AddressRange addr_range;
1136 if (target_symbols.GetContextAtIndex(i, context))
1137 {
1138 context.GetAddressRange (eSymbolContextEverything, addr_range);
Greg Claytoneea26402010-09-14 23:36:40 +00001139 lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
Jim Ingham17454cf2010-09-14 22:03:00 +00001140 addresses[i] = load_addr;
1141 }
1142 }
1143 if (addresses.size() > 0)
1144 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others));
1145 else
1146 {
1147 if (log)
1148 log->Printf ("Couldn't resolve the symbol contexts.");
Chris Lattner24943d22010-06-08 16:52:24 +00001149 }
1150 }
1151 else
1152 {
Chris Lattner24943d22010-06-08 16:52:24 +00001153 if (log)
1154 {
1155 log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
1156 }
1157 }
1158 }
1159 }
1160 }
Jim Ingham17454cf2010-09-14 22:03:00 +00001161 else
1162 {
1163 if (log)
1164 log->Printf ("Could not find symbol for step through.");
1165 }
Chris Lattner24943d22010-06-08 16:52:24 +00001166
Chris Lattner24943d22010-06-08 16:52:24 +00001167 return thread_plan_sp;
1168}
1169
Greg Clayton0baa3942010-11-04 01:54:29 +00001170Error
1171DynamicLoaderMacOSXDYLD::CanLoadImage ()
1172{
1173 Error error;
1174 // In order for us to tell if we can load a shared library we verify that
1175 // the dylib_info_addr isn't zero (which means no shared libraries have
1176 // been set yet, or dyld is currently mucking with the shared library list).
1177 if (ReadAllImageInfosStructure ())
1178 {
1179 // TODO: also check the _dyld_global_lock_held variable in libSystem.B.dylib?
1180 // TODO: check the malloc lock?
1181 // TODO: check the objective C lock?
1182 if (m_dyld_all_image_infos.dylib_info_addr != 0)
1183 return error; // Success
1184 }
1185
1186 error.SetErrorString("unsafe to load or unload shared libraries");
1187 return error;
1188}
1189
Chris Lattner24943d22010-06-08 16:52:24 +00001190void
1191DynamicLoaderMacOSXDYLD::Initialize()
1192{
1193 PluginManager::RegisterPlugin (GetPluginNameStatic(),
1194 GetPluginDescriptionStatic(),
1195 CreateInstance);
1196}
1197
1198void
1199DynamicLoaderMacOSXDYLD::Terminate()
1200{
1201 PluginManager::UnregisterPlugin (CreateInstance);
1202}
1203
1204
1205const char *
1206DynamicLoaderMacOSXDYLD::GetPluginNameStatic()
1207{
1208 return "dynamic-loader.macosx-dyld";
1209}
1210
1211const char *
1212DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic()
1213{
1214 return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes.";
1215}
1216
1217
1218//------------------------------------------------------------------
1219// PluginInterface protocol
1220//------------------------------------------------------------------
1221const char *
1222DynamicLoaderMacOSXDYLD::GetPluginName()
1223{
1224 return "DynamicLoaderMacOSXDYLD";
1225}
1226
1227const char *
1228DynamicLoaderMacOSXDYLD::GetShortPluginName()
1229{
1230 return GetPluginNameStatic();
1231}
1232
1233uint32_t
1234DynamicLoaderMacOSXDYLD::GetPluginVersion()
1235{
1236 return 1;
1237}
1238
1239void
1240DynamicLoaderMacOSXDYLD::GetPluginCommandHelp (const char *command, Stream *strm)
1241{
1242}
1243
1244Error
1245DynamicLoaderMacOSXDYLD::ExecutePluginCommand (Args &command, Stream *strm)
1246{
1247 Error error;
1248 error.SetErrorString("No plug-in command are currently supported.");
1249 return error;
1250}
1251
1252Log *
1253DynamicLoaderMacOSXDYLD::EnablePluginLogging (Stream *strm, Args &command)
1254{
1255 return NULL;
1256}
1257
1258