blob: 68aa0e00bd8d5202cf6f35a21a5e90c26803b8b3 [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
Greg Claytonab429022010-12-12 21:03:32 +000043
44DynamicLoaderMacOSXDYLD::DYLDImageInfo *
45DynamicLoaderMacOSXDYLD::GetImageInfo (const FileSpec &file_spec, const UUID &uuid)
46{
47 DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
48 for (pos = m_dyld_image_infos.begin(); pos != end; ++pos)
49 {
50 if (pos->uuid == uuid && pos->file_spec == file_spec)
51 return &(*pos);
52 }
53
54 if (m_dyld.uuid == uuid && m_dyld.file_spec == file_spec)
55 return &m_dyld;
56
57 return NULL;
58}
59
Chris Lattner24943d22010-06-08 16:52:24 +000060//----------------------------------------------------------------------
61// Create an instance of this class. This function is filled into
62// the plugin info class that gets handed out by the plugin factory and
63// allows the lldb to instantiate an instance of this class.
64//----------------------------------------------------------------------
65DynamicLoader *
66DynamicLoaderMacOSXDYLD::CreateInstance (Process* process)
67{
68 return new DynamicLoaderMacOSXDYLD (process);
69}
70
71//----------------------------------------------------------------------
72// Constructor
73//----------------------------------------------------------------------
74DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) :
75 DynamicLoader(process),
76 m_dyld(),
77 m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
78 m_dyld_all_image_infos(),
Greg Clayton20d338f2010-11-18 05:57:03 +000079 m_dyld_all_image_infos_stop_id (UINT32_MAX),
Chris Lattner24943d22010-06-08 16:52:24 +000080 m_break_id(LLDB_INVALID_BREAK_ID),
81 m_dyld_image_infos(),
Greg Clayton20d338f2010-11-18 05:57:03 +000082 m_dyld_image_infos_stop_id (UINT32_MAX),
Jim Inghamb66cd072010-09-28 01:25:32 +000083 m_mutex(Mutex::eMutexTypeRecursive)
Chris Lattner24943d22010-06-08 16:52:24 +000084{
85}
86
87//----------------------------------------------------------------------
88// Destructor
89//----------------------------------------------------------------------
90DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD()
91{
92 Clear(true);
93}
94
95//------------------------------------------------------------------
96/// Called after attaching a process.
97///
98/// Allow DynamicLoader plug-ins to execute some code after
99/// attaching to a process.
100//------------------------------------------------------------------
101void
102DynamicLoaderMacOSXDYLD::DidAttach ()
103{
104 PrivateInitialize(m_process);
Greg Clayton20d338f2010-11-18 05:57:03 +0000105 LocateDYLD ();
Chris Lattner24943d22010-06-08 16:52:24 +0000106 SetNotificationBreakpoint ();
Chris Lattner24943d22010-06-08 16:52:24 +0000107}
108
109//------------------------------------------------------------------
110/// Called after attaching a process.
111///
112/// Allow DynamicLoader plug-ins to execute some code after
113/// attaching to a process.
114//------------------------------------------------------------------
115void
116DynamicLoaderMacOSXDYLD::DidLaunch ()
117{
118 PrivateInitialize(m_process);
Greg Clayton20d338f2010-11-18 05:57:03 +0000119 LocateDYLD ();
Chris Lattner24943d22010-06-08 16:52:24 +0000120 SetNotificationBreakpoint ();
Chris Lattner24943d22010-06-08 16:52:24 +0000121}
122
123
124//----------------------------------------------------------------------
125// Clear out the state of this class.
126//----------------------------------------------------------------------
127void
128DynamicLoaderMacOSXDYLD::Clear (bool clear_process)
129{
130 Mutex::Locker locker(m_mutex);
131
132 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
133 m_process->ClearBreakpointSiteByID(m_break_id);
134
135 if (clear_process)
136 m_process = NULL;
137 m_dyld.Clear(false);
138 m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;
139 m_dyld_all_image_infos.Clear();
140 m_break_id = LLDB_INVALID_BREAK_ID;
141 m_dyld_image_infos.clear();
142}
143
144//----------------------------------------------------------------------
145// Check if we have found DYLD yet
146//----------------------------------------------------------------------
147bool
148DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() const
149{
150 return LLDB_BREAK_ID_IS_VALID (m_break_id);
151}
152
153//----------------------------------------------------------------------
154// Try and figure out where dyld is by first asking the Process
155// if it knows (which currently calls down in the the lldb::Process
156// to get the DYLD info (available on SnowLeopard only). If that fails,
157// then check in the default addresses.
158//----------------------------------------------------------------------
159bool
160DynamicLoaderMacOSXDYLD::LocateDYLD()
161{
162 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS)
163 m_dyld_all_image_infos_addr = m_process->GetImageInfoAddress ();
164
165 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
166 {
167 if (ReadAllImageInfosStructure ())
168 {
169 if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
170 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress);
171 else
172 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
173 }
174 }
175
176 // Check some default values
177 Module *executable = m_process->GetTarget().GetExecutableModule().get();
178
179 if (executable)
180 {
181 if (executable->GetArchitecture().GetAddressByteSize() == 8)
182 {
183 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
184 }
185#if defined (__arm__)
186 else
187 {
188 ArchSpec arm_arch("arm");
189 if (arm_arch == executable->Arch())
190 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
191 }
192#endif
193 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
194 }
195 return false;
196}
197
198//----------------------------------------------------------------------
199// Assume that dyld is in memory at ADDR and try to parse it's load
200// commands
201//----------------------------------------------------------------------
202bool
203DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr)
204{
205 DataExtractor data; // Load command data
206 if (ReadMachHeader (addr, &m_dyld.header, &data))
207 {
Greg Clayton1674b122010-07-21 22:12:05 +0000208 if (m_dyld.header.filetype == HeaderFileTypeDynamicLinkEditor)
Chris Lattner24943d22010-06-08 16:52:24 +0000209 {
210 m_dyld.address = addr;
211 ModuleSP dyld_module_sp;
212 if (ParseLoadCommands (data, m_dyld, &m_dyld.file_spec))
213 {
214 if (m_dyld.file_spec)
215 {
Greg Claytoncf015052010-06-11 03:25:34 +0000216 ArchSpec dyld_arch(eArchTypeMachO, m_dyld.header.cputype, m_dyld.header.cpusubtype);
Chris Lattner24943d22010-06-08 16:52:24 +0000217 dyld_module_sp = m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld.file_spec);
218
219 if (dyld_module_sp.get() == NULL || dyld_module_sp->GetArchitecture() != dyld_arch)
220 {
221 dyld_module_sp = m_process->GetTarget().GetSharedModule (m_dyld.file_spec,
222 dyld_arch,
223 &m_dyld.uuid);
224 }
225
226 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
227 }
228 }
229
230 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get())
231 {
232 static ConstString g_dyld_all_image_infos ("dyld_all_image_infos");
233 const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData);
234 if (symbol)
Greg Claytoneea26402010-09-14 23:36:40 +0000235 m_dyld_all_image_infos_addr = symbol->GetValue().GetLoadAddress(&m_process->GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +0000236 }
237
238 // Update all image infos
239 UpdateAllImageInfos();
240
241 // If we didn't have an executable before, but now we do, then the
242 // dyld module shared pointer might be unique and we may need to add
243 // it again (since Target::SetExecutableModule() will clear the
244 // images). So append the dyld module back to the list if it is
245 /// unique!
Greg Claytonab429022010-12-12 21:03:32 +0000246 if (m_process->GetTarget().GetImages().AppendIfNeeded (dyld_module_sp))
Chris Lattner24943d22010-06-08 16:52:24 +0000247 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
248
249 return true;
250 }
251 }
252 return false;
253}
254
255bool
256DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const
257{
258 return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
259}
260
261bool
262DynamicLoaderMacOSXDYLD::UpdateCommPageLoadAddress(Module *module)
263{
264 bool changed = false;
265 if (module)
266 {
267 ObjectFile *image_object_file = module->GetObjectFile();
268 if (image_object_file)
269 {
270 SectionList *section_list = image_object_file->GetSectionList ();
271 if (section_list)
272 {
273 uint32_t num_sections = section_list->GetSize();
274 for (uint32_t i=0; i<num_sections; ++i)
275 {
276 Section* section = section_list->GetSectionAtIndex (i).get();
277 if (section)
278 {
279 const addr_t new_section_load_addr = section->GetFileAddress ();
Greg Claytoneea26402010-09-14 23:36:40 +0000280 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section);
Chris Lattner24943d22010-06-08 16:52:24 +0000281 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
282 old_section_load_addr != new_section_load_addr)
283 {
Greg Claytoneea26402010-09-14 23:36:40 +0000284 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ()))
Chris Lattner24943d22010-06-08 16:52:24 +0000285 changed = true;
286 }
287 }
288 }
289 }
290 }
291 }
292 return changed;
293}
294
295//----------------------------------------------------------------------
296// Update the load addresses for all segments in MODULE using the
297// updated INFO that is passed in.
298//----------------------------------------------------------------------
299bool
300DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, struct DYLDImageInfo& info)
301{
302 bool changed = false;
303 if (module)
304 {
305 ObjectFile *image_object_file = module->GetObjectFile();
306 if (image_object_file)
307 {
308 SectionList *section_list = image_object_file->GetSectionList ();
309 if (section_list)
310 {
311 // All sections listed in the dyld image info structure will all
312 // either be fixed up already, or they will all be off by a single
313 // slide amount that is determined by finding the first segment
314 // that is at file offset zero which also has bytes (a file size
315 // that is greater than zero) in the object file.
316
317 // Determine the slide amount (if any)
318 info.slide = 0;
319 const size_t num_sections = section_list->GetSize();
320 size_t sect_idx = 0;
321 for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
322 {
323 // Iterate through the object file sections to find the
324 // first section that starts of file offset zero and that
325 // has bytes in the file...
326 Section *section = section_list->GetSectionAtIndex (sect_idx).get();
327 if (section)
328 {
329 // Find the first section that begins at file offset zero
330 // a file size (skip page zero).
331 if (section->GetFileOffset() == 0 && section->GetFileSize() > 0)
332 {
333 // We have now found the section, lets match it up
334 // with the section in the dyld image info structure.
335 const Segment *dyld_segment = info.FindSegment (section->GetName());
336 if (dyld_segment)
337 info.slide = info.address - dyld_segment->addr;
338 // We have found the slide amount, so we can exit
339 // this for loop.
340 break;
341 }
342 }
343 }
344
345 // We now know the slide amount, so go through all sections
346 // and update the load addresses with the correct values.
347 uint32_t num_segments = info.segments.size();
348 for (uint32_t i=0; i<num_segments; ++i)
349 {
350 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
351 assert (section_sp.get() != NULL);
352 const addr_t new_section_load_addr = info.segments[i].addr + info.slide;
Greg Claytoneea26402010-09-14 23:36:40 +0000353 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
Chris Lattner24943d22010-06-08 16:52:24 +0000354 if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
355 old_section_load_addr != new_section_load_addr)
356 {
Greg Claytoneea26402010-09-14 23:36:40 +0000357 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
Chris Lattner24943d22010-06-08 16:52:24 +0000358 changed = true;
359 }
360 }
361 }
362 }
363 }
364 return changed;
365}
366
367//----------------------------------------------------------------------
368// Update the load addresses for all segments in MODULE using the
369// updated INFO that is passed in.
370//----------------------------------------------------------------------
371bool
372DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, struct DYLDImageInfo& info)
373{
374 bool changed = false;
375 if (module)
376 {
377 ObjectFile *image_object_file = module->GetObjectFile();
378 if (image_object_file)
379 {
380 SectionList *section_list = image_object_file->GetSectionList ();
381 if (section_list)
382 {
383 uint32_t num_segments = info.segments.size();
384 for (uint32_t i=0; i<num_segments; ++i)
385 {
386 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
387 assert (section_sp.get() != NULL);
388 const addr_t old_section_load_addr = info.segments[i].addr + info.slide;
Greg Claytoneea26402010-09-14 23:36:40 +0000389 if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
Chris Lattner24943d22010-06-08 16:52:24 +0000390 changed = true;
391 }
392 }
393 }
394 }
395 return changed;
396}
397
398
399//----------------------------------------------------------------------
400// Static callback function that gets called when our DYLD notification
401// breakpoint gets hit. We update all of our image infos and then
402// let our super class DynamicLoader class decide if we should stop
403// or not (based on global preference).
404//----------------------------------------------------------------------
405bool
406DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
407{
408 // Let the event know that the images have changed
409 DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton;
410 dyld_instance->UpdateAllImageInfos();
411 // Return true to stop the target, false to just let the target run
412 return dyld_instance->GetStopWhenImagesChange();
413}
414
415bool
416DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
417{
418 Mutex::Locker locker(m_mutex);
Greg Clayton20d338f2010-11-18 05:57:03 +0000419
420 // the all image infos is already valid for this process stop ID
421 if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
422 return true;
423
Chris Lattner24943d22010-06-08 16:52:24 +0000424 m_dyld_all_image_infos.Clear();
425 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
426 {
Greg Clayton20d338f2010-11-18 05:57:03 +0000427 ByteOrder byte_order = m_process->GetByteOrder();
428 uint32_t addr_size = 4;
429 if (m_dyld_all_image_infos_addr > UINT32_MAX)
430 addr_size = 8;
431
Chris Lattner24943d22010-06-08 16:52:24 +0000432 uint8_t buf[256];
Greg Clayton20d338f2010-11-18 05:57:03 +0000433 DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
434 uint32_t offset = 0;
435
Jason Molenda1f3af542010-06-10 01:21:21 +0000436 const size_t count_v2 = sizeof (uint32_t) + // version
437 sizeof (uint32_t) + // infoArrayCount
438 addr_size + // infoArray
439 addr_size + // notification
440 addr_size + // processDetachedFromSharedRegion + libSystemInitialized + pad
441 addr_size; // dyldImageLoadAddress
442 const size_t count_v11 = count_v2 +
443 addr_size + // jitInfo
444 addr_size + // dyldVersion
445 addr_size + // errorMessage
446 addr_size + // terminationFlags
447 addr_size + // coreSymbolicationShmPage
448 addr_size + // systemOrderFlag
449 addr_size + // uuidArrayCount
450 addr_size + // uuidArray
451 addr_size + // dyldAllImageInfosAddress
452 addr_size + // initialImageCount
453 addr_size + // errorKind
454 addr_size + // errorClientOfDylibPath
455 addr_size + // errorTargetDylibPath
456 addr_size; // errorSymbol
457 assert (sizeof (buf) > count_v11);
458
459 int count;
Chris Lattner24943d22010-06-08 16:52:24 +0000460 Error error;
Jason Molenda1f3af542010-06-10 01:21:21 +0000461 if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4)
462 {
Jason Molenda1f3af542010-06-10 01:21:21 +0000463 m_dyld_all_image_infos.version = data.GetU32(&offset);
Greg Clayton20d338f2010-11-18 05:57:03 +0000464 // If anything in the high byte is set, we probably got the byte
465 // order incorrect (the process might not have it set correctly
466 // yet due to attaching to a program without a specified file).
467 if (m_dyld_all_image_infos.version & 0xff000000)
468 {
469 // We have guessed the wrong byte order. Swap it and try
470 // reading the version again.
471 if (byte_order == eByteOrderLittle)
472 byte_order = eByteOrderBig;
473 else
474 byte_order = eByteOrderLittle;
475
476 data.SetByteOrder (byte_order);
477 offset = 0;
478 m_dyld_all_image_infos.version = data.GetU32(&offset);
479 }
Jason Molenda1f3af542010-06-10 01:21:21 +0000480 }
481 else
482 {
483 return false;
484 }
485
486 if (m_dyld_all_image_infos.version >= 11)
487 count = count_v11;
488 else
489 count = count_v2;
490
Chris Lattner24943d22010-06-08 16:52:24 +0000491 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error);
492 if (bytes_read == count)
493 {
Greg Clayton20d338f2010-11-18 05:57:03 +0000494 offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000495 m_dyld_all_image_infos.version = data.GetU32(&offset);
496 m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
497 m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset);
498 m_dyld_all_image_infos.notification = data.GetPointer(&offset);
499 m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset);
Jason Molenda1f3af542010-06-10 01:21:21 +0000500 m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
501 // Adjust for padding.
502 offset += addr_size - 2;
503 m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset);
504 if (m_dyld_all_image_infos.version >= 11)
Chris Lattner24943d22010-06-08 16:52:24 +0000505 {
Jason Molenda1f3af542010-06-10 01:21:21 +0000506 offset += addr_size * 8;
507 uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset);
508
509 // When we started, we were given the actual address of the all_image_infos
510 // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in
511 // m_dyld_all_image_infos_addr and is the most accurate address we have.
512
513 // We read the dyld_all_image_infos struct from memory; it contains its own address.
514 // If the address in the struct does not match the actual address,
515 // the dyld we're looking at has been loaded at a different location (slid) from
516 // where it intended to load. The addresses in the dyld_all_image_infos struct
517 // are the original, non-slid addresses, and need to be adjusted. Most importantly
518 // the address of dyld and the notification address need to be adjusted.
519
520 if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr)
521 {
522 uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress;
523 uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress;
524 m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset;
525 m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
526 }
Chris Lattner24943d22010-06-08 16:52:24 +0000527 }
Greg Clayton20d338f2010-11-18 05:57:03 +0000528 m_dyld_all_image_infos_stop_id = m_process->GetStopID();
Chris Lattner24943d22010-06-08 16:52:24 +0000529 return true;
530 }
531 }
532 return false;
533}
534
535//----------------------------------------------------------------------
536// If we have found where the "_dyld_all_image_infos" lives in memory,
537// read the current info from it, and then update all image load
538// addresses (or lack thereof).
539//----------------------------------------------------------------------
540uint32_t
541DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
542{
Greg Claytone005f2c2010-11-06 01:53:30 +0000543 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
Chris Lattner24943d22010-06-08 16:52:24 +0000544 if (ReadAllImageInfosStructure ())
545 {
546 Mutex::Locker locker(m_mutex);
Greg Clayton20d338f2010-11-18 05:57:03 +0000547 if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
548 m_dyld_image_infos.size();
549
Chris Lattner24943d22010-06-08 16:52:24 +0000550 uint32_t idx;
Chris Lattner24943d22010-06-08 16:52:24 +0000551 uint32_t i = 0;
552 DYLDImageInfo::collection old_dyld_all_image_infos;
553 old_dyld_all_image_infos.swap(m_dyld_image_infos);
554
555 // If we made it here, we are assuming that the all dylib info data should
556 // be valid, lets read the info array.
Greg Clayton20d338f2010-11-18 05:57:03 +0000557 const ByteOrder endian = m_dyld.GetByteOrder();
558 const uint32_t addr_size = m_dyld.GetAddressByteSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000559
560 if (m_dyld_all_image_infos.dylib_info_count > 0)
561 {
562 if (m_dyld_all_image_infos.dylib_info_addr == 0)
563 {
564 // DYLD is updating the images right now...
565 }
566 else
567 {
568 m_dyld_image_infos.resize(m_dyld_all_image_infos.dylib_info_count);
569 const size_t count = m_dyld_image_infos.size() * 3 * addr_size;
570 DataBufferHeap info_data(count, 0);
571 Error error;
572 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos.dylib_info_addr,
573 info_data.GetBytes(),
574 info_data.GetByteSize(),
575 error);
576 if (bytes_read == count)
577 {
578 uint32_t info_data_offset = 0;
579 DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size);
580 for (i = 0; info_data_ref.ValidOffset(info_data_offset); i++)
581 {
582 assert (i < m_dyld_image_infos.size());
583 m_dyld_image_infos[i].address = info_data_ref.GetPointer(&info_data_offset);
584 lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset);
585 m_dyld_image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset);
586
587 char raw_path[PATH_MAX];
588 m_process->ReadMemory (path_addr, raw_path, sizeof(raw_path), error);
Greg Clayton537a7a82010-10-20 20:54:39 +0000589 m_dyld_image_infos[i].file_spec.SetFile(raw_path, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000590 }
591 assert(i == m_dyld_all_image_infos.dylib_info_count);
592
593 UpdateAllImageInfosHeaderAndLoadCommands();
594 }
595 else
596 {
597 DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
598 m_dyld_image_infos.clear();
599 }
600 }
601 }
602 else
603 {
604 m_dyld_image_infos.clear();
605 }
606
607 // If our new list is smaller than our old list, we have unloaded
608 // some shared libraries
Greg Claytonab429022010-12-12 21:03:32 +0000609 if (m_dyld_image_infos.size() != old_dyld_all_image_infos.size())
Chris Lattner24943d22010-06-08 16:52:24 +0000610 {
611 ModuleList unloaded_module_list;
Greg Claytonab429022010-12-12 21:03:32 +0000612 if (old_dyld_all_image_infos.size() == 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000613 {
Greg Claytonab429022010-12-12 21:03:32 +0000614 // This is the first time we are loading shared libraries,
615 // we need to make sure to trim anything that isn't in the
616 // m_dyld_image_infos out of the target module list since
617 // we might have shared libraries that got loaded from
618 // elsewhere due to DYLD_FRAMEWORK_PATH, or DYLD_LIBRARY_PATH
619 // environment variables...
620 ModuleList& images = m_process->GetTarget().GetImages();
621 const size_t num_images = images.GetSize();
622 for (idx = 0; idx < num_images; ++idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000623 {
Greg Claytonab429022010-12-12 21:03:32 +0000624 ModuleSP module_sp (images.GetModuleAtIndex (idx));
625
626 if (GetImageInfo (module_sp->GetFileSpec(), module_sp->GetUUID()) == NULL)
627 unloaded_module_list.AppendIfNeeded (module_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000628 }
629 }
Greg Claytonab429022010-12-12 21:03:32 +0000630 else
Greg Clayton9d2993d2010-11-03 04:08:06 +0000631 {
Greg Claytonab429022010-12-12 21:03:32 +0000632 uint32_t old_idx;
633 for (idx = 0; idx < old_dyld_all_image_infos.size(); ++idx)
Greg Clayton9d2993d2010-11-03 04:08:06 +0000634 {
Greg Claytonab429022010-12-12 21:03:32 +0000635 for (old_idx = idx; old_idx < old_dyld_all_image_infos.size(); ++old_idx)
Greg Clayton9d2993d2010-11-03 04:08:06 +0000636 {
Greg Claytonab429022010-12-12 21:03:32 +0000637 if (m_dyld_image_infos[idx].file_spec == old_dyld_all_image_infos[old_idx].file_spec)
638 {
639 old_dyld_all_image_infos[old_idx].address = LLDB_INVALID_ADDRESS;
640 break;
641 }
642 }
643 }
644
Greg Claytonab429022010-12-12 21:03:32 +0000645 for (old_idx = 0; old_idx < old_dyld_all_image_infos.size(); ++old_idx)
646 {
647 if (old_dyld_all_image_infos[old_idx].address != LLDB_INVALID_ADDRESS)
648 {
649 if (log)
650 old_dyld_all_image_infos[old_idx].PutToLog (log.get());
651 ModuleSP unload_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (old_dyld_all_image_infos[old_idx].file_spec));
652 if (unload_image_module_sp.get())
653 {
654 if (UnloadImageLoadAddress (unload_image_module_sp.get(), old_dyld_all_image_infos[old_idx]))
655 unloaded_module_list.AppendIfNeeded (unload_image_module_sp);
656 }
Greg Clayton9d2993d2010-11-03 04:08:06 +0000657 }
658 }
659 }
660
Chris Lattner24943d22010-06-08 16:52:24 +0000661 if (unloaded_module_list.GetSize() > 0)
Greg Clayton427f2902010-12-14 02:59:59 +0000662 {
663 if (log)
664 {
665 log->PutCString("Unloaded:");
666 unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload");
667 }
Chris Lattner24943d22010-06-08 16:52:24 +0000668 m_process->GetTarget().ModulesDidUnload (unloaded_module_list);
Greg Clayton427f2902010-12-14 02:59:59 +0000669 }
Chris Lattner24943d22010-06-08 16:52:24 +0000670 }
Greg Clayton9d2993d2010-11-03 04:08:06 +0000671 else
672 {
673 if (log)
Greg Claytone005f2c2010-11-06 01:53:30 +0000674 PutToLog(log.get());
Greg Clayton9d2993d2010-11-03 04:08:06 +0000675 }
Greg Clayton20d338f2010-11-18 05:57:03 +0000676 m_dyld_image_infos_stop_id = m_process->GetStopID();
Chris Lattner24943d22010-06-08 16:52:24 +0000677 }
678 else
679 {
680 m_dyld_image_infos.clear();
681 }
682
683 const uint32_t num_dylibs = m_dyld_image_infos.size();
684 if (num_dylibs > 0)
685 {
686 ModuleList loaded_module_list;
687 for (uint32_t idx = 0; idx<num_dylibs; ++idx)
688 {
Greg Claytoncf015052010-06-11 03:25:34 +0000689 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 +0000690 ModuleSP image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld_image_infos[idx].file_spec));
691 if (image_module_sp.get() == NULL || image_module_sp->GetArchitecture() != arch_spec)
692 {
693 image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec,
694 arch_spec,
695 &m_dyld_image_infos[idx].uuid);
696 }
697
698 if (image_module_sp)
699 {
Greg Clayton236c1c72010-09-07 23:40:05 +0000700 if (m_dyld_image_infos[idx].header.filetype == HeaderFileTypeDynamicLinkEditor)
701 image_module_sp->SetIsDynamicLinkEditor (true);
702
Chris Lattner24943d22010-06-08 16:52:24 +0000703 ObjectFile *objfile = image_module_sp->GetObjectFile ();
704 if (objfile)
705 {
706 SectionList *sections = objfile->GetSectionList();
707 if (sections)
708 {
709 ConstString commpage_dbstr("__commpage");
710 Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
711 if (commpage_section)
712 {
713 FileSpec objfile_file_spec(objfile->GetFileSpec());
714 ModuleSP commpage_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (objfile_file_spec, &commpage_dbstr));
715 if (commpage_image_module_sp.get() == NULL)
716 {
717 commpage_image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec,
718 arch_spec,
719 &m_dyld_image_infos[idx].uuid,
720 &commpage_dbstr,
721 objfile->GetOffset() + commpage_section->GetOffset());
722 UpdateCommPageLoadAddress(commpage_image_module_sp.get());
723 }
724 }
725 }
726 }
727
728 // UpdateImageLoadAddress will return true if any segments
729 // change load address. We need to check this so we don't
730 // mention that all loaded shared libraries are newly loaded
731 // each time we hit out dyld breakpoint since dyld will list all
732 // shared libraries each time.
733 if (UpdateImageLoadAddress (image_module_sp.get(), m_dyld_image_infos[idx]))
734 {
Greg Claytonab429022010-12-12 21:03:32 +0000735 loaded_module_list.AppendIfNeeded (image_module_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000736 }
737 }
738 }
Chris Lattner24943d22010-06-08 16:52:24 +0000739 if (loaded_module_list.GetSize() > 0)
740 {
741 // FIXME: This should really be in the Runtime handlers class, which should get
742 // called by the target's ModulesDidLoad, but we're doing it all locally for now
743 // to save time.
744 // Also, I'm assuming there can be only one libobjc dylib loaded...
745
Jim Inghamb66cd072010-09-28 01:25:32 +0000746 ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
747 if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
Chris Lattner24943d22010-06-08 16:52:24 +0000748 {
749 size_t num_modules = loaded_module_list.GetSize();
750 for (int i = 0; i < num_modules; i++)
751 {
Jim Inghamb66cd072010-09-28 01:25:32 +0000752 if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
Chris Lattner24943d22010-06-08 16:52:24 +0000753 {
Jim Inghamb66cd072010-09-28 01:25:32 +0000754 objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
Chris Lattner24943d22010-06-08 16:52:24 +0000755 break;
756 }
757 }
758 }
Greg Clayton427f2902010-12-14 02:59:59 +0000759 if (log)
760 loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidLoad");
Chris Lattner24943d22010-06-08 16:52:24 +0000761 m_process->GetTarget().ModulesDidLoad (loaded_module_list);
762 }
763 }
764 return m_dyld_image_infos.size();
765}
766
767//----------------------------------------------------------------------
768// Read a mach_header at ADDR into HEADER, and also fill in the load
769// command data into LOAD_COMMAND_DATA if it is non-NULL.
770//
771// Returns true if we succeed, false if we fail for any reason.
772//----------------------------------------------------------------------
773bool
Greg Clayton1674b122010-07-21 22:12:05 +0000774DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, mach_header *header, DataExtractor *load_command_data)
Chris Lattner24943d22010-06-08 16:52:24 +0000775{
Greg Clayton1674b122010-07-21 22:12:05 +0000776 DataBufferHeap header_bytes(sizeof(mach_header), 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000777 Error error;
778 size_t bytes_read = m_process->ReadMemory (addr,
779 header_bytes.GetBytes(),
780 header_bytes.GetByteSize(),
781 error);
Greg Clayton1674b122010-07-21 22:12:05 +0000782 if (bytes_read == sizeof(mach_header))
Chris Lattner24943d22010-06-08 16:52:24 +0000783 {
784 uint32_t offset = 0;
785 ::memset (header, 0, sizeof(header));
786
787 // Get the magic byte unswapped so we can figure out what we are dealing with
Greg Claytoncd548032011-02-01 01:31:41 +0000788 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4);
Chris Lattner24943d22010-06-08 16:52:24 +0000789 header->magic = data.GetU32(&offset);
790 lldb::addr_t load_cmd_addr = addr;
791 data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
792 switch (header->magic)
793 {
Greg Clayton1674b122010-07-21 22:12:05 +0000794 case llvm::MachO::HeaderMagic32:
795 case llvm::MachO::HeaderMagic32Swapped:
Chris Lattner24943d22010-06-08 16:52:24 +0000796 data.SetAddressByteSize(4);
Greg Clayton1674b122010-07-21 22:12:05 +0000797 load_cmd_addr += sizeof(mach_header);
Chris Lattner24943d22010-06-08 16:52:24 +0000798 break;
799
Greg Clayton1674b122010-07-21 22:12:05 +0000800 case llvm::MachO::HeaderMagic64:
801 case llvm::MachO::HeaderMagic64Swapped:
Chris Lattner24943d22010-06-08 16:52:24 +0000802 data.SetAddressByteSize(8);
Greg Clayton1674b122010-07-21 22:12:05 +0000803 load_cmd_addr += sizeof(mach_header_64);
Chris Lattner24943d22010-06-08 16:52:24 +0000804 break;
805
806 default:
807 return false;
808 }
809
810 // Read the rest of dyld's mach header
Greg Clayton1674b122010-07-21 22:12:05 +0000811 if (data.GetU32(&offset, &header->cputype, (sizeof(mach_header)/sizeof(uint32_t)) - 1))
Chris Lattner24943d22010-06-08 16:52:24 +0000812 {
813 if (load_command_data == NULL)
814 return true; // We were able to read the mach_header and weren't asked to read the load command bytes
815
816 DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));
817
818 size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr,
819 load_cmd_data_sp->GetBytes(),
820 load_cmd_data_sp->GetByteSize(),
821 error);
822
823 if (load_cmd_bytes_read == header->sizeofcmds)
824 {
825 // Set the load command data and also set the correct endian
826 // swap settings and the correct address size
827 load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
828 load_command_data->SetByteOrder(data.GetByteOrder());
829 load_command_data->SetAddressByteSize(data.GetAddressByteSize());
830 return true; // We successfully read the mach_header and the load command data
831 }
832
833 return false; // We weren't able to read the load command data
834 }
835 }
836 return false; // We failed the read the mach_header
837}
838
839
840//----------------------------------------------------------------------
841// Parse the load commands for an image
842//----------------------------------------------------------------------
843uint32_t
844DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, struct DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker)
845{
846 uint32_t offset = 0;
847 uint32_t cmd_idx;
848 Segment segment;
849 dylib_info.Clear (true);
850
851 for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++)
852 {
853 // Clear out any load command specific data from DYLIB_INFO since
854 // we are about to read it.
855
Greg Clayton1674b122010-07-21 22:12:05 +0000856 if (data.ValidOffsetForDataOfSize (offset, sizeof(load_command)))
Chris Lattner24943d22010-06-08 16:52:24 +0000857 {
Greg Clayton1674b122010-07-21 22:12:05 +0000858 load_command load_cmd;
Chris Lattner24943d22010-06-08 16:52:24 +0000859 uint32_t load_cmd_offset = offset;
860 load_cmd.cmd = data.GetU32 (&offset);
861 load_cmd.cmdsize = data.GetU32 (&offset);
862 switch (load_cmd.cmd)
863 {
Greg Clayton1674b122010-07-21 22:12:05 +0000864 case LoadCommandSegment32:
Chris Lattner24943d22010-06-08 16:52:24 +0000865 {
866 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
867 segment.addr = data.GetU32 (&offset);
868 segment.size = data.GetU32 (&offset);
869 dylib_info.segments.push_back (segment);
870 }
871 break;
872
Greg Clayton1674b122010-07-21 22:12:05 +0000873 case LoadCommandSegment64:
Chris Lattner24943d22010-06-08 16:52:24 +0000874 {
875 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
876 segment.addr = data.GetU64 (&offset);
877 segment.size = data.GetU64 (&offset);
878 dylib_info.segments.push_back (segment);
879 }
880 break;
881
Greg Clayton1674b122010-07-21 22:12:05 +0000882 case LoadCommandDynamicLinkerIdent:
Chris Lattner24943d22010-06-08 16:52:24 +0000883 if (lc_id_dylinker)
884 {
885 uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset);
886 const char *path = data.PeekCStr (name_offset);
Greg Clayton537a7a82010-10-20 20:54:39 +0000887 lc_id_dylinker->SetFile (path, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000888 }
889 break;
890
Greg Clayton1674b122010-07-21 22:12:05 +0000891 case LoadCommandUUID:
Chris Lattner24943d22010-06-08 16:52:24 +0000892 dylib_info.uuid.SetBytes(data.GetData (&offset, 16));
893 break;
894
895 default:
896 break;
897 }
898 // Set offset to be the beginning of the next load command.
899 offset = load_cmd_offset + load_cmd.cmdsize;
900 }
901 }
902 return cmd_idx;
903}
904
905//----------------------------------------------------------------------
906// Read the mach_header and load commands for each image that the
907// _dyld_all_image_infos structure points to and cache the results.
908//----------------------------------------------------------------------
909void
910DynamicLoaderMacOSXDYLD::UpdateAllImageInfosHeaderAndLoadCommands()
911{
912 uint32_t exe_idx = UINT32_MAX;
913 // Read any UUID values that we can get
914 for (uint32_t i = 0; i < m_dyld_all_image_infos.dylib_info_count; i++)
915 {
916 if (!m_dyld_image_infos[i].UUIDValid())
917 {
918 DataExtractor data; // Load command data
919 if (!ReadMachHeader (m_dyld_image_infos[i].address, &m_dyld_image_infos[i].header, &data))
920 continue;
921
922 ParseLoadCommands (data, m_dyld_image_infos[i], NULL);
923
Greg Clayton1674b122010-07-21 22:12:05 +0000924 if (m_dyld_image_infos[i].header.filetype == HeaderFileTypeExecutable)
Chris Lattner24943d22010-06-08 16:52:24 +0000925 exe_idx = i;
926 }
927 }
928
929 if (exe_idx < m_dyld_image_infos.size())
930 {
931 bool set_executable = false;
Greg Claytoncf015052010-06-11 03:25:34 +0000932 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 +0000933 ModuleSP exe_module_sp(m_process->GetTarget().GetExecutableModule());
934 if (exe_module_sp.get())
935 {
936 if (exe_module_sp->GetFileSpec() != m_dyld_image_infos[exe_idx].file_spec ||
937 exe_module_sp->GetArchitecture() != dyld_exe_arch_spec)
938 set_executable = true;
939 }
940 else
941 set_executable = true;
942
943 if (set_executable)
944 {
945 exe_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[exe_idx].file_spec,
946 dyld_exe_arch_spec,
947 &m_dyld_image_infos[exe_idx].uuid);
948 if (exe_module_sp.get())
949 {
950 // If we found the file where it purported to be, then it should
951 // be safe to load dependent images.
952 bool get_dependent_images = exe_module_sp->GetFileSpec() == m_dyld_image_infos[exe_idx].file_spec;
953
954 m_process->GetTarget().SetExecutableModule (exe_module_sp, get_dependent_images);
955 }
956 }
957 }
958}
959
960//----------------------------------------------------------------------
961// Dump a Segment to the file handle provided.
962//----------------------------------------------------------------------
963void
964DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const
965{
966 if (log)
967 log->Printf("\t\t%16s [0x%16.16llx - 0x%16.16llx)", name.AsCString(""), addr + slide, addr + slide + size);
968}
969
970const DynamicLoaderMacOSXDYLD::Segment *
971DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const
972{
973 const size_t num_segments = segments.size();
974 for (size_t i=0; i<num_segments; ++i)
975 {
976 if (segments[i].name == name)
977 return &segments[i];
978 }
979 return NULL;
980}
981
982
983//----------------------------------------------------------------------
984// Dump an image info structure to the file handle provided.
985//----------------------------------------------------------------------
986void
987DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const
988{
989 if (log == NULL)
990 return;
991 uint8_t *u = (uint8_t *)uuid.GetBytes();
992
993 if (address == LLDB_INVALID_ADDRESS)
994 {
995 if (u)
996 {
997 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)",
998 mod_date,
999 u[ 0], u[ 1], u[ 2], u[ 3],
1000 u[ 4], u[ 5], u[ 6], u[ 7],
1001 u[ 8], u[ 9], u[10], u[11],
1002 u[12], u[13], u[14], u[15],
1003 file_spec.GetDirectory().AsCString(),
1004 file_spec.GetFilename().AsCString());
1005 }
1006 else
1007 log->Printf("\t modtime=0x%8.8llx path='%s/%s' (UNLOADED)",
1008 mod_date,
1009 file_spec.GetDirectory().AsCString(),
1010 file_spec.GetFilename().AsCString());
1011 }
1012 else
1013 {
1014 if (u)
1015 {
1016 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'",
1017 address,
1018 mod_date,
1019 u[ 0], u[ 1], u[ 2], u[ 3],
1020 u[ 4], u[ 5], u[ 6], u[ 7],
1021 u[ 8], u[ 9], u[10], u[11],
1022 u[12], u[13], u[14], u[15],
1023 file_spec.GetDirectory().AsCString(),
1024 file_spec.GetFilename().AsCString());
1025 }
1026 else
1027 {
1028 log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'",
1029 address,
1030 mod_date,
1031 file_spec.GetDirectory().AsCString(),
1032 file_spec.GetFilename().AsCString());
1033
1034 }
1035 for (uint32_t i=0; i<segments.size(); ++i)
1036 segments[i].PutToLog(log, slide);
1037 }
1038}
1039
1040//----------------------------------------------------------------------
1041// Dump the _dyld_all_image_infos members and all current image infos
1042// that we have parsed to the file handle provided.
1043//----------------------------------------------------------------------
1044void
1045DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const
1046{
1047 if (log == NULL)
1048 return;
1049
1050 Mutex::Locker locker(m_mutex);
1051 log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }",
1052 m_dyld_all_image_infos.version,
1053 m_dyld_all_image_infos.dylib_info_count,
1054 (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
1055 (uint64_t)m_dyld_all_image_infos.notification);
1056 size_t i;
1057 const size_t count = m_dyld_image_infos.size();
1058 if (count > 0)
1059 {
Greg Clayton9d2993d2010-11-03 04:08:06 +00001060 log->PutCString("Loaded:");
Chris Lattner24943d22010-06-08 16:52:24 +00001061 for (i = 0; i<count; i++)
1062 m_dyld_image_infos[i].PutToLog(log);
1063 }
1064}
1065
Chris Lattner24943d22010-06-08 16:52:24 +00001066void
1067DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process)
1068{
1069 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1070 Clear(true);
1071 m_process = process;
Greg Clayton58e844b2010-12-08 05:08:21 +00001072 m_process->GetTarget().GetSectionLoadList().Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001073}
1074
1075bool
1076DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint ()
1077{
1078 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1079 if (m_break_id == LLDB_INVALID_BREAK_ID)
1080 {
1081 if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS)
1082 {
1083 Address so_addr;
1084 // Set the notification breakpoint and install a breakpoint
1085 // callback function that will get called each time the
1086 // breakpoint gets hit. We will use this to track when shared
1087 // libraries get loaded/unloaded.
1088
Greg Claytoneea26402010-09-14 23:36:40 +00001089 if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr))
Chris Lattner24943d22010-06-08 16:52:24 +00001090 {
1091 Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
1092 dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true);
1093 m_break_id = dyld_break->GetID();
1094 }
1095 }
1096 }
1097 return m_break_id != LLDB_INVALID_BREAK_ID;
1098}
1099
Jim Ingham7508e732010-08-09 23:31:02 +00001100//----------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001101// Member function that gets called when the process state changes.
1102//----------------------------------------------------------------------
1103void
1104DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state)
1105{
1106 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state));
1107 switch (state)
1108 {
1109 case eStateAttaching:
1110 case eStateLaunching:
1111 case eStateInvalid:
1112 case eStateUnloaded:
1113 case eStateExited:
1114 case eStateDetached:
1115 Clear(false);
1116 break;
1117
1118 case eStateStopped:
1119 // Keep trying find dyld and set our notification breakpoint each time
1120 // we stop until we succeed
1121 if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
1122 {
1123 if (NeedToLocateDYLD ())
1124 LocateDYLD ();
1125
1126 SetNotificationBreakpoint ();
1127 }
1128 break;
1129
1130 case eStateRunning:
1131 case eStateStepping:
1132 case eStateCrashed:
1133 case eStateSuspended:
1134 break;
1135
1136 default:
1137 break;
1138 }
1139}
1140
1141ThreadPlanSP
1142DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
1143{
1144 ThreadPlanSP thread_plan_sp;
1145 StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
1146 const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
1147 Symbol *current_symbol = current_context.symbol;
Greg Claytone005f2c2010-11-06 01:53:30 +00001148 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +00001149
1150 if (current_symbol != NULL)
1151 {
1152 if (current_symbol->IsTrampoline())
1153 {
Jim Ingham17454cf2010-09-14 22:03:00 +00001154 const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
1155
Chris Lattner24943d22010-06-08 16:52:24 +00001156 if (trampoline_name)
1157 {
1158 SymbolContextList target_symbols;
1159 ModuleList &images = thread.GetProcess().GetTarget().GetImages();
1160 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
1161 // FIXME - Make the Run to Address take multiple addresses, and
1162 // run to any of them.
Jim Ingham17454cf2010-09-14 22:03:00 +00001163 uint32_t num_symbols = target_symbols.GetSize();
1164 if (num_symbols == 1)
Chris Lattner24943d22010-06-08 16:52:24 +00001165 {
1166 SymbolContext context;
1167 AddressRange addr_range;
1168 if (target_symbols.GetContextAtIndex(0, context))
1169 {
1170 context.GetAddressRange (eSymbolContextEverything, addr_range);
1171 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others));
1172 }
Jim Ingham17454cf2010-09-14 22:03:00 +00001173 else
Chris Lattner24943d22010-06-08 16:52:24 +00001174 {
Jim Ingham17454cf2010-09-14 22:03:00 +00001175 if (log)
1176 log->Printf ("Couldn't resolve the symbol context.");
1177 }
1178 }
1179 else if (num_symbols > 1)
1180 {
1181 std::vector<lldb::addr_t> addresses;
1182 addresses.resize (num_symbols);
1183 for (uint32_t i = 0; i < num_symbols; i++)
1184 {
1185 SymbolContext context;
1186 AddressRange addr_range;
1187 if (target_symbols.GetContextAtIndex(i, context))
1188 {
1189 context.GetAddressRange (eSymbolContextEverything, addr_range);
Greg Claytoneea26402010-09-14 23:36:40 +00001190 lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
Jim Ingham17454cf2010-09-14 22:03:00 +00001191 addresses[i] = load_addr;
1192 }
1193 }
1194 if (addresses.size() > 0)
1195 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others));
1196 else
1197 {
1198 if (log)
1199 log->Printf ("Couldn't resolve the symbol contexts.");
Chris Lattner24943d22010-06-08 16:52:24 +00001200 }
1201 }
1202 else
1203 {
Chris Lattner24943d22010-06-08 16:52:24 +00001204 if (log)
1205 {
1206 log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
1207 }
1208 }
1209 }
1210 }
1211 }
Jim Ingham17454cf2010-09-14 22:03:00 +00001212 else
1213 {
1214 if (log)
1215 log->Printf ("Could not find symbol for step through.");
1216 }
Chris Lattner24943d22010-06-08 16:52:24 +00001217
Chris Lattner24943d22010-06-08 16:52:24 +00001218 return thread_plan_sp;
1219}
1220
Greg Clayton0baa3942010-11-04 01:54:29 +00001221Error
1222DynamicLoaderMacOSXDYLD::CanLoadImage ()
1223{
1224 Error error;
1225 // In order for us to tell if we can load a shared library we verify that
1226 // the dylib_info_addr isn't zero (which means no shared libraries have
1227 // been set yet, or dyld is currently mucking with the shared library list).
1228 if (ReadAllImageInfosStructure ())
1229 {
1230 // TODO: also check the _dyld_global_lock_held variable in libSystem.B.dylib?
1231 // TODO: check the malloc lock?
1232 // TODO: check the objective C lock?
1233 if (m_dyld_all_image_infos.dylib_info_addr != 0)
1234 return error; // Success
1235 }
1236
1237 error.SetErrorString("unsafe to load or unload shared libraries");
1238 return error;
1239}
1240
Chris Lattner24943d22010-06-08 16:52:24 +00001241void
1242DynamicLoaderMacOSXDYLD::Initialize()
1243{
1244 PluginManager::RegisterPlugin (GetPluginNameStatic(),
1245 GetPluginDescriptionStatic(),
1246 CreateInstance);
1247}
1248
1249void
1250DynamicLoaderMacOSXDYLD::Terminate()
1251{
1252 PluginManager::UnregisterPlugin (CreateInstance);
1253}
1254
1255
1256const char *
1257DynamicLoaderMacOSXDYLD::GetPluginNameStatic()
1258{
1259 return "dynamic-loader.macosx-dyld";
1260}
1261
1262const char *
1263DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic()
1264{
1265 return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes.";
1266}
1267
1268
1269//------------------------------------------------------------------
1270// PluginInterface protocol
1271//------------------------------------------------------------------
1272const char *
1273DynamicLoaderMacOSXDYLD::GetPluginName()
1274{
1275 return "DynamicLoaderMacOSXDYLD";
1276}
1277
1278const char *
1279DynamicLoaderMacOSXDYLD::GetShortPluginName()
1280{
1281 return GetPluginNameStatic();
1282}
1283
1284uint32_t
1285DynamicLoaderMacOSXDYLD::GetPluginVersion()
1286{
1287 return 1;
1288}
1289
1290void
1291DynamicLoaderMacOSXDYLD::GetPluginCommandHelp (const char *command, Stream *strm)
1292{
1293}
1294
1295Error
1296DynamicLoaderMacOSXDYLD::ExecutePluginCommand (Args &command, Stream *strm)
1297{
1298 Error error;
1299 error.SetErrorString("No plug-in command are currently supported.");
1300 return error;
1301}
1302
1303Log *
1304DynamicLoaderMacOSXDYLD::EnablePluginLogging (Stream *strm, Args &command)
1305{
1306 return NULL;
1307}
1308
1309