1 //===-- DynamicLoaderDarwin.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/Debugger.h"
14 #include "lldb/Core/Log.h"
15 #include "lldb/Core/Module.h"
16 #include "lldb/Core/ModuleSpec.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Section.h"
19 #include "lldb/Core/State.h"
20 #include "lldb/Expression/DiagnosticManager.h"
21 #include "lldb/Symbol/ClangASTContext.h"
22 #include "lldb/Symbol/Function.h"
23 #include "lldb/Symbol/ObjectFile.h"
24 #include "lldb/Target/ABI.h"
25 #include "lldb/Target/ObjCLanguageRuntime.h"
26 #include "lldb/Target/RegisterContext.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Target/Thread.h"
30 #include "lldb/Target/ThreadPlanCallFunction.h"
31 #include "lldb/Target/ThreadPlanRunToAddress.h"
32 
33 #include "DynamicLoaderDarwin.h"
34 
35 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
36 #ifdef ENABLE_DEBUG_PRINTF
37 #include <stdio.h>
38 #define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
39 #else
40 #define DEBUG_PRINTF(fmt, ...)
41 #endif
42 
43 #ifndef __APPLE__
44 #include "Utility/UuidCompatibility.h"
45 #else
46 #include <uuid/uuid.h>
47 #endif
48 
49 using namespace lldb;
50 using namespace lldb_private;
51 
52 
53 //----------------------------------------------------------------------
54 // Constructor
55 //----------------------------------------------------------------------
56 DynamicLoaderDarwin::DynamicLoaderDarwin (Process* process)
57     : DynamicLoader(process),
58       m_dyld_module_wp(),
59       m_libpthread_module_wp(),
60       m_pthread_getspecific_addr(),
61       m_tid_to_tls_map(),
62       m_dyld_image_infos(),
63       m_dyld_image_infos_stop_id(UINT32_MAX),
64       m_dyld(),
65       m_mutex()
66 {
67 }
68 
69 //----------------------------------------------------------------------
70 // Destructor
71 //----------------------------------------------------------------------
72 DynamicLoaderDarwin::~DynamicLoaderDarwin()
73 {
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 //------------------------------------------------------------------
82 void
83 DynamicLoaderDarwin::DidAttach ()
84 {
85     PrivateInitialize(m_process);
86     DoInitialImageFetch ();
87     SetNotificationBreakpoint ();
88 }
89 
90 //------------------------------------------------------------------
91 /// Called after attaching a process.
92 ///
93 /// Allow DynamicLoader plug-ins to execute some code after
94 /// attaching to a process.
95 //------------------------------------------------------------------
96 void
97 DynamicLoaderDarwin::DidLaunch ()
98 {
99     PrivateInitialize(m_process);
100     DoInitialImageFetch ();
101     SetNotificationBreakpoint ();
102 }
103 
104 
105 //----------------------------------------------------------------------
106 // Clear out the state of this class.
107 //----------------------------------------------------------------------
108 void
109 DynamicLoaderDarwin::Clear (bool clear_process)
110 {
111     std::lock_guard<std::recursive_mutex> guard(m_mutex);
112     if (clear_process)
113         m_process = NULL;
114     m_dyld_image_infos.clear();
115     m_dyld_image_infos_stop_id = UINT32_MAX;
116     m_dyld.Clear(false);
117 }
118 
119 ModuleSP
120 DynamicLoaderDarwin::FindTargetModuleForImageInfo (ImageInfo &image_info, bool can_create, bool *did_create_ptr)
121 {
122     if (did_create_ptr)
123         *did_create_ptr = false;
124 
125     Target &target = m_process->GetTarget();
126     const ModuleList &target_images = target.GetImages();
127     ModuleSpec module_spec (image_info.file_spec);
128     module_spec.GetUUID() = image_info.uuid;
129     ModuleSP module_sp (target_images.FindFirstModule (module_spec));
130 
131     if (module_sp && !module_spec.GetUUID().IsValid() && !module_sp->GetUUID().IsValid())
132     {
133         // No UUID, we must rely upon the cached module modification
134         // time and the modification time of the file on disk
135         if (module_sp->GetModificationTime() != module_sp->GetFileSpec().GetModificationTime())
136             module_sp.reset();
137     }
138 
139     if (!module_sp)
140     {
141         if (can_create)
142         {
143             module_sp = target.GetSharedModule (module_spec);
144             if (!module_sp || module_sp->GetObjectFile() == NULL)
145                 module_sp = m_process->ReadModuleFromMemory (image_info.file_spec, image_info.address);
146 
147             if (did_create_ptr)
148                 *did_create_ptr = (bool) module_sp;
149         }
150     }
151     return module_sp;
152 }
153 
154 void
155 DynamicLoaderDarwin::UnloadImages (const std::vector<lldb::addr_t> &solib_addresses)
156 {
157     std::lock_guard<std::recursive_mutex> guard(m_mutex);
158     if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
159         return;
160 
161     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
162     Target &target = m_process->GetTarget();
163     if (log)
164         log->Printf ("Removing %" PRId64 " modules.", (uint64_t) solib_addresses.size());
165 
166     ModuleList unloaded_module_list;
167 
168     for (addr_t solib_addr : solib_addresses)
169     {
170         Address header;
171         if (header.SetLoadAddress (solib_addr, &target))
172         {
173             if (header.GetOffset() == 0)
174             {
175                 ModuleSP module_to_remove (header.GetModule());
176                 if (module_to_remove.get())
177                 {
178                     if (log)
179                         log->Printf ("Removing module at address 0x%" PRIx64, solib_addr);
180                     // remove the sections from the Target
181                     UnloadSections (module_to_remove);
182                     // add this to the list of modules to remove
183                     unloaded_module_list.AppendIfNeeded (module_to_remove);
184                     // remove the entry from the m_dyld_image_infos
185                     ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
186                     for (pos = m_dyld_image_infos.begin(); pos != end; pos++)
187                     {
188                         if (solib_addr == (*pos).address)
189                         {
190                             m_dyld_image_infos.erase(pos);
191                             break;
192                         }
193                     }
194                 }
195             }
196         }
197     }
198 
199     if (unloaded_module_list.GetSize() > 0)
200     {
201         if (log)
202         {
203             log->PutCString("Unloaded:");
204             unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderDarwin::UnloadModules");
205         }
206         m_process->GetTarget().GetImages().Remove (unloaded_module_list);
207         m_dyld_image_infos_stop_id = m_process->GetStopID();
208     }
209 }
210 
211 void
212 DynamicLoaderDarwin::UnloadAllImages ()
213 {
214     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
215     ModuleList unloaded_modules_list;
216 
217     Target &target = m_process->GetTarget();
218     const ModuleList &target_modules = target.GetImages();
219     std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
220 
221     size_t num_modules = target_modules.GetSize();
222     ModuleSP dyld_sp (GetDYLDModule());
223 
224     for (size_t i = 0; i < num_modules; i++)
225     {
226         ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked (i);
227 
228         // Don't remove dyld - else we'll lose our breakpoint notifying us about libraries
229         // being re-loaded...
230         if (module_sp.get() != nullptr
231             && module_sp.get() != dyld_sp.get())
232         {
233             UnloadSections (module_sp);
234             unloaded_modules_list.Append (module_sp);
235         }
236     }
237 
238     if (unloaded_modules_list.GetSize() != 0)
239     {
240         if (log)
241         {
242             log->PutCString("Unloaded:");
243             unloaded_modules_list.LogUUIDAndPaths (log, "DynamicLoaderDarwin::UnloadAllImages");
244         }
245         target.GetImages().Remove(unloaded_modules_list);
246         m_dyld_image_infos.clear();
247         m_dyld_image_infos_stop_id = m_process->GetStopID();
248     }
249 }
250 
251 //----------------------------------------------------------------------
252 // Update the load addresses for all segments in MODULE using the
253 // updated INFO that is passed in.
254 //----------------------------------------------------------------------
255 bool
256 DynamicLoaderDarwin::UpdateImageLoadAddress (Module *module, ImageInfo& info)
257 {
258     bool changed = false;
259     if (module)
260     {
261         ObjectFile *image_object_file = module->GetObjectFile();
262         if (image_object_file)
263         {
264             SectionList *section_list = image_object_file->GetSectionList ();
265             if (section_list)
266             {
267                 std::vector<uint32_t> inaccessible_segment_indexes;
268                 // We now know the slide amount, so go through all sections
269                 // and update the load addresses with the correct values.
270                 const size_t num_segments = info.segments.size();
271                 for (size_t i=0; i<num_segments; ++i)
272                 {
273                     // Only load a segment if it has protections. Things like
274                     // __PAGEZERO don't have any protections, and they shouldn't
275                     // be slid
276                     SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
277 
278                     if (info.segments[i].maxprot == 0)
279                     {
280                         inaccessible_segment_indexes.push_back(i);
281                     }
282                     else
283                     {
284                         const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide;
285                         static ConstString g_section_name_LINKEDIT ("__LINKEDIT");
286 
287                         if (section_sp)
288                         {
289                             // __LINKEDIT sections from files in the shared cache
290                             // can overlap so check to see what the segment name is
291                             // and pass "false" so we don't warn of overlapping
292                             // "Section" objects, and "true" for all other sections.
293                             const bool warn_multiple = section_sp->GetName() != g_section_name_LINKEDIT;
294 
295                             changed = m_process->GetTarget().SetSectionLoadAddress (section_sp, new_section_load_addr, warn_multiple);
296                         }
297                         else
298                         {
299                             Host::SystemLog (Host::eSystemLogWarning,
300                                              "warning: unable to find and load segment named '%s' at 0x%" PRIx64 " in '%s' in macosx dynamic loader plug-in.\n",
301                                              info.segments[i].name.AsCString("<invalid>"),
302                                              (uint64_t)new_section_load_addr,
303                                              image_object_file->GetFileSpec().GetPath().c_str());
304                         }
305                     }
306                 }
307 
308                 // If the loaded the file (it changed) and we have segments that
309                 // are not readable or writeable, add them to the invalid memory
310                 // region cache for the process. This will typically only be
311                 // the __PAGEZERO segment in the main executable. We might be able
312                 // to apply this more generally to more sections that have no
313                 // protections in the future, but for now we are going to just
314                 // do __PAGEZERO.
315                 if (changed && !inaccessible_segment_indexes.empty())
316                 {
317                     for (uint32_t i=0; i<inaccessible_segment_indexes.size(); ++i)
318                     {
319                         const uint32_t seg_idx = inaccessible_segment_indexes[i];
320                         SectionSP section_sp(section_list->FindSectionByName(info.segments[seg_idx].name));
321 
322                         if (section_sp)
323                         {
324                             static ConstString g_pagezero_section_name("__PAGEZERO");
325                             if (g_pagezero_section_name == section_sp->GetName())
326                             {
327                                 // __PAGEZERO never slides...
328                                 const lldb::addr_t vmaddr = info.segments[seg_idx].vmaddr;
329                                 const lldb::addr_t vmsize = info.segments[seg_idx].vmsize;
330                                 Process::LoadRange pagezero_range (vmaddr, vmsize);
331                                 m_process->AddInvalidMemoryRegion(pagezero_range);
332                             }
333                         }
334                     }
335                 }
336             }
337         }
338     }
339     // We might have an in memory image that was loaded as soon as it was created
340     if (info.load_stop_id == m_process->GetStopID())
341         changed = true;
342     else if (changed)
343     {
344         // Update the stop ID when this library was updated
345         info.load_stop_id = m_process->GetStopID();
346     }
347     return changed;
348 }
349 
350 //----------------------------------------------------------------------
351 // Unload the segments in MODULE using the INFO that is passed in.
352 //----------------------------------------------------------------------
353 bool
354 DynamicLoaderDarwin::UnloadModuleSections (Module *module, ImageInfo& info)
355 {
356     bool changed = false;
357     if (module)
358     {
359         ObjectFile *image_object_file = module->GetObjectFile();
360         if (image_object_file)
361         {
362             SectionList *section_list = image_object_file->GetSectionList ();
363             if (section_list)
364             {
365                 const size_t num_segments = info.segments.size();
366                 for (size_t i=0; i<num_segments; ++i)
367                 {
368                     SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
369                     if (section_sp)
370                     {
371                         const addr_t old_section_load_addr = info.segments[i].vmaddr + info.slide;
372                         if (m_process->GetTarget().SetSectionUnloaded (section_sp, old_section_load_addr))
373                             changed = true;
374                     }
375                     else
376                     {
377                         Host::SystemLog (Host::eSystemLogWarning,
378                                          "warning: unable to find and unload segment named '%s' in '%s' in macosx dynamic loader plug-in.\n",
379                                          info.segments[i].name.AsCString("<invalid>"),
380                                          image_object_file->GetFileSpec().GetPath().c_str());
381                     }
382                 }
383             }
384         }
385     }
386     return changed;
387 }
388 
389 
390 // Given a JSON dictionary (from debugserver, most likely) of binary images loaded in the inferior
391 // process, add the images to the ImageInfo collection.
392 
393 bool
394 DynamicLoaderDarwin::JSONImageInformationIntoImageInfo (StructuredData::ObjectSP image_details, ImageInfo::collection &image_infos)
395 {
396     StructuredData::ObjectSP images_sp = image_details->GetAsDictionary()->GetValueForKey("images");
397     if (images_sp.get() == nullptr)
398         return false;
399 
400     image_infos.resize (images_sp->GetAsArray()->GetSize());
401 
402     for (size_t i = 0; i < image_infos.size(); i++)
403     {
404         StructuredData::ObjectSP image_sp = images_sp->GetAsArray()->GetItemAtIndex(i);
405         if (image_sp.get() == nullptr || image_sp->GetAsDictionary() == nullptr)
406             return false;
407         StructuredData::Dictionary *image = image_sp->GetAsDictionary();
408         if (image->HasKey("load_address") == false
409             || image->HasKey("pathname") == false
410             || image->HasKey("mod_date") == false
411             || image->HasKey("mach_header") == false
412             || image->GetValueForKey("mach_header")->GetAsDictionary() == nullptr
413             || image->HasKey("segments") == false
414             || image->GetValueForKey("segments")->GetAsArray() == nullptr
415             || image->HasKey("uuid") == false )
416         {
417             return false;
418         }
419         image_infos[i].address = image->GetValueForKey("load_address")->GetAsInteger()->GetValue();
420         image_infos[i].mod_date = image->GetValueForKey("mod_date")->GetAsInteger()->GetValue();
421         image_infos[i].file_spec.SetFile(image->GetValueForKey("pathname")->GetAsString()->GetValue().c_str(), false);
422 
423         StructuredData::Dictionary *mh = image->GetValueForKey("mach_header")->GetAsDictionary();
424         image_infos[i].header.magic = mh->GetValueForKey("magic")->GetAsInteger()->GetValue();
425         image_infos[i].header.cputype = mh->GetValueForKey("cputype")->GetAsInteger()->GetValue();
426         image_infos[i].header.cpusubtype = mh->GetValueForKey("cpusubtype")->GetAsInteger()->GetValue();
427         image_infos[i].header.filetype = mh->GetValueForKey("filetype")->GetAsInteger()->GetValue();
428 
429         if (image->HasKey("min_version_os_name"))
430         {
431             std::string os_name = image->GetValueForKey("min_version_os_name")->GetAsString()->GetValue();
432             if (os_name == "macosx")
433                 image_infos[i].os_type = llvm::Triple::MacOSX;
434             else if (os_name == "ios" || os_name == "iphoneos")
435                 image_infos[i].os_type = llvm::Triple::IOS;
436             else if (os_name == "tvos")
437                 image_infos[i].os_type = llvm::Triple::TvOS;
438             else if (os_name == "watchos")
439                 image_infos[i].os_type = llvm::Triple::WatchOS;
440         }
441         if (image->HasKey("min_version_os_sdk"))
442         {
443             image_infos[i].min_version_os_sdk = image->GetValueForKey("min_version_os_sdk")->GetAsString()->GetValue();
444         }
445 
446         // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't currently send them
447         // in the reply.
448 
449         if (mh->HasKey("flags"))
450             image_infos[i].header.flags = mh->GetValueForKey("flags")->GetAsInteger()->GetValue();
451         else
452             image_infos[i].header.flags = 0;
453 
454         if (mh->HasKey("ncmds"))
455             image_infos[i].header.ncmds = mh->GetValueForKey("ncmds")->GetAsInteger()->GetValue();
456         else
457             image_infos[i].header.ncmds = 0;
458 
459         if (mh->HasKey("sizeofcmds"))
460             image_infos[i].header.sizeofcmds = mh->GetValueForKey("sizeofcmds")->GetAsInteger()->GetValue();
461         else
462             image_infos[i].header.sizeofcmds = 0;
463 
464         StructuredData::Array *segments = image->GetValueForKey("segments")->GetAsArray();
465         uint32_t segcount = segments->GetSize();
466         for (size_t j = 0; j < segcount; j++)
467         {
468             Segment segment;
469             StructuredData::Dictionary *seg = segments->GetItemAtIndex(j)->GetAsDictionary();
470             segment.name = ConstString(seg->GetValueForKey("name")->GetAsString()->GetValue().c_str());
471             segment.vmaddr = seg->GetValueForKey("vmaddr")->GetAsInteger()->GetValue();
472             segment.vmsize = seg->GetValueForKey("vmsize")->GetAsInteger()->GetValue();
473             segment.fileoff = seg->GetValueForKey("fileoff")->GetAsInteger()->GetValue();
474             segment.filesize = seg->GetValueForKey("filesize")->GetAsInteger()->GetValue();
475             segment.maxprot = seg->GetValueForKey("maxprot")->GetAsInteger()->GetValue();
476 
477             // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't currently send them
478             // in the reply.
479 
480             if (seg->HasKey("initprot"))
481                 segment.initprot = seg->GetValueForKey("initprot")->GetAsInteger()->GetValue();
482             else
483                 segment.initprot = 0;
484 
485             if (seg->HasKey("flags"))
486                 segment.flags = seg->GetValueForKey("flags")->GetAsInteger()->GetValue();
487             else
488                 segment.flags = 0;
489 
490             if (seg->HasKey("nsects"))
491                 segment.nsects = seg->GetValueForKey("nsects")->GetAsInteger()->GetValue();
492             else
493                 segment.nsects = 0;
494 
495             image_infos[i].segments.push_back (segment);
496         }
497 
498         image_infos[i].uuid.SetFromCString (image->GetValueForKey("uuid")->GetAsString()->GetValue().c_str());
499 
500         // All sections listed in the dyld image info structure will all
501         // either be fixed up already, or they will all be off by a single
502         // slide amount that is determined by finding the first segment
503         // that is at file offset zero which also has bytes (a file size
504         // that is greater than zero) in the object file.
505 
506         // Determine the slide amount (if any)
507         const size_t num_sections = image_infos[i].segments.size();
508         for (size_t k = 0; k < num_sections; ++k)
509         {
510             // Iterate through the object file sections to find the
511             // first section that starts of file offset zero and that
512             // has bytes in the file...
513             if ((image_infos[i].segments[k].fileoff == 0 && image_infos[i].segments[k].filesize > 0)
514                 || (image_infos[i].segments[k].name == ConstString("__TEXT")))
515             {
516                 image_infos[i].slide = image_infos[i].address - image_infos[i].segments[k].vmaddr;
517                 // We have found the slide amount, so we can exit
518                 // this for loop.
519                 break;
520             }
521         }
522     }
523 
524  return true;
525 }
526 
527 void
528 DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos (ImageInfo::collection &image_infos)
529 {
530     uint32_t exe_idx = UINT32_MAX;
531     uint32_t dyld_idx = UINT32_MAX;
532     Target &target = m_process->GetTarget();
533     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
534     ConstString g_dyld_sim_filename ("dyld_sim");
535 
536     ArchSpec target_arch = target.GetArchitecture();
537     const size_t image_infos_size = image_infos.size();
538     for (size_t i = 0; i < image_infos_size; i++)
539     {
540         if (image_infos[i].header.filetype == llvm::MachO::MH_DYLINKER)
541         {
542             // In a "simulator" process (an x86 process that is ios/tvos/watchos)
543             // we will have two dyld modules -- a "dyld" that we want to keep track of,
544             // and a "dyld_sim" which we don't need to keep track of here.
545             // If the target is an x86 system and the OS of the dyld binary is
546             // ios/tvos/watchos, then we are looking at dyld_sym.
547 
548             // debugserver has only recently (late 2016) started sending up the
549             // os type for each binary it sees -- so if we don't have an os
550             // type, use a filename check as our next best guess.
551             if (image_infos[i].os_type == llvm::Triple::OSType::UnknownOS)
552             {
553                 if (image_infos[i].file_spec.GetFilename() != g_dyld_sim_filename)
554                 {
555                     dyld_idx = i;
556                 }
557             }
558             else if (target_arch.GetTriple().getArch() == llvm::Triple::x86
559                      || target_arch.GetTriple().getArch() == llvm::Triple::x86_64)
560             {
561                 if (image_infos[i].os_type != llvm::Triple::OSType::IOS
562                     && image_infos[i].os_type != llvm::Triple::TvOS
563                     && image_infos[i].os_type != llvm::Triple::WatchOS)
564                 {
565                     dyld_idx = i;
566                 }
567             }
568         }
569         else if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE)
570         {
571             exe_idx = i;
572         }
573     }
574 
575     if (exe_idx != UINT32_MAX)
576     {
577         const bool can_create = true;
578         ModuleSP exe_module_sp (FindTargetModuleForImageInfo (image_infos[exe_idx], can_create, NULL));
579         if (exe_module_sp)
580         {
581             if (log)
582                 log->Printf ("Found executable module: %s", exe_module_sp->GetFileSpec().GetPath().c_str());
583             target.GetImages().AppendIfNeeded (exe_module_sp);
584             UpdateImageLoadAddress (exe_module_sp.get(), image_infos[exe_idx]);
585             if (exe_module_sp.get() != target.GetExecutableModulePointer())
586             {
587                 const bool get_dependent_images = false;
588                 target.SetExecutableModule (exe_module_sp, get_dependent_images);
589             }
590         }
591     }
592 
593     if (dyld_idx != UINT32_MAX)
594     {
595         const bool can_create = true;
596         ModuleSP dyld_sp = FindTargetModuleForImageInfo (image_infos[dyld_idx], can_create, NULL);
597         if (dyld_sp.get())
598         {
599             if (log)
600                 log->Printf ("Found dyld module: %s", dyld_sp->GetFileSpec().GetPath().c_str());
601             target.GetImages().AppendIfNeeded (dyld_sp);
602             UpdateImageLoadAddress (dyld_sp.get(), image_infos[dyld_idx]);
603             SetDYLDModule (dyld_sp);
604         }
605     }
606 }
607 
608 void
609 DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo (ImageInfo &image_info)
610 {
611     if (image_info.header.filetype == llvm::MachO::MH_DYLINKER)
612     {
613         const bool can_create = true;
614         ModuleSP dyld_sp = FindTargetModuleForImageInfo (image_info, can_create, NULL);
615         if (dyld_sp.get())
616         {
617             Target &target = m_process->GetTarget();
618             target.GetImages().AppendIfNeeded (dyld_sp);
619             UpdateImageLoadAddress (dyld_sp.get(), image_info);
620             SetDYLDModule (dyld_sp);
621         }
622     }
623 }
624 
625 void
626 DynamicLoaderDarwin::SetDYLDModule (lldb::ModuleSP &dyld_module_sp)
627 {
628     m_dyld_module_wp = dyld_module_sp;
629 }
630 
631 ModuleSP
632 DynamicLoaderDarwin::GetDYLDModule ()
633 {
634     ModuleSP dyld_sp (m_dyld_module_wp.lock());
635     return dyld_sp;
636 }
637 
638 bool
639 DynamicLoaderDarwin::AddModulesUsingImageInfos (ImageInfo::collection &image_infos)
640 {
641     std::lock_guard<std::recursive_mutex> guard(m_mutex);
642     // Now add these images to the main list.
643     ModuleList loaded_module_list;
644     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
645     Target &target = m_process->GetTarget();
646     ModuleList& target_images = target.GetImages();
647 
648     for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
649     {
650         if (log)
651         {
652             log->Printf ("Adding new image at address=0x%16.16" PRIx64 ".", image_infos[idx].address);
653             image_infos[idx].PutToLog (log);
654         }
655 
656         m_dyld_image_infos.push_back(image_infos[idx]);
657 
658         ModuleSP image_module_sp (FindTargetModuleForImageInfo (image_infos[idx], true, NULL));
659 
660         if (image_module_sp)
661         {
662             ObjectFile *objfile = image_module_sp->GetObjectFile ();
663             if (objfile)
664             {
665                 SectionList *sections = objfile->GetSectionList();
666                 if (sections)
667                 {
668                     ConstString commpage_dbstr("__commpage");
669                     Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
670                     if (commpage_section)
671                     {
672                         ModuleSpec module_spec (objfile->GetFileSpec(), image_infos[idx].GetArchitecture ());
673                         module_spec.GetObjectName() = commpage_dbstr;
674                         ModuleSP commpage_image_module_sp(target_images.FindFirstModule (module_spec));
675                         if (!commpage_image_module_sp)
676                         {
677                             module_spec.SetObjectOffset (objfile->GetFileOffset() + commpage_section->GetFileOffset());
678                             module_spec.SetObjectSize (objfile->GetByteSize());
679                             commpage_image_module_sp  = target.GetSharedModule (module_spec);
680                             if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL)
681                             {
682                                 commpage_image_module_sp = m_process->ReadModuleFromMemory (image_infos[idx].file_spec,
683                                                                                             image_infos[idx].address);
684                                 // Always load a memory image right away in the target in case
685                                 // we end up trying to read the symbol table from memory... The
686                                 // __LINKEDIT will need to be mapped so we can figure out where
687                                 // the symbol table bits are...
688                                 bool changed = false;
689                                 UpdateImageLoadAddress (commpage_image_module_sp.get(), image_infos[idx]);
690                                 target.GetImages().Append(commpage_image_module_sp);
691                                 if (changed)
692                                 {
693                                     image_infos[idx].load_stop_id = m_process->GetStopID();
694                                     loaded_module_list.AppendIfNeeded (commpage_image_module_sp);
695                                 }
696                             }
697                         }
698                     }
699                 }
700             }
701 
702             // UpdateImageLoadAddress will return true if any segments
703             // change load address. We need to check this so we don't
704             // mention that all loaded shared libraries are newly loaded
705             // each time we hit out dyld breakpoint since dyld will list all
706             // shared libraries each time.
707             if (UpdateImageLoadAddress (image_module_sp.get(), image_infos[idx]))
708             {
709                 target_images.AppendIfNeeded(image_module_sp);
710                 loaded_module_list.AppendIfNeeded (image_module_sp);
711             }
712         }
713     }
714 
715     if (loaded_module_list.GetSize() > 0)
716     {
717         if (log)
718             loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderDarwin::ModulesDidLoad");
719         m_process->GetTarget().ModulesDidLoad (loaded_module_list);
720     }
721     return true;
722 }
723 
724 
725 //----------------------------------------------------------------------
726 // On Mac OS X libobjc (the Objective-C runtime) has several critical dispatch
727 // functions written in hand-written assembly, and also have hand-written unwind
728 // information in the eh_frame section.  Normally we prefer analyzing the
729 // assembly instructions of a currently executing frame to unwind from that frame --
730 // but on hand-written functions this profiling can fail.  We should use the
731 // eh_frame instructions for these functions all the time.
732 //
733 // As an aside, it would be better if the eh_frame entries had a flag (or were
734 // extensible so they could have an Apple-specific flag) which indicates that
735 // the instructions are asynchronous -- accurate at every instruction, instead
736 // of our normal default assumption that they are not.
737 //----------------------------------------------------------------------
738 
739 bool
740 DynamicLoaderDarwin::AlwaysRelyOnEHUnwindInfo (SymbolContext &sym_ctx)
741 {
742     ModuleSP module_sp;
743     if (sym_ctx.symbol)
744     {
745         module_sp = sym_ctx.symbol->GetAddressRef().GetModule();
746     }
747     if (module_sp.get() == NULL && sym_ctx.function)
748     {
749         module_sp = sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule();
750     }
751     if (module_sp.get() == NULL)
752         return false;
753 
754     ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
755     if (objc_runtime != NULL && objc_runtime->IsModuleObjCLibrary (module_sp))
756     {
757         return true;
758     }
759 
760     return false;
761 }
762 
763 
764 
765 //----------------------------------------------------------------------
766 // Dump a Segment to the file handle provided.
767 //----------------------------------------------------------------------
768 void
769 DynamicLoaderDarwin::Segment::PutToLog (Log *log, lldb::addr_t slide) const
770 {
771     if (log)
772     {
773         if (slide == 0)
774             log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")",
775                          name.AsCString(""),
776                          vmaddr + slide,
777                          vmaddr + slide + vmsize);
778         else
779             log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") slide = 0x%" PRIx64,
780                          name.AsCString(""),
781                          vmaddr + slide,
782                          vmaddr + slide + vmsize,
783                          slide);
784     }
785 }
786 
787 const DynamicLoaderDarwin::Segment *
788 DynamicLoaderDarwin::ImageInfo::FindSegment (const ConstString &name) const
789 {
790     const size_t num_segments = segments.size();
791     for (size_t i=0; i<num_segments; ++i)
792     {
793         if (segments[i].name == name)
794             return &segments[i];
795     }
796     return NULL;
797 }
798 
799 
800 //----------------------------------------------------------------------
801 // Dump an image info structure to the file handle provided.
802 //----------------------------------------------------------------------
803 void
804 DynamicLoaderDarwin::ImageInfo::PutToLog (Log *log) const
805 {
806     if (log == NULL)
807         return;
808     const uint8_t *u = (const uint8_t *)uuid.GetBytes();
809 
810     if (address == LLDB_INVALID_ADDRESS)
811     {
812         if (u)
813         {
814             log->Printf("\t                           modtime=0x%8.8" PRIx64 " 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' (UNLOADED)",
815                         mod_date,
816                         u[ 0], u[ 1], u[ 2], u[ 3],
817                         u[ 4], u[ 5], u[ 6], u[ 7],
818                         u[ 8], u[ 9], u[10], u[11],
819                         u[12], u[13], u[14], u[15],
820                         file_spec.GetPath().c_str());
821         }
822         else
823             log->Printf("\t                           modtime=0x%8.8" PRIx64 " path='%s' (UNLOADED)",
824                         mod_date,
825                         file_spec.GetPath().c_str());
826     }
827     else
828     {
829         if (u)
830         {
831             log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " 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'",
832                         address,
833                         mod_date,
834                         u[ 0], u[ 1], u[ 2], u[ 3],
835                         u[ 4], u[ 5], u[ 6], u[ 7],
836                         u[ 8], u[ 9], u[10], u[11],
837                         u[12], u[13], u[14], u[15],
838                         file_spec.GetPath().c_str());
839         }
840         else
841         {
842             log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " path='%s'",
843                         address,
844                         mod_date,
845                         file_spec.GetPath().c_str());
846 
847         }
848         for (uint32_t i=0; i<segments.size(); ++i)
849             segments[i].PutToLog(log, slide);
850     }
851 }
852 
853 void
854 DynamicLoaderDarwin::PrivateInitialize(Process *process)
855 {
856     DEBUG_PRINTF("DynamicLoaderDarwin::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
857     Clear(true);
858     m_process = process;
859     m_process->GetTarget().ClearAllLoadedSections();
860 }
861 
862 //----------------------------------------------------------------------
863 // Member function that gets called when the process state changes.
864 //----------------------------------------------------------------------
865 void
866 DynamicLoaderDarwin::PrivateProcessStateChanged (Process *process, StateType state)
867 {
868     DEBUG_PRINTF("DynamicLoaderDarwin::%s(%s)\n", __FUNCTION__, StateAsCString(state));
869     switch (state)
870     {
871     case eStateConnected:
872     case eStateAttaching:
873     case eStateLaunching:
874     case eStateInvalid:
875     case eStateUnloaded:
876     case eStateExited:
877     case eStateDetached:
878         Clear(false);
879         break;
880 
881     case eStateStopped:
882         // Keep trying find dyld and set our notification breakpoint each time
883         // we stop until we succeed
884         if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
885         {
886             if (NeedToDoInitialImageFetch ())
887                 DoInitialImageFetch ();
888 
889             SetNotificationBreakpoint ();
890         }
891         break;
892 
893     case eStateRunning:
894     case eStateStepping:
895     case eStateCrashed:
896     case eStateSuspended:
897         break;
898     }
899 }
900 
901 ThreadPlanSP
902 DynamicLoaderDarwin::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
903 {
904     ThreadPlanSP thread_plan_sp;
905     StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
906     const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
907     Symbol *current_symbol = current_context.symbol;
908     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
909     TargetSP target_sp (thread.CalculateTarget());
910 
911     if (current_symbol != NULL)
912     {
913         std::vector<Address>  addresses;
914 
915         if (current_symbol->IsTrampoline())
916         {
917             const ConstString &trampoline_name = current_symbol->GetMangled().GetName(current_symbol->GetLanguage(), Mangled::ePreferMangled);
918 
919             if (trampoline_name)
920             {
921                 const ModuleList &images = target_sp->GetImages();
922 
923                 SymbolContextList code_symbols;
924                 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, code_symbols);
925                 size_t num_code_symbols = code_symbols.GetSize();
926 
927                 if (num_code_symbols > 0)
928                 {
929                     for (uint32_t i = 0; i < num_code_symbols; i++)
930                     {
931                         SymbolContext context;
932                         AddressRange addr_range;
933                         if (code_symbols.GetContextAtIndex(i, context))
934                         {
935                             context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
936                             addresses.push_back(addr_range.GetBaseAddress());
937                             if (log)
938                             {
939                                 addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
940 
941                                 log->Printf ("Found a trampoline target symbol at 0x%" PRIx64 ".", load_addr);
942                             }
943                         }
944                     }
945                 }
946 
947                 SymbolContextList reexported_symbols;
948                 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeReExported, reexported_symbols);
949                 size_t num_reexported_symbols = reexported_symbols.GetSize();
950                 if (num_reexported_symbols > 0)
951                 {
952                     for (uint32_t i = 0; i < num_reexported_symbols; i++)
953                     {
954                         SymbolContext context;
955                         if (reexported_symbols.GetContextAtIndex(i, context))
956                         {
957                             if (context.symbol)
958                             {
959                                 Symbol *actual_symbol = context.symbol->ResolveReExportedSymbol(*target_sp.get());
960                                 if (actual_symbol)
961                                 {
962                                     const Address actual_symbol_addr = actual_symbol->GetAddress();
963                                     if (actual_symbol_addr.IsValid())
964                                     {
965                                         addresses.push_back(actual_symbol_addr);
966                                         if (log)
967                                         {
968                                             lldb::addr_t load_addr = actual_symbol_addr.GetLoadAddress(target_sp.get());
969                                             log->Printf ("Found a re-exported symbol: %s at 0x%" PRIx64 ".",
970                                                          actual_symbol->GetName().GetCString(), load_addr);
971                                         }
972                                     }
973                                 }
974                             }
975                         }
976                     }
977                 }
978 
979                 SymbolContextList indirect_symbols;
980                 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver, indirect_symbols);
981                 size_t num_indirect_symbols = indirect_symbols.GetSize();
982                 if (num_indirect_symbols > 0)
983                 {
984                     for (uint32_t i = 0; i < num_indirect_symbols; i++)
985                     {
986                         SymbolContext context;
987                         AddressRange addr_range;
988                         if (indirect_symbols.GetContextAtIndex(i, context))
989                         {
990                             context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
991                             addresses.push_back(addr_range.GetBaseAddress());
992                             if (log)
993                             {
994                                 addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
995 
996                                 log->Printf ("Found an indirect target symbol at 0x%" PRIx64 ".", load_addr);
997                             }
998                         }
999                     }
1000                 }
1001             }
1002         }
1003         else if (current_symbol->GetType() == eSymbolTypeReExported)
1004         {
1005             // I am not sure we could ever end up stopped AT a re-exported symbol.  But just in case:
1006 
1007             const Symbol *actual_symbol = current_symbol->ResolveReExportedSymbol(*(target_sp.get()));
1008             if (actual_symbol)
1009             {
1010                 Address target_addr(actual_symbol->GetAddress());
1011                 if (target_addr.IsValid())
1012                 {
1013                     if (log)
1014                         log->Printf ("Found a re-exported symbol: %s pointing to: %s at 0x%" PRIx64 ".",
1015                                      current_symbol->GetName().GetCString(),
1016                                      actual_symbol->GetName().GetCString(),
1017                                      target_addr.GetLoadAddress(target_sp.get()));
1018                     addresses.push_back (target_addr.GetLoadAddress(target_sp.get()));
1019 
1020                 }
1021             }
1022         }
1023 
1024         if (addresses.size() > 0)
1025         {
1026             // First check whether any of the addresses point to Indirect symbols, and if they do, resolve them:
1027             std::vector<lldb::addr_t> load_addrs;
1028             for (Address address : addresses)
1029             {
1030                 Symbol *symbol = address.CalculateSymbolContextSymbol();
1031                 if (symbol && symbol->IsIndirect())
1032                 {
1033                     Error error;
1034                     Address symbol_address = symbol->GetAddress();
1035                     addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction(&symbol_address, error);
1036                     if (error.Success())
1037                     {
1038                         load_addrs.push_back(resolved_addr);
1039                         if (log)
1040                             log->Printf("ResolveIndirectFunction found resolved target for %s at 0x%" PRIx64 ".",
1041                                         symbol->GetName().GetCString(), resolved_addr);
1042                     }
1043                 }
1044                 else
1045                 {
1046                     load_addrs.push_back(address.GetLoadAddress(target_sp.get()));
1047                 }
1048 
1049             }
1050             thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, load_addrs, stop_others));
1051         }
1052     }
1053     else
1054     {
1055         if (log)
1056             log->Printf ("Could not find symbol for step through.");
1057     }
1058 
1059     return thread_plan_sp;
1060 }
1061 
1062 size_t
1063 DynamicLoaderDarwin::FindEquivalentSymbols (lldb_private::Symbol *original_symbol,
1064                                                lldb_private::ModuleList &images,
1065                                                lldb_private::SymbolContextList &equivalent_symbols)
1066 {
1067     const ConstString &trampoline_name = original_symbol->GetMangled().GetName(original_symbol->GetLanguage(), Mangled::ePreferMangled);
1068     if (!trampoline_name)
1069         return 0;
1070 
1071     size_t initial_size = equivalent_symbols.GetSize();
1072 
1073     static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Za-z0-9\\$]+)$";
1074     std::string equivalent_regex_buf("^");
1075     equivalent_regex_buf.append (trampoline_name.GetCString());
1076     equivalent_regex_buf.append (resolver_name_regex);
1077 
1078     RegularExpression equivalent_name_regex (equivalent_regex_buf.c_str());
1079     const bool append = true;
1080     images.FindSymbolsMatchingRegExAndType (equivalent_name_regex, eSymbolTypeCode, equivalent_symbols, append);
1081 
1082     return equivalent_symbols.GetSize() - initial_size;
1083 }
1084 
1085 lldb::ModuleSP
1086 DynamicLoaderDarwin::GetPThreadLibraryModule()
1087 {
1088     ModuleSP module_sp = m_libpthread_module_wp.lock();
1089     if (!module_sp)
1090     {
1091         SymbolContextList sc_list;
1092         ModuleSpec module_spec;
1093         module_spec.GetFileSpec().GetFilename().SetCString("libsystem_pthread.dylib");
1094         ModuleList module_list;
1095         if (m_process->GetTarget().GetImages().FindModules(module_spec, module_list))
1096         {
1097             if (module_list.GetSize() == 1)
1098             {
1099                 module_sp = module_list.GetModuleAtIndex(0);
1100                 if (module_sp)
1101                     m_libpthread_module_wp = module_sp;
1102             }
1103         }
1104     }
1105     return module_sp;
1106 }
1107 
1108 Address
1109 DynamicLoaderDarwin::GetPthreadSetSpecificAddress()
1110 {
1111     if (!m_pthread_getspecific_addr.IsValid())
1112     {
1113         ModuleSP module_sp = GetPThreadLibraryModule();
1114         if (module_sp)
1115         {
1116             lldb_private::SymbolContextList sc_list;
1117             module_sp->FindSymbolsWithNameAndType(ConstString("pthread_getspecific"), eSymbolTypeCode, sc_list);
1118             SymbolContext sc;
1119             if (sc_list.GetContextAtIndex(0, sc))
1120             {
1121                 if (sc.symbol)
1122                     m_pthread_getspecific_addr = sc.symbol->GetAddress();
1123             }
1124         }
1125     }
1126     return m_pthread_getspecific_addr;
1127 }
1128 
1129 lldb::addr_t
1130 DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp, const lldb::ThreadSP thread_sp,
1131                                         lldb::addr_t tls_file_addr)
1132 {
1133     if (!thread_sp || !module_sp)
1134         return LLDB_INVALID_ADDRESS;
1135 
1136     std::lock_guard<std::recursive_mutex> guard(m_mutex);
1137 
1138     const uint32_t addr_size = m_process->GetAddressByteSize();
1139     uint8_t buf[sizeof(lldb::addr_t) * 3];
1140 
1141     lldb_private::Address tls_addr;
1142     if (module_sp->ResolveFileAddress(tls_file_addr, tls_addr))
1143     {
1144         Error error;
1145         const size_t tsl_data_size = addr_size * 3;
1146         Target &target = m_process->GetTarget();
1147         if (target.ReadMemory(tls_addr, false, buf, tsl_data_size, error) == tsl_data_size)
1148         {
1149             const ByteOrder byte_order = m_process->GetByteOrder();
1150             DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
1151             lldb::offset_t offset = addr_size; // Skip the first pointer
1152             const lldb::addr_t pthread_key = data.GetAddress(&offset);
1153             const lldb::addr_t tls_offset = data.GetAddress(&offset);
1154             if (pthread_key != 0)
1155             {
1156                 // First check to see if we have already figured out the location
1157                 // of TLS data for the pthread_key on a specific thread yet. If we
1158                 // have we can re-use it since its location will not change unless
1159                 // the process execs.
1160                 const tid_t tid = thread_sp->GetID();
1161                 auto tid_pos = m_tid_to_tls_map.find(tid);
1162                 if (tid_pos != m_tid_to_tls_map.end())
1163                 {
1164                     auto tls_pos = tid_pos->second.find(pthread_key);
1165                     if (tls_pos != tid_pos->second.end())
1166                     {
1167                         return tls_pos->second + tls_offset;
1168                     }
1169                 }
1170                 StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(0);
1171                 if (frame_sp)
1172                 {
1173                     ClangASTContext *clang_ast_context = target.GetScratchClangASTContext();
1174 
1175                     if (!clang_ast_context)
1176                         return LLDB_INVALID_ADDRESS;
1177 
1178                     CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
1179                     Address pthread_getspecific_addr = GetPthreadSetSpecificAddress();
1180                     if (pthread_getspecific_addr.IsValid())
1181                     {
1182                         EvaluateExpressionOptions options;
1183 
1184                         lldb::ThreadPlanSP thread_plan_sp(
1185                             new ThreadPlanCallFunction(*thread_sp, pthread_getspecific_addr, clang_void_ptr_type,
1186                                                        llvm::ArrayRef<lldb::addr_t>(pthread_key), options));
1187 
1188                         DiagnosticManager execution_errors;
1189                         ExecutionContext exe_ctx(thread_sp);
1190                         lldb::ExpressionResults results =
1191                             m_process->RunThreadPlan(exe_ctx, thread_plan_sp, options, execution_errors);
1192 
1193                         if (results == lldb::eExpressionCompleted)
1194                         {
1195                             lldb::ValueObjectSP result_valobj_sp = thread_plan_sp->GetReturnValueObject();
1196                             if (result_valobj_sp)
1197                             {
1198                                 const lldb::addr_t pthread_key_data = result_valobj_sp->GetValueAsUnsigned(0);
1199                                 if (pthread_key_data)
1200                                 {
1201                                     m_tid_to_tls_map[tid].insert(std::make_pair(pthread_key, pthread_key_data));
1202                                     return pthread_key_data + tls_offset;
1203                                 }
1204                             }
1205                         }
1206                     }
1207                 }
1208             }
1209         }
1210     }
1211     return LLDB_INVALID_ADDRESS;
1212 }
1213 
1214 bool
1215 DynamicLoaderDarwin::UseDYLDSPI (Process *process)
1216 {
1217     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
1218     uint32_t major, minor, update;
1219 
1220     bool use_new_spi_interface = false;
1221 
1222     if (process->GetHostOSVersion (major, minor, update))
1223     {
1224         const llvm::Triple::OSType os_type = process->GetTarget().GetArchitecture().GetTriple().getOS();
1225 
1226         // macOS 10.12 and newer
1227         if (os_type == llvm::Triple::MacOSX
1228             && (major >= 10 || (major == 10 && minor >= 12)))
1229         {
1230             use_new_spi_interface = true;
1231         }
1232 
1233         // iOS 10 and newer
1234         if (os_type == llvm::Triple::IOS && major >= 10)
1235         {
1236             use_new_spi_interface = true;
1237         }
1238 
1239         // tvOS 10 and newer
1240         if (os_type == llvm::Triple::TvOS && major >= 10)
1241         {
1242             use_new_spi_interface = true;
1243         }
1244 
1245         // watchOS 3 and newer
1246         if (os_type == llvm::Triple::WatchOS && major >= 3)
1247         {
1248             use_new_spi_interface = true;
1249         }
1250     }
1251 
1252 
1253     // FIXME: Temporarily force the use of the old DynamicLoader plugin until all
1254     // the different use cases have been tested & the updated SPIs are available
1255     // everywhere.
1256     use_new_spi_interface = false;
1257 
1258     if (log)
1259     {
1260         if (use_new_spi_interface)
1261             log->Printf ("DynamicLoaderDarwin::UseDYLDSPI: Use new DynamicLoader plugin");
1262         else
1263             log->Printf ("DynamicLoaderDarwin::UseDYLDSPI: Use old DynamicLoader plugin");
1264 
1265     }
1266     return use_new_spi_interface;
1267 }
1268