1 //===-- DynamicLoaderDarwin.cpp -------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "DynamicLoaderDarwin.h"
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"
37 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
38 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
40 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
41 #ifdef ENABLE_DEBUG_PRINTF
43 #define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
45 #define DEBUG_PRINTF(fmt, ...)
51 using namespace lldb_private
;
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() {}
60 DynamicLoaderDarwin::~DynamicLoaderDarwin() = default;
62 /// Called after attaching a process.
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();
72 /// Called after attaching a process.
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();
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(
88 DynamicLoaderDarwinProperties::GetGlobal().GetValueProperties(),
89 "Properties for the DynamicLoaderDarwin plug-in.", is_global_setting
);
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
);
98 m_dyld_image_infos
.clear();
99 m_dyld_image_infos_stop_id
= UINT32_MAX
;
103 ModuleSP
DynamicLoaderDarwin::FindTargetModuleForImageInfo(
104 const ImageInfo
&image_info
, bool can_create
, bool *did_create_ptr
) {
106 *did_create_ptr
= false;
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
;
113 // macCatalyst support: Request matching os/environment.
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
);
124 ModuleSP
module_sp(target_images
.FindFirstModule(module_spec
));
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()))
135 if (module_sp
|| !can_create
)
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());
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
,
154 target
.GetOrCreateModule(shared_cache_spec
, false /* notify */);
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.
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
,
166 *did_create_ptr
= (bool)module_sp
;
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
)
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());
182 ModuleList unloaded_module_list
;
184 for (addr_t solib_addr
: solib_addresses
) {
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
);
208 if (unloaded_module_list
.GetSize() > 0) {
210 log
->PutCString("Unloaded:");
211 unloaded_module_list
.LogUUIDAndPaths(
212 log
, "DynamicLoaderDarwin::UnloadModules");
214 m_process
->GetTarget().GetImages().Remove(unloaded_module_list
);
215 m_dyld_image_infos_stop_id
= m_process
->GetStopID();
219 void DynamicLoaderDarwin::UnloadAllImages() {
220 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
221 ModuleList unloaded_modules_list
;
223 Target
&target
= m_process
->GetTarget();
224 const ModuleList
&target_modules
= target
.GetImages();
225 std::lock_guard
<std::recursive_mutex
> guard(target_modules
.GetMutex());
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
);
237 if (unloaded_modules_list
.GetSize() != 0) {
239 log
->PutCString("Unloaded:");
240 unloaded_modules_list
.LogUUIDAndPaths(
241 log
, "DynamicLoaderDarwin::UnloadAllImages");
243 target
.GetImages().Remove(unloaded_modules_list
);
244 m_dyld_image_infos
.clear();
245 m_dyld_image_infos_stop_id
= m_process
->GetStopID();
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
,
253 bool changed
= false;
255 ObjectFile
*image_object_file
= module
->GetObjectFile();
256 if (image_object_file
) {
257 SectionList
*section_list
= image_object_file
->GetSectionList();
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
));
269 if (info
.segments
[i
].maxprot
== 0) {
270 inaccessible_segment_indexes
.push_back(i
);
272 const addr_t new_section_load_addr
=
273 info
.segments
[i
].vmaddr
+ info
.slide
;
274 static ConstString
g_section_name_LINKEDIT("__LINKEDIT");
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
;
284 changed
= m_process
->GetTarget().SetSectionLoadAddress(
285 section_sp
, new_section_load_addr
, warn_multiple
);
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
));
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
);
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())
321 // Update the stop ID when this library was updated
322 info
.load_stop_id
= m_process
->GetStopID();
327 // Unload the segments in MODULE using the INFO that is passed in.
328 bool DynamicLoaderDarwin::UnloadModuleSections(Module
*module
,
330 bool changed
= false;
332 ObjectFile
*image_object_file
= module
->GetObjectFile();
333 if (image_object_file
) {
334 SectionList
*section_list
= image_object_file
->GetSectionList();
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
));
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
))
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()));
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.
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)
371 image_infos
.resize(images_sp
->GetAsArray()->GetSize());
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)
378 StructuredData::Dictionary
*image
= image_sp
->GetAsDictionary();
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")) {
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
);
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();
407 if (image
->HasKey("min_version_os_name")) {
408 std::string os_name
=
409 std::string(image
->GetValueForKey("min_version_os_name")
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
;
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")
443 // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't
444 // currently send them in the reply.
446 if (mh
->HasKey("flags"))
447 image_infos
[i
].header
.flags
=
448 mh
->GetValueForKey("flags")->GetUnsignedIntegerValue();
450 image_infos
[i
].header
.flags
= 0;
452 if (mh
->HasKey("ncmds"))
453 image_infos
[i
].header
.ncmds
=
454 mh
->GetValueForKey("ncmds")->GetUnsignedIntegerValue();
456 image_infos
[i
].header
.ncmds
= 0;
458 if (mh
->HasKey("sizeofcmds"))
459 image_infos
[i
].header
.sizeofcmds
=
460 mh
->GetValueForKey("sizeofcmds")->GetUnsignedIntegerValue();
462 image_infos
[i
].header
.sizeofcmds
= 0;
464 StructuredData::Array
*segments
=
465 image
->GetValueForKey("segments")->GetAsArray();
466 uint32_t segcount
= segments
->GetSize();
467 for (size_t j
= 0; j
< segcount
; j
++) {
469 StructuredData::Dictionary
*seg
=
470 segments
->GetItemAtIndex(j
)->GetAsDictionary();
472 ConstString(seg
->GetValueForKey("name")->GetAsString()->GetValue());
473 segment
.vmaddr
= seg
->GetValueForKey("vmaddr")->GetUnsignedIntegerValue();
474 segment
.vmsize
= seg
->GetValueForKey("vmsize")->GetUnsignedIntegerValue();
476 seg
->GetValueForKey("fileoff")->GetUnsignedIntegerValue();
478 seg
->GetValueForKey("filesize")->GetUnsignedIntegerValue();
480 seg
->GetValueForKey("maxprot")->GetUnsignedIntegerValue();
482 // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't
483 // currently send them in the reply.
485 if (seg
->HasKey("initprot"))
487 seg
->GetValueForKey("initprot")->GetUnsignedIntegerValue();
489 segment
.initprot
= 0;
491 if (seg
->HasKey("flags"))
492 segment
.flags
= seg
->GetValueForKey("flags")->GetUnsignedIntegerValue();
496 if (seg
->HasKey("nsects"))
498 seg
->GetValueForKey("nsects")->GetUnsignedIntegerValue();
502 image_infos
[i
].segments
.push_back(segment
);
505 image_infos
[i
].uuid
.SetFromStringRef(
506 image
->GetValueForKey("uuid")->GetAsString()->GetValue());
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
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.
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");
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
550 if (target_arch
.GetTriple().getEnvironment() == llvm::Triple::Simulator
&&
551 image_info
.os_type
!= llvm::Triple::OSType::MacOSX
) {
557 if (image_info
.header
.filetype
== llvm::MachO::MH_EXECUTE
) {
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
;
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
);
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
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,
595 if (dyld_idx
!= UINT32_MAX
) {
596 ModuleSP dyld_sp
= images
[dyld_idx
].second
;
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
);
607 bool DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo(
608 ImageInfo
&image_info
) {
609 if (image_info
.header
.filetype
== llvm::MachO::MH_DYLINKER
) {
610 const bool can_create
= true;
612 FindTargetModuleForImageInfo(image_info
, can_create
, nullptr);
614 Target
&target
= m_process
->GetTarget();
615 target
.GetImages().AppendIfNeeded(dyld_sp
);
616 UpdateImageLoadAddress(dyld_sp
.get(), image_info
);
617 SetDYLDModule(dyld_sp
);
624 std::optional
<lldb_private::Address
> DynamicLoaderDarwin::GetStartAddress() {
625 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
627 auto log_err
= [log
](llvm::StringLiteral err_msg
) -> std::nullopt_t
{
628 LLDB_LOGV(log
, "{}", err_msg
);
632 ModuleSP dyld_sp
= GetDYLDModule();
634 return log_err("Couldn't retrieve DYLD module. Cannot get `start` symbol.");
636 const Symbol
*symbol
=
637 dyld_sp
->FindFirstSymbolWithNameAndType(ConstString("_dyld_start"));
639 return log_err("Cannot find `start` symbol in DYLD module.");
641 return symbol
->GetAddress();
644 void DynamicLoaderDarwin::SetDYLDModule(lldb::ModuleSP
&dyld_module_sp
) {
645 m_dyld_module_wp
= dyld_module_sp
;
648 ModuleSP
DynamicLoaderDarwin::GetDYLDModule() {
649 ModuleSP
dyld_sp(m_dyld_module_wp
.lock());
653 void DynamicLoaderDarwin::ClearDYLDModule() { m_dyld_module_wp
.reset(); }
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));
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
);
675 for (size_t i
= 0; i
< size
; ++i
, ++it
) {
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
);
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();
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
;
702 LLDB_LOGF(log
, "Adding new image at address=0x%16.16" PRIx64
".",
704 image_info
.PutToLog(log
);
706 m_dyld_image_infos
.push_back(image_info
);
708 if (image_module_sp
) {
709 ObjectFile
*objfile
= image_module_sp
->GetObjectFile();
711 SectionList
*sections
= objfile
->GetSectionList();
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
,
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(),
739 target
.GetImages().Append(commpage_image_module_sp
);
741 image_info
.load_stop_id
= m_process
->GetStopID();
742 loaded_module_list
.AppendIfNeeded(commpage_image_module_sp
);
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
);
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
);
773 if (loaded_module_list
.GetSize() > 0) {
775 loaded_module_list
.LogUUIDAndPaths(log
,
776 "DynamicLoaderDarwin::ModulesDidLoad");
777 m_process
->GetTarget().ModulesDidLoad(loaded_module_list
);
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.
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.
794 bool DynamicLoaderDarwin::AlwaysRelyOnEHUnwindInfo(SymbolContext
&sym_ctx
) {
796 if (sym_ctx
.symbol
) {
797 module_sp
= sym_ctx
.symbol
->GetAddressRef().GetModule();
799 if (module_sp
.get() == nullptr && sym_ctx
.function
) {
801 sym_ctx
.function
->GetAddressRange().GetBaseAddress().GetModule();
803 if (module_sp
.get() == nullptr)
806 ObjCLanguageRuntime
*objc_runtime
= ObjCLanguageRuntime::Get(*m_process
);
807 return objc_runtime
!= nullptr &&
808 objc_runtime
->IsModuleObjCLibrary(module_sp
);
811 // Dump a Segment to the file handle provided.
812 void DynamicLoaderDarwin::Segment::PutToLog(Log
*log
,
813 lldb::addr_t slide
) const {
816 LLDB_LOGF(log
, "\t\t%16s [0x%16.16" PRIx64
" - 0x%16.16" PRIx64
")",
817 name
.AsCString(""), vmaddr
+ slide
, vmaddr
+ slide
+ vmsize
);
820 "\t\t%16s [0x%16.16" PRIx64
" - 0x%16.16" PRIx64
821 ") slide = 0x%" PRIx64
,
822 name
.AsCString(""), vmaddr
+ slide
, vmaddr
+ slide
+ vmsize
,
827 lldb_private::ArchSpec
DynamicLoaderDarwin::ImageInfo::GetArchitecture() const {
828 // Update the module's platform with the DYLD info.
829 lldb_private::ArchSpec
arch_spec(lldb_private::eArchTypeMachO
, header
.cputype
,
831 if (os_env
== llvm::Triple::MacABI
&& os_type
== llvm::Triple::IOS
) {
832 llvm::Triple
triple(llvm::Twine(arch_spec
.GetArchitectureName()) +
833 "-apple-ios" + min_version_os_sdk
+ "-macabi");
834 ArchSpec
maccatalyst_spec(triple
);
835 if (arch_spec
.IsCompatibleMatch(maccatalyst_spec
))
836 arch_spec
.MergeFrom(maccatalyst_spec
);
838 if (os_env
== llvm::Triple::Simulator
&&
839 (os_type
== llvm::Triple::IOS
|| os_type
== llvm::Triple::TvOS
||
840 os_type
== llvm::Triple::WatchOS
)) {
841 llvm::Triple
triple(llvm::Twine(arch_spec
.GetArchitectureName()) +
842 "-apple-" + llvm::Triple::getOSTypeName(os_type
) +
843 min_version_os_sdk
+ "-simulator");
844 ArchSpec
sim_spec(triple
);
845 if (arch_spec
.IsCompatibleMatch(sim_spec
))
846 arch_spec
.MergeFrom(sim_spec
);
851 const DynamicLoaderDarwin::Segment
*
852 DynamicLoaderDarwin::ImageInfo::FindSegment(ConstString name
) const {
853 const size_t num_segments
= segments
.size();
854 for (size_t i
= 0; i
< num_segments
; ++i
) {
855 if (segments
[i
].name
== name
)
861 // Dump an image info structure to the file handle provided.
862 void DynamicLoaderDarwin::ImageInfo::PutToLog(Log
*log
) const {
865 if (address
== LLDB_INVALID_ADDRESS
) {
866 LLDB_LOG(log
, "uuid={1} path='{2}' (UNLOADED)", uuid
.GetAsString(),
867 file_spec
.GetPath());
869 LLDB_LOG(log
, "address={0:x+16} uuid={1} path='{2}'", address
,
870 uuid
.GetAsString(), file_spec
.GetPath());
871 for (uint32_t i
= 0; i
< segments
.size(); ++i
)
872 segments
[i
].PutToLog(log
, slide
);
876 void DynamicLoaderDarwin::PrivateInitialize(Process
*process
) {
877 DEBUG_PRINTF("DynamicLoaderDarwin::%s() process state = %s\n", __FUNCTION__
,
878 StateAsCString(m_process
->GetState()));
881 m_process
->GetTarget().ClearAllLoadedSections();
884 // Member function that gets called when the process state changes.
885 void DynamicLoaderDarwin::PrivateProcessStateChanged(Process
*process
,
887 DEBUG_PRINTF("DynamicLoaderDarwin::%s(%s)\n", __FUNCTION__
,
888 StateAsCString(state
));
890 case eStateConnected
:
891 case eStateAttaching
:
892 case eStateLaunching
:
901 // Keep trying find dyld and set our notification breakpoint each time we
902 // stop until we succeed
903 if (!DidSetNotificationBreakpoint() && m_process
->IsAlive()) {
904 if (NeedToDoInitialImageFetch())
905 DoInitialImageFetch();
907 SetNotificationBreakpoint();
914 case eStateSuspended
:
920 DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread
&thread
,
922 ThreadPlanSP thread_plan_sp
;
923 StackFrame
*current_frame
= thread
.GetStackFrameAtIndex(0).get();
924 const SymbolContext
¤t_context
=
925 current_frame
->GetSymbolContext(eSymbolContextSymbol
);
926 Symbol
*current_symbol
= current_context
.symbol
;
927 Log
*log
= GetLog(LLDBLog::Step
);
928 TargetSP
target_sp(thread
.CalculateTarget());
930 if (current_symbol
!= nullptr) {
931 std::vector
<Address
> addresses
;
933 if (current_symbol
->IsTrampoline()) {
934 ConstString trampoline_name
=
935 current_symbol
->GetMangled().GetName(Mangled::ePreferMangled
);
937 if (trampoline_name
) {
938 const ModuleList
&images
= target_sp
->GetImages();
940 SymbolContextList code_symbols
;
941 images
.FindSymbolsWithNameAndType(trampoline_name
, eSymbolTypeCode
,
943 for (const SymbolContext
&context
: code_symbols
) {
944 AddressRange addr_range
;
945 context
.GetAddressRange(eSymbolContextEverything
, 0, false,
947 addresses
.push_back(addr_range
.GetBaseAddress());
950 addr_range
.GetBaseAddress().GetLoadAddress(target_sp
.get());
952 LLDB_LOGF(log
, "Found a trampoline target symbol at 0x%" PRIx64
".",
957 SymbolContextList reexported_symbols
;
958 images
.FindSymbolsWithNameAndType(
959 trampoline_name
, eSymbolTypeReExported
, reexported_symbols
);
960 for (const SymbolContext
&context
: reexported_symbols
) {
961 if (context
.symbol
) {
962 Symbol
*actual_symbol
=
963 context
.symbol
->ResolveReExportedSymbol(*target_sp
.get());
965 const Address actual_symbol_addr
= actual_symbol
->GetAddress();
966 if (actual_symbol_addr
.IsValid()) {
967 addresses
.push_back(actual_symbol_addr
);
969 lldb::addr_t load_addr
=
970 actual_symbol_addr
.GetLoadAddress(target_sp
.get());
972 "Found a re-exported symbol: %s at 0x%" PRIx64
".",
973 actual_symbol
->GetName().GetCString(), load_addr
);
980 SymbolContextList indirect_symbols
;
981 images
.FindSymbolsWithNameAndType(trampoline_name
, eSymbolTypeResolver
,
984 for (const SymbolContext
&context
: indirect_symbols
) {
985 AddressRange addr_range
;
986 context
.GetAddressRange(eSymbolContextEverything
, 0, false,
988 addresses
.push_back(addr_range
.GetBaseAddress());
991 addr_range
.GetBaseAddress().GetLoadAddress(target_sp
.get());
993 LLDB_LOGF(log
, "Found an indirect target symbol at 0x%" PRIx64
".",
998 } else if (current_symbol
->GetType() == eSymbolTypeReExported
) {
999 // I am not sure we could ever end up stopped AT a re-exported symbol.
1000 // But just in case:
1002 const Symbol
*actual_symbol
=
1003 current_symbol
->ResolveReExportedSymbol(*(target_sp
.get()));
1004 if (actual_symbol
) {
1005 Address
target_addr(actual_symbol
->GetAddress());
1006 if (target_addr
.IsValid()) {
1009 "Found a re-exported symbol: %s pointing to: %s at 0x%" PRIx64
1011 current_symbol
->GetName().GetCString(),
1012 actual_symbol
->GetName().GetCString(),
1013 target_addr
.GetLoadAddress(target_sp
.get()));
1014 addresses
.push_back(target_addr
.GetLoadAddress(target_sp
.get()));
1019 if (addresses
.size() > 0) {
1020 // First check whether any of the addresses point to Indirect symbols,
1021 // and if they do, resolve them:
1022 std::vector
<lldb::addr_t
> load_addrs
;
1023 for (Address address
: addresses
) {
1024 Symbol
*symbol
= address
.CalculateSymbolContextSymbol();
1025 if (symbol
&& symbol
->IsIndirect()) {
1027 Address symbol_address
= symbol
->GetAddress();
1028 addr_t resolved_addr
= thread
.GetProcess()->ResolveIndirectFunction(
1029 &symbol_address
, error
);
1030 if (error
.Success()) {
1031 load_addrs
.push_back(resolved_addr
);
1033 "ResolveIndirectFunction found resolved target for "
1034 "%s at 0x%" PRIx64
".",
1035 symbol
->GetName().GetCString(), resolved_addr
);
1038 load_addrs
.push_back(address
.GetLoadAddress(target_sp
.get()));
1041 thread_plan_sp
= std::make_shared
<ThreadPlanRunToAddress
>(
1042 thread
, load_addrs
, stop_others
);
1045 LLDB_LOGF(log
, "Could not find symbol for step through.");
1048 return thread_plan_sp
;
1051 void DynamicLoaderDarwin::FindEquivalentSymbols(
1052 lldb_private::Symbol
*original_symbol
, lldb_private::ModuleList
&images
,
1053 lldb_private::SymbolContextList
&equivalent_symbols
) {
1054 ConstString trampoline_name
=
1055 original_symbol
->GetMangled().GetName(Mangled::ePreferMangled
);
1056 if (!trampoline_name
)
1059 static const char *resolver_name_regex
= "(_gc|_non_gc|\\$[A-Za-z0-9\\$]+)$";
1060 std::string
equivalent_regex_buf("^");
1061 equivalent_regex_buf
.append(trampoline_name
.GetCString());
1062 equivalent_regex_buf
.append(resolver_name_regex
);
1064 RegularExpression
equivalent_name_regex(equivalent_regex_buf
);
1065 images
.FindSymbolsMatchingRegExAndType(equivalent_name_regex
, eSymbolTypeCode
,
1066 equivalent_symbols
);
1070 lldb::ModuleSP
DynamicLoaderDarwin::GetPThreadLibraryModule() {
1071 ModuleSP module_sp
= m_libpthread_module_wp
.lock();
1073 SymbolContextList sc_list
;
1074 ModuleSpec module_spec
;
1075 module_spec
.GetFileSpec().SetFilename("libsystem_pthread.dylib");
1076 ModuleList module_list
;
1077 m_process
->GetTarget().GetImages().FindModules(module_spec
, module_list
);
1078 if (!module_list
.IsEmpty()) {
1079 if (module_list
.GetSize() == 1) {
1080 module_sp
= module_list
.GetModuleAtIndex(0);
1082 m_libpthread_module_wp
= module_sp
;
1089 Address
DynamicLoaderDarwin::GetPthreadSetSpecificAddress() {
1090 if (!m_pthread_getspecific_addr
.IsValid()) {
1091 ModuleSP module_sp
= GetPThreadLibraryModule();
1093 lldb_private::SymbolContextList sc_list
;
1094 module_sp
->FindSymbolsWithNameAndType(ConstString("pthread_getspecific"),
1095 eSymbolTypeCode
, sc_list
);
1097 if (sc_list
.GetContextAtIndex(0, sc
)) {
1099 m_pthread_getspecific_addr
= sc
.symbol
->GetAddress();
1103 return m_pthread_getspecific_addr
;
1107 DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp
,
1108 const lldb::ThreadSP thread_sp
,
1109 lldb::addr_t tls_file_addr
) {
1110 if (!thread_sp
|| !module_sp
)
1111 return LLDB_INVALID_ADDRESS
;
1113 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
1115 lldb_private::Address tls_addr
;
1116 if (!module_sp
->ResolveFileAddress(tls_file_addr
, tls_addr
))
1117 return LLDB_INVALID_ADDRESS
;
1119 Target
&target
= m_process
->GetTarget();
1120 TypeSystemClangSP scratch_ts_sp
=
1121 ScratchTypeSystemClang::GetForTarget(target
);
1123 return LLDB_INVALID_ADDRESS
;
1125 CompilerType clang_void_ptr_type
=
1126 scratch_ts_sp
->GetBasicType(eBasicTypeVoid
).GetPointerType();
1128 auto evaluate_tls_address
= [this, &thread_sp
, &clang_void_ptr_type
](
1130 llvm::ArrayRef
<addr_t
> args
) -> addr_t
{
1131 EvaluateExpressionOptions options
;
1133 lldb::ThreadPlanSP
thread_plan_sp(new ThreadPlanCallFunction(
1134 *thread_sp
, func_ptr
, clang_void_ptr_type
, args
, options
));
1136 DiagnosticManager execution_errors
;
1137 ExecutionContext
exe_ctx(thread_sp
);
1138 lldb::ExpressionResults results
= m_process
->RunThreadPlan(
1139 exe_ctx
, thread_plan_sp
, options
, execution_errors
);
1141 if (results
== lldb::eExpressionCompleted
) {
1142 if (lldb::ValueObjectSP result_valobj_sp
=
1143 thread_plan_sp
->GetReturnValueObject()) {
1144 return result_valobj_sp
->GetValueAsUnsigned(LLDB_INVALID_ADDRESS
);
1147 return LLDB_INVALID_ADDRESS
;
1150 // On modern apple platforms, there is a small data structure that looks
1151 // approximately like this:
1152 // struct TLS_Thunk {
1153 // void *(*get_addr)(struct TLS_Thunk *);
1158 // The strategy is to take get_addr, call it with the address of the
1159 // containing TLS_Thunk structure, and add the offset to the resulting
1160 // pointer to get the data block.
1162 // On older apple platforms, the key is treated as a pthread_key_t and passed
1163 // to pthread_getspecific. The pointer returned from that call is added to
1164 // offset to get the relevant data block.
1166 const uint32_t addr_size
= m_process
->GetAddressByteSize();
1167 uint8_t buf
[sizeof(addr_t
) * 3];
1169 const size_t tls_data_size
= addr_size
* 3;
1170 const size_t bytes_read
= target
.ReadMemory(
1171 tls_addr
, buf
, tls_data_size
, error
, /*force_live_memory = */ true);
1172 if (bytes_read
!= tls_data_size
|| error
.Fail())
1173 return LLDB_INVALID_ADDRESS
;
1175 DataExtractor
data(buf
, sizeof(buf
), m_process
->GetByteOrder(), addr_size
);
1176 lldb::offset_t offset
= 0;
1177 const addr_t tls_thunk
= data
.GetAddress(&offset
);
1178 const addr_t key
= data
.GetAddress(&offset
);
1179 const addr_t tls_offset
= data
.GetAddress(&offset
);
1181 if (tls_thunk
!= 0) {
1182 const addr_t fixed_tls_thunk
= m_process
->FixCodeAddress(tls_thunk
);
1183 Address thunk_load_addr
;
1184 if (target
.ResolveLoadAddress(fixed_tls_thunk
, thunk_load_addr
)) {
1185 const addr_t tls_load_addr
= tls_addr
.GetLoadAddress(&target
);
1186 const addr_t tls_data
= evaluate_tls_address(
1187 thunk_load_addr
, llvm::ArrayRef
<addr_t
>(tls_load_addr
));
1188 if (tls_data
!= LLDB_INVALID_ADDRESS
)
1189 return tls_data
+ tls_offset
;
1194 // First check to see if we have already figured out the location of
1195 // TLS data for the pthread_key on a specific thread yet. If we have we
1196 // can re-use it since its location will not change unless the process
1198 const lldb::tid_t tid
= thread_sp
->GetID();
1199 auto tid_pos
= m_tid_to_tls_map
.find(tid
);
1200 if (tid_pos
!= m_tid_to_tls_map
.end()) {
1201 auto tls_pos
= tid_pos
->second
.find(key
);
1202 if (tls_pos
!= tid_pos
->second
.end()) {
1203 return tls_pos
->second
+ tls_offset
;
1206 Address pthread_getspecific_addr
= GetPthreadSetSpecificAddress();
1207 if (pthread_getspecific_addr
.IsValid()) {
1208 const addr_t tls_data
= evaluate_tls_address(pthread_getspecific_addr
,
1209 llvm::ArrayRef
<addr_t
>(key
));
1210 if (tls_data
!= LLDB_INVALID_ADDRESS
)
1211 return tls_data
+ tls_offset
;
1214 return LLDB_INVALID_ADDRESS
;
1217 bool DynamicLoaderDarwin::UseDYLDSPI(Process
*process
) {
1218 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
1219 bool use_new_spi_interface
= false;
1221 llvm::VersionTuple version
= process
->GetHostOSVersion();
1222 if (!version
.empty()) {
1223 const llvm::Triple::OSType os_type
=
1224 process
->GetTarget().GetArchitecture().GetTriple().getOS();
1226 // macOS 10.12 and newer
1227 if (os_type
== llvm::Triple::MacOSX
&&
1228 version
>= llvm::VersionTuple(10, 12))
1229 use_new_spi_interface
= true;
1232 if (os_type
== llvm::Triple::IOS
&& version
>= llvm::VersionTuple(10))
1233 use_new_spi_interface
= true;
1235 // tvOS 10 and newer
1236 if (os_type
== llvm::Triple::TvOS
&& version
>= llvm::VersionTuple(10))
1237 use_new_spi_interface
= true;
1239 // watchOS 3 and newer
1240 if (os_type
== llvm::Triple::WatchOS
&& version
>= llvm::VersionTuple(3))
1241 use_new_spi_interface
= true;
1243 // NEED_BRIDGEOS_TRIPLE // Any BridgeOS
1244 // NEED_BRIDGEOS_TRIPLE if (os_type == llvm::Triple::BridgeOS)
1245 // NEED_BRIDGEOS_TRIPLE use_new_spi_interface = true;
1249 if (use_new_spi_interface
)
1251 log
, "DynamicLoaderDarwin::UseDYLDSPI: Use new DynamicLoader plugin");
1254 log
, "DynamicLoaderDarwin::UseDYLDSPI: Use old DynamicLoader plugin");
1256 return use_new_spi_interface
;