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