aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp')
-rw-r--r--source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp1914
1 files changed, 970 insertions, 944 deletions
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
index efca1bea4ad6..bd0e772f7783 100644
--- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "DynamicLoaderDarwin.h"
+
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/DataBufferHeap.h"
@@ -18,6 +20,7 @@
#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
#include "lldb/Expression/DiagnosticManager.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -30,12 +33,10 @@
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
-#include "DynamicLoaderDarwin.h"
-
//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
#include <stdio.h>
-#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
#endif
@@ -49,29 +50,18 @@
using namespace lldb;
using namespace lldb_private;
-
//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
-DynamicLoaderDarwin::DynamicLoaderDarwin (Process* process)
- : DynamicLoader(process),
- m_dyld_module_wp(),
- m_libpthread_module_wp(),
- m_pthread_getspecific_addr(),
- m_tid_to_tls_map(),
- m_dyld_image_infos(),
- m_dyld_image_infos_stop_id(UINT32_MAX),
- m_dyld(),
- m_mutex()
-{
-}
+DynamicLoaderDarwin::DynamicLoaderDarwin(Process *process)
+ : DynamicLoader(process), m_dyld_module_wp(), m_libpthread_module_wp(),
+ m_pthread_getspecific_addr(), m_tid_to_tls_map(), m_dyld_image_infos(),
+ m_dyld_image_infos_stop_id(UINT32_MAX), m_dyld(), m_mutex() {}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-DynamicLoaderDarwin::~DynamicLoaderDarwin()
-{
-}
+DynamicLoaderDarwin::~DynamicLoaderDarwin() {}
//------------------------------------------------------------------
/// Called after attaching a process.
@@ -79,12 +69,10 @@ DynamicLoaderDarwin::~DynamicLoaderDarwin()
/// Allow DynamicLoader plug-ins to execute some code after
/// attaching to a process.
//------------------------------------------------------------------
-void
-DynamicLoaderDarwin::DidAttach ()
-{
- PrivateInitialize(m_process);
- DoInitialImageFetch ();
- SetNotificationBreakpoint ();
+void DynamicLoaderDarwin::DidAttach() {
+ PrivateInitialize(m_process);
+ DoInitialImageFetch();
+ SetNotificationBreakpoint();
}
//------------------------------------------------------------------
@@ -93,570 +81,617 @@ DynamicLoaderDarwin::DidAttach ()
/// Allow DynamicLoader plug-ins to execute some code after
/// attaching to a process.
//------------------------------------------------------------------
-void
-DynamicLoaderDarwin::DidLaunch ()
-{
- PrivateInitialize(m_process);
- DoInitialImageFetch ();
- SetNotificationBreakpoint ();
+void DynamicLoaderDarwin::DidLaunch() {
+ PrivateInitialize(m_process);
+ DoInitialImageFetch();
+ SetNotificationBreakpoint();
}
-
//----------------------------------------------------------------------
// Clear out the state of this class.
//----------------------------------------------------------------------
-void
-DynamicLoaderDarwin::Clear (bool clear_process)
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (clear_process)
- m_process = NULL;
- m_dyld_image_infos.clear();
- m_dyld_image_infos_stop_id = UINT32_MAX;
- m_dyld.Clear(false);
+void DynamicLoaderDarwin::Clear(bool clear_process) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ if (clear_process)
+ m_process = NULL;
+ m_dyld_image_infos.clear();
+ m_dyld_image_infos_stop_id = UINT32_MAX;
+ m_dyld.Clear(false);
}
-ModuleSP
-DynamicLoaderDarwin::FindTargetModuleForImageInfo (ImageInfo &image_info, bool can_create, bool *did_create_ptr)
-{
- if (did_create_ptr)
- *did_create_ptr = false;
-
- Target &target = m_process->GetTarget();
- const ModuleList &target_images = target.GetImages();
- ModuleSpec module_spec (image_info.file_spec);
- module_spec.GetUUID() = image_info.uuid;
- ModuleSP module_sp (target_images.FindFirstModule (module_spec));
-
- if (module_sp && !module_spec.GetUUID().IsValid() && !module_sp->GetUUID().IsValid())
- {
- // No UUID, we must rely upon the cached module modification
- // time and the modification time of the file on disk
- if (module_sp->GetModificationTime() != module_sp->GetFileSpec().GetModificationTime())
- module_sp.reset();
+ModuleSP DynamicLoaderDarwin::FindTargetModuleForImageInfo(
+ ImageInfo &image_info, bool can_create, bool *did_create_ptr) {
+ if (did_create_ptr)
+ *did_create_ptr = false;
+
+ Target &target = m_process->GetTarget();
+ const ModuleList &target_images = target.GetImages();
+ ModuleSpec module_spec(image_info.file_spec);
+ module_spec.GetUUID() = image_info.uuid;
+ ModuleSP module_sp(target_images.FindFirstModule(module_spec));
+
+ if (module_sp && !module_spec.GetUUID().IsValid() &&
+ !module_sp->GetUUID().IsValid()) {
+ // No UUID, we must rely upon the cached module modification
+ // time and the modification time of the file on disk
+ if (module_sp->GetModificationTime() !=
+ FileSystem::GetModificationTime(module_sp->GetFileSpec()))
+ module_sp.reset();
+ }
+
+ if (!module_sp) {
+ if (can_create) {
+ module_sp = target.GetSharedModule(module_spec);
+ if (!module_sp || module_sp->GetObjectFile() == NULL)
+ module_sp = m_process->ReadModuleFromMemory(image_info.file_spec,
+ image_info.address);
+
+ if (did_create_ptr)
+ *did_create_ptr = (bool)module_sp;
}
+ }
+ return module_sp;
+}
- if (!module_sp)
- {
- if (can_create)
- {
- module_sp = target.GetSharedModule (module_spec);
- if (!module_sp || module_sp->GetObjectFile() == NULL)
- module_sp = m_process->ReadModuleFromMemory (image_info.file_spec, image_info.address);
-
- if (did_create_ptr)
- *did_create_ptr = (bool) module_sp;
+void DynamicLoaderDarwin::UnloadImages(
+ const std::vector<lldb::addr_t> &solib_addresses) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
+ return;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ Target &target = m_process->GetTarget();
+ if (log)
+ log->Printf("Removing %" PRId64 " modules.",
+ (uint64_t)solib_addresses.size());
+
+ ModuleList unloaded_module_list;
+
+ for (addr_t solib_addr : solib_addresses) {
+ Address header;
+ if (header.SetLoadAddress(solib_addr, &target)) {
+ if (header.GetOffset() == 0) {
+ ModuleSP module_to_remove(header.GetModule());
+ if (module_to_remove.get()) {
+ if (log)
+ log->Printf("Removing module at address 0x%" PRIx64, solib_addr);
+ // remove the sections from the Target
+ UnloadSections(module_to_remove);
+ // add this to the list of modules to remove
+ unloaded_module_list.AppendIfNeeded(module_to_remove);
+ // remove the entry from the m_dyld_image_infos
+ ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
+ for (pos = m_dyld_image_infos.begin(); pos != end; pos++) {
+ if (solib_addr == (*pos).address) {
+ m_dyld_image_infos.erase(pos);
+ break;
+ }
+ }
}
+ }
}
- return module_sp;
-}
+ }
-DynamicLoaderDarwin::ImageInfo *
-DynamicLoaderDarwin::FindImageInfoForAddress (addr_t load_address)
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- const size_t image_count = m_dyld_image_infos.size();
- for (size_t i = 0; i < image_count; i++)
- {
- if (load_address == m_dyld_image_infos[i].address)
- {
- return &m_dyld_image_infos[i];
- }
+ if (unloaded_module_list.GetSize() > 0) {
+ if (log) {
+ log->PutCString("Unloaded:");
+ unloaded_module_list.LogUUIDAndPaths(
+ log, "DynamicLoaderDarwin::UnloadModules");
}
- return NULL;
+ m_process->GetTarget().GetImages().Remove(unloaded_module_list);
+ m_dyld_image_infos_stop_id = m_process->GetStopID();
+ }
}
-void
-DynamicLoaderDarwin::UnloadImages (const std::vector<lldb::addr_t> &solib_addresses)
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
- return;
+void DynamicLoaderDarwin::UnloadAllImages() {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ ModuleList unloaded_modules_list;
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
- Target &target = m_process->GetTarget();
- if (log)
- log->Printf ("Removing %" PRId64 " modules.", (uint64_t) solib_addresses.size());
-
- ModuleList unloaded_module_list;
-
- for (addr_t solib_addr : solib_addresses)
- {
- Address header;
- if (header.SetLoadAddress (solib_addr, &target))
- {
- if (header.GetOffset() == 0)
- {
- ModuleSP module_to_remove (header.GetModule());
- if (module_to_remove.get())
- {
- if (log)
- log->Printf ("Removing module at address 0x%" PRIx64, solib_addr);
- // remove the sections from the Target
- UnloadSections (module_to_remove);
- // add this to the list of modules to remove
- unloaded_module_list.AppendIfNeeded (module_to_remove);
- // remove the entry from the m_dyld_image_infos
- ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
- for (pos = m_dyld_image_infos.begin(); pos != end; pos++)
- {
- if (solib_addr == (*pos).address)
- {
- m_dyld_image_infos.erase(pos);
- break;
- }
- }
- }
- }
- }
+ Target &target = m_process->GetTarget();
+ const ModuleList &target_modules = target.GetImages();
+ std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
+
+ size_t num_modules = target_modules.GetSize();
+ ModuleSP dyld_sp(GetDYLDModule());
+
+ for (size_t i = 0; i < num_modules; i++) {
+ ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked(i);
+
+ // Don't remove dyld - else we'll lose our breakpoint notifying us about
+ // libraries
+ // being re-loaded...
+ if (module_sp.get() != nullptr && module_sp.get() != dyld_sp.get()) {
+ UnloadSections(module_sp);
+ unloaded_modules_list.Append(module_sp);
}
+ }
- if (unloaded_module_list.GetSize() > 0)
- {
- if (log)
- {
- log->PutCString("Unloaded:");
- unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderDarwin::UnloadModules");
- }
- m_process->GetTarget().GetImages().Remove (unloaded_module_list);
- m_dyld_image_infos_stop_id = m_process->GetStopID();
+ if (unloaded_modules_list.GetSize() != 0) {
+ if (log) {
+ log->PutCString("Unloaded:");
+ unloaded_modules_list.LogUUIDAndPaths(
+ log, "DynamicLoaderDarwin::UnloadAllImages");
}
+ target.GetImages().Remove(unloaded_modules_list);
+ m_dyld_image_infos.clear();
+ m_dyld_image_infos_stop_id = m_process->GetStopID();
+ }
}
//----------------------------------------------------------------------
// Update the load addresses for all segments in MODULE using the
// updated INFO that is passed in.
//----------------------------------------------------------------------
-bool
-DynamicLoaderDarwin::UpdateImageLoadAddress (Module *module, ImageInfo& info)
-{
- bool changed = false;
- if (module)
- {
- ObjectFile *image_object_file = module->GetObjectFile();
- if (image_object_file)
- {
- SectionList *section_list = image_object_file->GetSectionList ();
- if (section_list)
- {
- std::vector<uint32_t> inaccessible_segment_indexes;
- // We now know the slide amount, so go through all sections
- // and update the load addresses with the correct values.
- const size_t num_segments = info.segments.size();
- for (size_t i=0; i<num_segments; ++i)
- {
- // Only load a segment if it has protections. Things like
- // __PAGEZERO don't have any protections, and they shouldn't
- // be slid
- SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
-
- if (info.segments[i].maxprot == 0)
- {
- inaccessible_segment_indexes.push_back(i);
- }
- else
- {
- const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide;
- static ConstString g_section_name_LINKEDIT ("__LINKEDIT");
-
- if (section_sp)
- {
- // __LINKEDIT sections from files in the shared cache
- // can overlap so check to see what the segment name is
- // and pass "false" so we don't warn of overlapping
- // "Section" objects, and "true" for all other sections.
- const bool warn_multiple = section_sp->GetName() != g_section_name_LINKEDIT;
-
- changed = m_process->GetTarget().SetSectionLoadAddress (section_sp, new_section_load_addr, warn_multiple);
- }
- else
- {
- Host::SystemLog (Host::eSystemLogWarning,
- "warning: unable to find and load segment named '%s' at 0x%" PRIx64 " in '%s' in macosx dynamic loader plug-in.\n",
- info.segments[i].name.AsCString("<invalid>"),
- (uint64_t)new_section_load_addr,
- image_object_file->GetFileSpec().GetPath().c_str());
- }
- }
- }
-
- // If the loaded the file (it changed) and we have segments that
- // are not readable or writeable, add them to the invalid memory
- // region cache for the process. This will typically only be
- // the __PAGEZERO segment in the main executable. We might be able
- // to apply this more generally to more sections that have no
- // protections in the future, but for now we are going to just
- // do __PAGEZERO.
- if (changed && !inaccessible_segment_indexes.empty())
- {
- for (uint32_t i=0; i<inaccessible_segment_indexes.size(); ++i)
- {
- const uint32_t seg_idx = inaccessible_segment_indexes[i];
- SectionSP section_sp(section_list->FindSectionByName(info.segments[seg_idx].name));
-
- if (section_sp)
- {
- static ConstString g_pagezero_section_name("__PAGEZERO");
- if (g_pagezero_section_name == section_sp->GetName())
- {
- // __PAGEZERO never slides...
- const lldb::addr_t vmaddr = info.segments[seg_idx].vmaddr;
- const lldb::addr_t vmsize = info.segments[seg_idx].vmsize;
- Process::LoadRange pagezero_range (vmaddr, vmsize);
- m_process->AddInvalidMemoryRegion(pagezero_range);
- }
- }
- }
- }
+bool DynamicLoaderDarwin::UpdateImageLoadAddress(Module *module,
+ ImageInfo &info) {
+ bool changed = false;
+ if (module) {
+ ObjectFile *image_object_file = module->GetObjectFile();
+ if (image_object_file) {
+ SectionList *section_list = image_object_file->GetSectionList();
+ if (section_list) {
+ std::vector<uint32_t> inaccessible_segment_indexes;
+ // We now know the slide amount, so go through all sections
+ // and update the load addresses with the correct values.
+ const size_t num_segments = info.segments.size();
+ for (size_t i = 0; i < num_segments; ++i) {
+ // Only load a segment if it has protections. Things like
+ // __PAGEZERO don't have any protections, and they shouldn't
+ // be slid
+ SectionSP section_sp(
+ section_list->FindSectionByName(info.segments[i].name));
+
+ if (info.segments[i].maxprot == 0) {
+ inaccessible_segment_indexes.push_back(i);
+ } else {
+ const addr_t new_section_load_addr =
+ info.segments[i].vmaddr + info.slide;
+ static ConstString g_section_name_LINKEDIT("__LINKEDIT");
+
+ if (section_sp) {
+ // __LINKEDIT sections from files in the shared cache
+ // can overlap so check to see what the segment name is
+ // and pass "false" so we don't warn of overlapping
+ // "Section" objects, and "true" for all other sections.
+ const bool warn_multiple =
+ section_sp->GetName() != g_section_name_LINKEDIT;
+
+ changed = m_process->GetTarget().SetSectionLoadAddress(
+ section_sp, new_section_load_addr, warn_multiple);
+ } else {
+ Host::SystemLog(
+ Host::eSystemLogWarning,
+ "warning: unable to find and load segment named '%s' at "
+ "0x%" PRIx64 " in '%s' in macosx dynamic loader plug-in.\n",
+ info.segments[i].name.AsCString("<invalid>"),
+ (uint64_t)new_section_load_addr,
+ image_object_file->GetFileSpec().GetPath().c_str());
}
+ }
}
+
+ // If the loaded the file (it changed) and we have segments that
+ // are not readable or writeable, add them to the invalid memory
+ // region cache for the process. This will typically only be
+ // the __PAGEZERO segment in the main executable. We might be able
+ // to apply this more generally to more sections that have no
+ // protections in the future, but for now we are going to just
+ // do __PAGEZERO.
+ if (changed && !inaccessible_segment_indexes.empty()) {
+ for (uint32_t i = 0; i < inaccessible_segment_indexes.size(); ++i) {
+ const uint32_t seg_idx = inaccessible_segment_indexes[i];
+ SectionSP section_sp(
+ section_list->FindSectionByName(info.segments[seg_idx].name));
+
+ if (section_sp) {
+ static ConstString g_pagezero_section_name("__PAGEZERO");
+ if (g_pagezero_section_name == section_sp->GetName()) {
+ // __PAGEZERO never slides...
+ const lldb::addr_t vmaddr = info.segments[seg_idx].vmaddr;
+ const lldb::addr_t vmsize = info.segments[seg_idx].vmsize;
+ Process::LoadRange pagezero_range(vmaddr, vmsize);
+ m_process->AddInvalidMemoryRegion(pagezero_range);
+ }
+ }
+ }
+ }
+ }
}
- // We might have an in memory image that was loaded as soon as it was created
- if (info.load_stop_id == m_process->GetStopID())
- changed = true;
- else if (changed)
- {
- // Update the stop ID when this library was updated
- info.load_stop_id = m_process->GetStopID();
- }
- return changed;
+ }
+ // We might have an in memory image that was loaded as soon as it was created
+ if (info.load_stop_id == m_process->GetStopID())
+ changed = true;
+ else if (changed) {
+ // Update the stop ID when this library was updated
+ info.load_stop_id = m_process->GetStopID();
+ }
+ return changed;
}
//----------------------------------------------------------------------
// Unload the segments in MODULE using the INFO that is passed in.
//----------------------------------------------------------------------
-bool
-DynamicLoaderDarwin::UnloadModuleSections (Module *module, ImageInfo& info)
-{
- bool changed = false;
- if (module)
- {
- ObjectFile *image_object_file = module->GetObjectFile();
- if (image_object_file)
- {
- SectionList *section_list = image_object_file->GetSectionList ();
- if (section_list)
- {
- const size_t num_segments = info.segments.size();
- for (size_t i=0; i<num_segments; ++i)
- {
- SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
- if (section_sp)
- {
- const addr_t old_section_load_addr = info.segments[i].vmaddr + info.slide;
- if (m_process->GetTarget().SetSectionUnloaded (section_sp, old_section_load_addr))
- changed = true;
- }
- else
- {
- Host::SystemLog (Host::eSystemLogWarning,
- "warning: unable to find and unload segment named '%s' in '%s' in macosx dynamic loader plug-in.\n",
- info.segments[i].name.AsCString("<invalid>"),
- image_object_file->GetFileSpec().GetPath().c_str());
- }
- }
- }
+bool DynamicLoaderDarwin::UnloadModuleSections(Module *module,
+ ImageInfo &info) {
+ bool changed = false;
+ if (module) {
+ ObjectFile *image_object_file = module->GetObjectFile();
+ if (image_object_file) {
+ SectionList *section_list = image_object_file->GetSectionList();
+ if (section_list) {
+ const size_t num_segments = info.segments.size();
+ for (size_t i = 0; i < num_segments; ++i) {
+ SectionSP section_sp(
+ section_list->FindSectionByName(info.segments[i].name));
+ if (section_sp) {
+ const addr_t old_section_load_addr =
+ info.segments[i].vmaddr + info.slide;
+ if (m_process->GetTarget().SetSectionUnloaded(
+ section_sp, old_section_load_addr))
+ changed = true;
+ } else {
+ Host::SystemLog(Host::eSystemLogWarning,
+ "warning: unable to find and unload segment named "
+ "'%s' in '%s' in macosx dynamic loader plug-in.\n",
+ info.segments[i].name.AsCString("<invalid>"),
+ image_object_file->GetFileSpec().GetPath().c_str());
+ }
}
+ }
}
- return changed;
+ }
+ return changed;
}
-
-// Given a JSON dictionary (from debugserver, most likely) of binary images loaded in the inferior
+// Given a JSON dictionary (from debugserver, most likely) of binary images
+// loaded in the inferior
// process, add the images to the ImageInfo collection.
-bool
-DynamicLoaderDarwin::JSONImageInformationIntoImageInfo (StructuredData::ObjectSP image_details, ImageInfo::collection &image_infos)
-{
- StructuredData::ObjectSP images_sp = image_details->GetAsDictionary()->GetValueForKey("images");
- if (images_sp.get() == nullptr)
- return false;
-
- image_infos.resize (images_sp->GetAsArray()->GetSize());
-
- for (size_t i = 0; i < image_infos.size(); i++)
- {
- StructuredData::ObjectSP image_sp = images_sp->GetAsArray()->GetItemAtIndex(i);
- if (image_sp.get() == nullptr || image_sp->GetAsDictionary() == nullptr)
- return false;
- StructuredData::Dictionary *image = image_sp->GetAsDictionary();
- if (image->HasKey("load_address") == false
- || image->HasKey("pathname") == false
- || image->HasKey("mod_date") == false
- || image->HasKey("mach_header") == false
- || image->GetValueForKey("mach_header")->GetAsDictionary() == nullptr
- || image->HasKey("segments") == false
- || image->GetValueForKey("segments")->GetAsArray() == nullptr
- || image->HasKey("uuid") == false )
- {
- return false;
- }
- image_infos[i].address = image->GetValueForKey("load_address")->GetAsInteger()->GetValue();
- image_infos[i].mod_date = image->GetValueForKey("mod_date")->GetAsInteger()->GetValue();
- image_infos[i].file_spec.SetFile(image->GetValueForKey("pathname")->GetAsString()->GetValue().c_str(), false);
-
- StructuredData::Dictionary *mh = image->GetValueForKey("mach_header")->GetAsDictionary();
- image_infos[i].header.magic = mh->GetValueForKey("magic")->GetAsInteger()->GetValue();
- image_infos[i].header.cputype = mh->GetValueForKey("cputype")->GetAsInteger()->GetValue();
- image_infos[i].header.cpusubtype = mh->GetValueForKey("cpusubtype")->GetAsInteger()->GetValue();
- image_infos[i].header.filetype = mh->GetValueForKey("filetype")->GetAsInteger()->GetValue();
-
- // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't currently send them
- // in the reply.
-
- if (mh->HasKey("flags"))
- image_infos[i].header.flags = mh->GetValueForKey("flags")->GetAsInteger()->GetValue();
- else
- image_infos[i].header.flags = 0;
-
- if (mh->HasKey("ncmds"))
- image_infos[i].header.ncmds = mh->GetValueForKey("ncmds")->GetAsInteger()->GetValue();
- else
- image_infos[i].header.ncmds = 0;
-
- if (mh->HasKey("sizeofcmds"))
- image_infos[i].header.sizeofcmds = mh->GetValueForKey("sizeofcmds")->GetAsInteger()->GetValue();
- else
- image_infos[i].header.sizeofcmds = 0;
-
- StructuredData::Array *segments = image->GetValueForKey("segments")->GetAsArray();
- uint32_t segcount = segments->GetSize();
- for (size_t j = 0; j < segcount; j++)
- {
- Segment segment;
- StructuredData::Dictionary *seg = segments->GetItemAtIndex(j)->GetAsDictionary();
- segment.name = ConstString(seg->GetValueForKey("name")->GetAsString()->GetValue().c_str());
- segment.vmaddr = seg->GetValueForKey("vmaddr")->GetAsInteger()->GetValue();
- segment.vmsize = seg->GetValueForKey("vmsize")->GetAsInteger()->GetValue();
- segment.fileoff = seg->GetValueForKey("fileoff")->GetAsInteger()->GetValue();
- segment.filesize = seg->GetValueForKey("filesize")->GetAsInteger()->GetValue();
- segment.maxprot = seg->GetValueForKey("maxprot")->GetAsInteger()->GetValue();
-
- // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't currently send them
- // in the reply.
-
- if (seg->HasKey("initprot"))
- segment.initprot = seg->GetValueForKey("initprot")->GetAsInteger()->GetValue();
- else
- segment.initprot = 0;
-
- if (seg->HasKey("flags"))
- segment.flags = seg->GetValueForKey("flags")->GetAsInteger()->GetValue();
- else
- segment.flags = 0;
-
- if (seg->HasKey("nsects"))
- segment.nsects = seg->GetValueForKey("nsects")->GetAsInteger()->GetValue();
- else
- segment.nsects = 0;
-
- image_infos[i].segments.push_back (segment);
- }
+bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
+ StructuredData::ObjectSP image_details,
+ ImageInfo::collection &image_infos) {
+ StructuredData::ObjectSP images_sp =
+ image_details->GetAsDictionary()->GetValueForKey("images");
+ if (images_sp.get() == nullptr)
+ return false;
- image_infos[i].uuid.SetFromCString (image->GetValueForKey("uuid")->GetAsString()->GetValue().c_str());
-
- // All sections listed in the dyld image info structure will all
- // either be fixed up already, or they will all be off by a single
- // slide amount that is determined by finding the first segment
- // that is at file offset zero which also has bytes (a file size
- // that is greater than zero) in the object file.
-
- // Determine the slide amount (if any)
- const size_t num_sections = image_infos[i].segments.size();
- for (size_t k = 0; k < num_sections; ++k)
- {
- // Iterate through the object file sections to find the
- // first section that starts of file offset zero and that
- // has bytes in the file...
- if ((image_infos[i].segments[k].fileoff == 0 && image_infos[i].segments[k].filesize > 0)
- || (image_infos[i].segments[k].name == ConstString("__TEXT")))
- {
- image_infos[i].slide = image_infos[i].address - image_infos[i].segments[k].vmaddr;
- // We have found the slide amount, so we can exit
- // this for loop.
- break;
- }
- }
+ image_infos.resize(images_sp->GetAsArray()->GetSize());
+
+ for (size_t i = 0; i < image_infos.size(); i++) {
+ StructuredData::ObjectSP image_sp =
+ images_sp->GetAsArray()->GetItemAtIndex(i);
+ if (image_sp.get() == nullptr || image_sp->GetAsDictionary() == nullptr)
+ return false;
+ StructuredData::Dictionary *image = image_sp->GetAsDictionary();
+ if (image->HasKey("load_address") == false ||
+ image->HasKey("pathname") == false ||
+ image->HasKey("mod_date") == false ||
+ image->HasKey("mach_header") == false ||
+ image->GetValueForKey("mach_header")->GetAsDictionary() == nullptr ||
+ image->HasKey("segments") == false ||
+ image->GetValueForKey("segments")->GetAsArray() == nullptr ||
+ image->HasKey("uuid") == false) {
+ return false;
+ }
+ image_infos[i].address =
+ image->GetValueForKey("load_address")->GetAsInteger()->GetValue();
+ image_infos[i].mod_date =
+ image->GetValueForKey("mod_date")->GetAsInteger()->GetValue();
+ image_infos[i].file_spec.SetFile(
+ image->GetValueForKey("pathname")->GetAsString()->GetValue(), false);
+
+ StructuredData::Dictionary *mh =
+ image->GetValueForKey("mach_header")->GetAsDictionary();
+ image_infos[i].header.magic =
+ mh->GetValueForKey("magic")->GetAsInteger()->GetValue();
+ image_infos[i].header.cputype =
+ mh->GetValueForKey("cputype")->GetAsInteger()->GetValue();
+ image_infos[i].header.cpusubtype =
+ mh->GetValueForKey("cpusubtype")->GetAsInteger()->GetValue();
+ image_infos[i].header.filetype =
+ mh->GetValueForKey("filetype")->GetAsInteger()->GetValue();
+
+ if (image->HasKey("min_version_os_name")) {
+ std::string os_name = image->GetValueForKey("min_version_os_name")
+ ->GetAsString()
+ ->GetValue();
+ if (os_name == "macosx")
+ image_infos[i].os_type = llvm::Triple::MacOSX;
+ else if (os_name == "ios" || os_name == "iphoneos")
+ image_infos[i].os_type = llvm::Triple::IOS;
+ else if (os_name == "tvos")
+ image_infos[i].os_type = llvm::Triple::TvOS;
+ else if (os_name == "watchos")
+ image_infos[i].os_type = llvm::Triple::WatchOS;
+ }
+ if (image->HasKey("min_version_os_sdk")) {
+ image_infos[i].min_version_os_sdk =
+ image->GetValueForKey("min_version_os_sdk")
+ ->GetAsString()
+ ->GetValue();
}
- return true;
-}
+ // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't
+ // currently send them
+ // in the reply.
-void
-DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfos (ImageInfo::collection &image_infos)
-{
- const size_t image_infos_size = image_infos.size();
- for (size_t i = 0; i < image_infos_size; i++)
- {
- if (image_infos[i].header.filetype == llvm::MachO::MH_DYLINKER)
- {
- UpdateDYLDImageInfoFromNewImageInfo (image_infos[i]);
- break; // FIXME simulator debugging w/ multiple dylds
- }
+ if (mh->HasKey("flags"))
+ image_infos[i].header.flags =
+ mh->GetValueForKey("flags")->GetAsInteger()->GetValue();
+ else
+ image_infos[i].header.flags = 0;
+
+ if (mh->HasKey("ncmds"))
+ image_infos[i].header.ncmds =
+ mh->GetValueForKey("ncmds")->GetAsInteger()->GetValue();
+ else
+ image_infos[i].header.ncmds = 0;
+
+ if (mh->HasKey("sizeofcmds"))
+ image_infos[i].header.sizeofcmds =
+ mh->GetValueForKey("sizeofcmds")->GetAsInteger()->GetValue();
+ else
+ image_infos[i].header.sizeofcmds = 0;
+
+ StructuredData::Array *segments =
+ image->GetValueForKey("segments")->GetAsArray();
+ uint32_t segcount = segments->GetSize();
+ for (size_t j = 0; j < segcount; j++) {
+ Segment segment;
+ StructuredData::Dictionary *seg =
+ segments->GetItemAtIndex(j)->GetAsDictionary();
+ segment.name = ConstString(
+ seg->GetValueForKey("name")->GetAsString()->GetValue().c_str());
+ segment.vmaddr =
+ seg->GetValueForKey("vmaddr")->GetAsInteger()->GetValue();
+ segment.vmsize =
+ seg->GetValueForKey("vmsize")->GetAsInteger()->GetValue();
+ segment.fileoff =
+ seg->GetValueForKey("fileoff")->GetAsInteger()->GetValue();
+ segment.filesize =
+ seg->GetValueForKey("filesize")->GetAsInteger()->GetValue();
+ segment.maxprot =
+ seg->GetValueForKey("maxprot")->GetAsInteger()->GetValue();
+
+ // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't
+ // currently send them
+ // in the reply.
+
+ if (seg->HasKey("initprot"))
+ segment.initprot =
+ seg->GetValueForKey("initprot")->GetAsInteger()->GetValue();
+ else
+ segment.initprot = 0;
+
+ if (seg->HasKey("flags"))
+ segment.flags =
+ seg->GetValueForKey("flags")->GetAsInteger()->GetValue();
+ else
+ segment.flags = 0;
+
+ if (seg->HasKey("nsects"))
+ segment.nsects =
+ seg->GetValueForKey("nsects")->GetAsInteger()->GetValue();
+ else
+ segment.nsects = 0;
+
+ image_infos[i].segments.push_back(segment);
+ }
+
+ image_infos[i].uuid.SetFromCString(
+ image->GetValueForKey("uuid")->GetAsString()->GetValue().c_str());
+
+ // All sections listed in the dyld image info structure will all
+ // either be fixed up already, or they will all be off by a single
+ // slide amount that is determined by finding the first segment
+ // that is at file offset zero which also has bytes (a file size
+ // that is greater than zero) in the object file.
+
+ // Determine the slide amount (if any)
+ const size_t num_sections = image_infos[i].segments.size();
+ for (size_t k = 0; k < num_sections; ++k) {
+ // Iterate through the object file sections to find the
+ // first section that starts of file offset zero and that
+ // has bytes in the file...
+ if ((image_infos[i].segments[k].fileoff == 0 &&
+ image_infos[i].segments[k].filesize > 0) ||
+ (image_infos[i].segments[k].name == ConstString("__TEXT"))) {
+ image_infos[i].slide =
+ image_infos[i].address - image_infos[i].segments[k].vmaddr;
+ // We have found the slide amount, so we can exit
+ // this for loop.
+ break;
+ }
}
+ }
+
+ return true;
}
-void
-DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo (ImageInfo &image_info)
-{
- // FIXME simulator debugging w/ multiple dylds
- if (image_info.header.filetype == llvm::MachO::MH_DYLINKER)
- {
- const bool can_create = true;
- ModuleSP dyld_sp = FindTargetModuleForImageInfo (image_info, can_create, NULL);
- if (dyld_sp.get())
- {
- Target &target = m_process->GetTarget();
- target.GetImages().AppendIfNeeded (dyld_sp);
- UpdateImageLoadAddress (dyld_sp.get(), image_info);
- SetDYLDModule (dyld_sp);
+void DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos(
+ ImageInfo::collection &image_infos) {
+ uint32_t exe_idx = UINT32_MAX;
+ uint32_t dyld_idx = UINT32_MAX;
+ Target &target = m_process->GetTarget();
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ ConstString g_dyld_sim_filename("dyld_sim");
+
+ ArchSpec target_arch = target.GetArchitecture();
+ const size_t image_infos_size = image_infos.size();
+ for (size_t i = 0; i < image_infos_size; i++) {
+ if (image_infos[i].header.filetype == llvm::MachO::MH_DYLINKER) {
+ // In a "simulator" process (an x86 process that is ios/tvos/watchos)
+ // we will have two dyld modules -- a "dyld" that we want to keep track
+ // of,
+ // and a "dyld_sim" which we don't need to keep track of here.
+ // If the target is an x86 system and the OS of the dyld binary is
+ // ios/tvos/watchos, then we are looking at dyld_sym.
+
+ // debugserver has only recently (late 2016) started sending up the
+ // os type for each binary it sees -- so if we don't have an os
+ // type, use a filename check as our next best guess.
+ if (image_infos[i].os_type == llvm::Triple::OSType::UnknownOS) {
+ if (image_infos[i].file_spec.GetFilename() != g_dyld_sim_filename) {
+ dyld_idx = i;
+ }
+ } else if (target_arch.GetTriple().getArch() == llvm::Triple::x86 ||
+ target_arch.GetTriple().getArch() == llvm::Triple::x86_64) {
+ if (image_infos[i].os_type != llvm::Triple::OSType::IOS &&
+ image_infos[i].os_type != llvm::Triple::TvOS &&
+ image_infos[i].os_type != llvm::Triple::WatchOS) {
+ dyld_idx = i;
}
+ }
+ } else if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE) {
+ exe_idx = i;
+ }
+ }
+
+ if (exe_idx != UINT32_MAX) {
+ const bool can_create = true;
+ ModuleSP exe_module_sp(
+ FindTargetModuleForImageInfo(image_infos[exe_idx], can_create, NULL));
+ if (exe_module_sp) {
+ if (log)
+ log->Printf("Found executable module: %s",
+ exe_module_sp->GetFileSpec().GetPath().c_str());
+ target.GetImages().AppendIfNeeded(exe_module_sp);
+ UpdateImageLoadAddress(exe_module_sp.get(), image_infos[exe_idx]);
+ if (exe_module_sp.get() != target.GetExecutableModulePointer()) {
+ const bool get_dependent_images = false;
+ target.SetExecutableModule(exe_module_sp, get_dependent_images);
+ }
}
+ }
+
+ if (dyld_idx != UINT32_MAX) {
+ const bool can_create = true;
+ ModuleSP dyld_sp =
+ FindTargetModuleForImageInfo(image_infos[dyld_idx], can_create, NULL);
+ if (dyld_sp.get()) {
+ if (log)
+ log->Printf("Found dyld module: %s",
+ dyld_sp->GetFileSpec().GetPath().c_str());
+ target.GetImages().AppendIfNeeded(dyld_sp);
+ UpdateImageLoadAddress(dyld_sp.get(), image_infos[dyld_idx]);
+ SetDYLDModule(dyld_sp);
+ }
+ }
}
-void
-DynamicLoaderDarwin::AddExecutableModuleIfInImageInfos (ImageInfo::collection &image_infos)
-{
- const size_t image_infos_size = image_infos.size();
- for (size_t i = 0; i < image_infos_size; i++)
- {
- if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE)
- {
- Target &target = m_process->GetTarget();
- const bool can_create = true;
- ModuleSP exe_module_sp (FindTargetModuleForImageInfo (image_infos[i], can_create, NULL));
-
- if (exe_module_sp)
- {
- UpdateImageLoadAddress (exe_module_sp.get(), image_infos[i]);
-
- if (exe_module_sp.get() != target.GetExecutableModulePointer())
- {
- // Don't load dependent images since we are in dyld where we will know
- // and find out about all images that are loaded. Also when setting the
- // executable module, it will clear the targets module list, and if we
- // have an in memory dyld module, it will get removed from the list
- // so we will need to add it back after setting the executable module,
- // so we first try and see if we already have a weak pointer to the
- // dyld module, make it into a shared pointer, then add the executable,
- // then re-add it back to make sure it is always in the list.
-
- const bool get_dependent_images = false;
- m_process->GetTarget().SetExecutableModule (exe_module_sp,
- get_dependent_images);
-
- UpdateDYLDImageInfoFromNewImageInfos (image_infos);
- }
- }
- }
+void DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo(
+ ImageInfo &image_info) {
+ if (image_info.header.filetype == llvm::MachO::MH_DYLINKER) {
+ const bool can_create = true;
+ ModuleSP dyld_sp =
+ FindTargetModuleForImageInfo(image_info, can_create, NULL);
+ if (dyld_sp.get()) {
+ Target &target = m_process->GetTarget();
+ target.GetImages().AppendIfNeeded(dyld_sp);
+ UpdateImageLoadAddress(dyld_sp.get(), image_info);
+ SetDYLDModule(dyld_sp);
}
+ }
}
-void
-DynamicLoaderDarwin::SetDYLDModule (lldb::ModuleSP &dyld_module_sp)
-{
- m_dyld_module_wp = dyld_module_sp;
+void DynamicLoaderDarwin::SetDYLDModule(lldb::ModuleSP &dyld_module_sp) {
+ m_dyld_module_wp = dyld_module_sp;
}
-ModuleSP
-DynamicLoaderDarwin::GetDYLDModule ()
-{
- ModuleSP dyld_sp (m_dyld_module_wp.lock());
- return dyld_sp;
+ModuleSP DynamicLoaderDarwin::GetDYLDModule() {
+ ModuleSP dyld_sp(m_dyld_module_wp.lock());
+ return dyld_sp;
}
-bool
-DynamicLoaderDarwin::AddModulesUsingImageInfos (ImageInfo::collection &image_infos)
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- // Now add these images to the main list.
- ModuleList loaded_module_list;
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
- Target &target = m_process->GetTarget();
- ModuleList& target_images = target.GetImages();
-
- for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
- {
- if (log)
- {
- log->Printf ("Adding new image at address=0x%16.16" PRIx64 ".", image_infos[idx].address);
- image_infos[idx].PutToLog (log);
- }
-
- m_dyld_image_infos.push_back(image_infos[idx]);
-
- ModuleSP image_module_sp (FindTargetModuleForImageInfo (image_infos[idx], true, NULL));
-
- if (image_module_sp)
- {
- ObjectFile *objfile = image_module_sp->GetObjectFile ();
- if (objfile)
- {
- SectionList *sections = objfile->GetSectionList();
- if (sections)
- {
- ConstString commpage_dbstr("__commpage");
- Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
- if (commpage_section)
- {
- ModuleSpec module_spec (objfile->GetFileSpec(), image_infos[idx].GetArchitecture ());
- module_spec.GetObjectName() = commpage_dbstr;
- ModuleSP commpage_image_module_sp(target_images.FindFirstModule (module_spec));
- if (!commpage_image_module_sp)
- {
- module_spec.SetObjectOffset (objfile->GetFileOffset() + commpage_section->GetFileOffset());
- module_spec.SetObjectSize (objfile->GetByteSize());
- commpage_image_module_sp = target.GetSharedModule (module_spec);
- if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL)
- {
- commpage_image_module_sp = m_process->ReadModuleFromMemory (image_infos[idx].file_spec,
- image_infos[idx].address);
- // Always load a memory image right away in the target in case
- // we end up trying to read the symbol table from memory... The
- // __LINKEDIT will need to be mapped so we can figure out where
- // the symbol table bits are...
- bool changed = false;
- UpdateImageLoadAddress (commpage_image_module_sp.get(), image_infos[idx]);
- target.GetImages().Append(commpage_image_module_sp);
- if (changed)
- {
- image_infos[idx].load_stop_id = m_process->GetStopID();
- loaded_module_list.AppendIfNeeded (commpage_image_module_sp);
- }
- }
- }
- }
- }
- }
+bool DynamicLoaderDarwin::AddModulesUsingImageInfos(
+ ImageInfo::collection &image_infos) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ // Now add these images to the main list.
+ ModuleList loaded_module_list;
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ Target &target = m_process->GetTarget();
+ ModuleList &target_images = target.GetImages();
+
+ for (uint32_t idx = 0; idx < image_infos.size(); ++idx) {
+ if (log) {
+ log->Printf("Adding new image at address=0x%16.16" PRIx64 ".",
+ image_infos[idx].address);
+ image_infos[idx].PutToLog(log);
+ }
- // UpdateImageLoadAddress will return true if any segments
- // change load address. We need to check this so we don't
- // mention that all loaded shared libraries are newly loaded
- // each time we hit out dyld breakpoint since dyld will list all
- // shared libraries each time.
- if (UpdateImageLoadAddress (image_module_sp.get(), image_infos[idx]))
- {
- target_images.AppendIfNeeded(image_module_sp);
- loaded_module_list.AppendIfNeeded (image_module_sp);
+ m_dyld_image_infos.push_back(image_infos[idx]);
+
+ ModuleSP image_module_sp(
+ FindTargetModuleForImageInfo(image_infos[idx], true, NULL));
+
+ if (image_module_sp) {
+ ObjectFile *objfile = image_module_sp->GetObjectFile();
+ if (objfile) {
+ SectionList *sections = objfile->GetSectionList();
+ if (sections) {
+ ConstString commpage_dbstr("__commpage");
+ Section *commpage_section =
+ sections->FindSectionByName(commpage_dbstr).get();
+ if (commpage_section) {
+ ModuleSpec module_spec(objfile->GetFileSpec(),
+ image_infos[idx].GetArchitecture());
+ module_spec.GetObjectName() = commpage_dbstr;
+ ModuleSP commpage_image_module_sp(
+ target_images.FindFirstModule(module_spec));
+ if (!commpage_image_module_sp) {
+ module_spec.SetObjectOffset(objfile->GetFileOffset() +
+ commpage_section->GetFileOffset());
+ module_spec.SetObjectSize(objfile->GetByteSize());
+ commpage_image_module_sp = target.GetSharedModule(module_spec);
+ if (!commpage_image_module_sp ||
+ commpage_image_module_sp->GetObjectFile() == NULL) {
+ commpage_image_module_sp = m_process->ReadModuleFromMemory(
+ image_infos[idx].file_spec, image_infos[idx].address);
+ // Always load a memory image right away in the target in case
+ // we end up trying to read the symbol table from memory... The
+ // __LINKEDIT will need to be mapped so we can figure out where
+ // the symbol table bits are...
+ bool changed = false;
+ UpdateImageLoadAddress(commpage_image_module_sp.get(),
+ image_infos[idx]);
+ target.GetImages().Append(commpage_image_module_sp);
+ if (changed) {
+ image_infos[idx].load_stop_id = m_process->GetStopID();
+ loaded_module_list.AppendIfNeeded(commpage_image_module_sp);
+ }
+ }
}
+ }
}
+ }
+
+ // UpdateImageLoadAddress will return true if any segments
+ // change load address. We need to check this so we don't
+ // mention that all loaded shared libraries are newly loaded
+ // each time we hit out dyld breakpoint since dyld will list all
+ // shared libraries each time.
+ if (UpdateImageLoadAddress(image_module_sp.get(), image_infos[idx])) {
+ target_images.AppendIfNeeded(image_module_sp);
+ loaded_module_list.AppendIfNeeded(image_module_sp);
+ }
}
-
- if (loaded_module_list.GetSize() > 0)
- {
- if (log)
- loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderDarwin::ModulesDidLoad");
- m_process->GetTarget().ModulesDidLoad (loaded_module_list);
- }
- return true;
-}
+ }
+ if (loaded_module_list.GetSize() > 0) {
+ if (log)
+ loaded_module_list.LogUUIDAndPaths(log,
+ "DynamicLoaderDarwin::ModulesDidLoad");
+ m_process->GetTarget().ModulesDidLoad(loaded_module_list);
+ }
+ return true;
+}
//----------------------------------------------------------------------
// On Mac OS X libobjc (the Objective-C runtime) has several critical dispatch
// functions written in hand-written assembly, and also have hand-written unwind
-// information in the eh_frame section. Normally we prefer analyzing the
-// assembly instructions of a currently executing frame to unwind from that frame --
+// information in the eh_frame section. Normally we prefer analyzing the
+// assembly instructions of a currently executing frame to unwind from that
+// frame --
// but on hand-written functions this profiling can fail. We should use the
// eh_frame instructions for these functions all the time.
//
@@ -666,478 +701,469 @@ DynamicLoaderDarwin::AddModulesUsingImageInfos (ImageInfo::collection &image_inf
// of our normal default assumption that they are not.
//----------------------------------------------------------------------
-bool
-DynamicLoaderDarwin::AlwaysRelyOnEHUnwindInfo (SymbolContext &sym_ctx)
-{
- ModuleSP module_sp;
- if (sym_ctx.symbol)
- {
- module_sp = sym_ctx.symbol->GetAddressRef().GetModule();
- }
- if (module_sp.get() == NULL && sym_ctx.function)
- {
- module_sp = sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule();
- }
- if (module_sp.get() == NULL)
- return false;
-
- ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
- if (objc_runtime != NULL && objc_runtime->IsModuleObjCLibrary (module_sp))
- {
- return true;
- }
-
+bool DynamicLoaderDarwin::AlwaysRelyOnEHUnwindInfo(SymbolContext &sym_ctx) {
+ ModuleSP module_sp;
+ if (sym_ctx.symbol) {
+ module_sp = sym_ctx.symbol->GetAddressRef().GetModule();
+ }
+ if (module_sp.get() == NULL && sym_ctx.function) {
+ module_sp =
+ sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule();
+ }
+ if (module_sp.get() == NULL)
return false;
-}
+ ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
+ if (objc_runtime != NULL && objc_runtime->IsModuleObjCLibrary(module_sp)) {
+ return true;
+ }
+ return false;
+}
//----------------------------------------------------------------------
// Dump a Segment to the file handle provided.
//----------------------------------------------------------------------
-void
-DynamicLoaderDarwin::Segment::PutToLog (Log *log, lldb::addr_t slide) const
-{
- if (log)
- {
- if (slide == 0)
- log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")",
- name.AsCString(""),
- vmaddr + slide,
- vmaddr + slide + vmsize);
- else
- log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") slide = 0x%" PRIx64,
- name.AsCString(""),
- vmaddr + slide,
- vmaddr + slide + vmsize,
- slide);
- }
+void DynamicLoaderDarwin::Segment::PutToLog(Log *log,
+ lldb::addr_t slide) const {
+ if (log) {
+ if (slide == 0)
+ log->Printf("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")",
+ name.AsCString(""), vmaddr + slide, vmaddr + slide + vmsize);
+ else
+ log->Printf("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64
+ ") slide = 0x%" PRIx64,
+ name.AsCString(""), vmaddr + slide, vmaddr + slide + vmsize,
+ slide);
+ }
}
const DynamicLoaderDarwin::Segment *
-DynamicLoaderDarwin::ImageInfo::FindSegment (const ConstString &name) const
-{
- const size_t num_segments = segments.size();
- for (size_t i=0; i<num_segments; ++i)
- {
- if (segments[i].name == name)
- return &segments[i];
- }
- return NULL;
+DynamicLoaderDarwin::ImageInfo::FindSegment(const ConstString &name) const {
+ const size_t num_segments = segments.size();
+ for (size_t i = 0; i < num_segments; ++i) {
+ if (segments[i].name == name)
+ return &segments[i];
+ }
+ return NULL;
}
-
//----------------------------------------------------------------------
// Dump an image info structure to the file handle provided.
//----------------------------------------------------------------------
-void
-DynamicLoaderDarwin::ImageInfo::PutToLog (Log *log) const
-{
- if (log == NULL)
- return;
- const uint8_t *u = (const uint8_t *)uuid.GetBytes();
-
- if (address == LLDB_INVALID_ADDRESS)
- {
- if (u)
- {
- log->Printf("\t modtime=0x%8.8" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s' (UNLOADED)",
- mod_date,
- u[ 0], u[ 1], u[ 2], u[ 3],
- u[ 4], u[ 5], u[ 6], u[ 7],
- u[ 8], u[ 9], u[10], u[11],
- u[12], u[13], u[14], u[15],
- file_spec.GetPath().c_str());
- }
- else
- log->Printf("\t modtime=0x%8.8" PRIx64 " path='%s' (UNLOADED)",
- mod_date,
- file_spec.GetPath().c_str());
- }
- else
- {
- if (u)
- {
- log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s'",
- address,
- mod_date,
- u[ 0], u[ 1], u[ 2], u[ 3],
- u[ 4], u[ 5], u[ 6], u[ 7],
- u[ 8], u[ 9], u[10], u[11],
- u[12], u[13], u[14], u[15],
- file_spec.GetPath().c_str());
- }
- else
- {
- log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " path='%s'",
- address,
- mod_date,
- file_spec.GetPath().c_str());
-
- }
- for (uint32_t i=0; i<segments.size(); ++i)
- segments[i].PutToLog(log, slide);
+void DynamicLoaderDarwin::ImageInfo::PutToLog(Log *log) const {
+ if (log == NULL)
+ return;
+ const uint8_t *u = (const uint8_t *)uuid.GetBytes();
+
+ if (address == LLDB_INVALID_ADDRESS) {
+ if (u) {
+ log->Printf("\t modtime=0x%8.8" PRIx64
+ " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-"
+ "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s' (UNLOADED)",
+ mod_date, u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7],
+ u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15],
+ file_spec.GetPath().c_str());
+ } else
+ log->Printf("\t modtime=0x%8.8" PRIx64
+ " path='%s' (UNLOADED)",
+ mod_date, file_spec.GetPath().c_str());
+ } else {
+ if (u) {
+ log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64
+ " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-"
+ "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s'",
+ address, mod_date, u[0], u[1], u[2], u[3], u[4], u[5], u[6],
+ u[7], u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15],
+ file_spec.GetPath().c_str());
+ } else {
+ log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64
+ " path='%s'",
+ address, mod_date, file_spec.GetPath().c_str());
}
+ for (uint32_t i = 0; i < segments.size(); ++i)
+ segments[i].PutToLog(log, slide);
+ }
}
-void
-DynamicLoaderDarwin::PrivateInitialize(Process *process)
-{
- DEBUG_PRINTF("DynamicLoaderDarwin::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
- Clear(true);
- m_process = process;
- m_process->GetTarget().ClearAllLoadedSections();
+void DynamicLoaderDarwin::PrivateInitialize(Process *process) {
+ DEBUG_PRINTF("DynamicLoaderDarwin::%s() process state = %s\n", __FUNCTION__,
+ StateAsCString(m_process->GetState()));
+ Clear(true);
+ m_process = process;
+ m_process->GetTarget().ClearAllLoadedSections();
}
//----------------------------------------------------------------------
// Member function that gets called when the process state changes.
//----------------------------------------------------------------------
-void
-DynamicLoaderDarwin::PrivateProcessStateChanged (Process *process, StateType state)
-{
- DEBUG_PRINTF("DynamicLoaderDarwin::%s(%s)\n", __FUNCTION__, StateAsCString(state));
- switch (state)
- {
- case eStateConnected:
- case eStateAttaching:
- case eStateLaunching:
- case eStateInvalid:
- case eStateUnloaded:
- case eStateExited:
- case eStateDetached:
- Clear(false);
- break;
-
- case eStateStopped:
- // Keep trying find dyld and set our notification breakpoint each time
- // we stop until we succeed
- if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
- {
- if (NeedToDoInitialImageFetch ())
- DoInitialImageFetch ();
-
- SetNotificationBreakpoint ();
- }
- break;
-
- case eStateRunning:
- case eStateStepping:
- case eStateCrashed:
- case eStateSuspended:
- break;
+void DynamicLoaderDarwin::PrivateProcessStateChanged(Process *process,
+ StateType state) {
+ DEBUG_PRINTF("DynamicLoaderDarwin::%s(%s)\n", __FUNCTION__,
+ StateAsCString(state));
+ switch (state) {
+ case eStateConnected:
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateInvalid:
+ case eStateUnloaded:
+ case eStateExited:
+ case eStateDetached:
+ Clear(false);
+ break;
+
+ case eStateStopped:
+ // Keep trying find dyld and set our notification breakpoint each time
+ // we stop until we succeed
+ if (!DidSetNotificationBreakpoint() && m_process->IsAlive()) {
+ if (NeedToDoInitialImageFetch())
+ DoInitialImageFetch();
+
+ SetNotificationBreakpoint();
}
+ break;
+
+ case eStateRunning:
+ case eStateStepping:
+ case eStateCrashed:
+ case eStateSuspended:
+ break;
+ }
}
ThreadPlanSP
-DynamicLoaderDarwin::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
-{
- ThreadPlanSP thread_plan_sp;
- StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
- const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
- Symbol *current_symbol = current_context.symbol;
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- TargetSP target_sp (thread.CalculateTarget());
-
- if (current_symbol != NULL)
- {
- std::vector<Address> addresses;
-
- if (current_symbol->IsTrampoline())
- {
- const ConstString &trampoline_name = current_symbol->GetMangled().GetName(current_symbol->GetLanguage(), Mangled::ePreferMangled);
-
- if (trampoline_name)
- {
- const ModuleList &images = target_sp->GetImages();
-
- SymbolContextList code_symbols;
- images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, code_symbols);
- size_t num_code_symbols = code_symbols.GetSize();
-
- if (num_code_symbols > 0)
- {
- for (uint32_t i = 0; i < num_code_symbols; i++)
- {
- SymbolContext context;
- AddressRange addr_range;
- if (code_symbols.GetContextAtIndex(i, context))
- {
- context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
- addresses.push_back(addr_range.GetBaseAddress());
- if (log)
- {
- addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
-
- log->Printf ("Found a trampoline target symbol at 0x%" PRIx64 ".", load_addr);
- }
- }
- }
- }
-
- SymbolContextList reexported_symbols;
- images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeReExported, reexported_symbols);
- size_t num_reexported_symbols = reexported_symbols.GetSize();
- if (num_reexported_symbols > 0)
- {
- for (uint32_t i = 0; i < num_reexported_symbols; i++)
- {
- SymbolContext context;
- if (reexported_symbols.GetContextAtIndex(i, context))
- {
- if (context.symbol)
- {
- Symbol *actual_symbol = context.symbol->ResolveReExportedSymbol(*target_sp.get());
- if (actual_symbol)
- {
- const Address actual_symbol_addr = actual_symbol->GetAddress();
- if (actual_symbol_addr.IsValid())
- {
- addresses.push_back(actual_symbol_addr);
- if (log)
- {
- lldb::addr_t load_addr = actual_symbol_addr.GetLoadAddress(target_sp.get());
- log->Printf ("Found a re-exported symbol: %s at 0x%" PRIx64 ".",
- actual_symbol->GetName().GetCString(), load_addr);
- }
- }
- }
- }
- }
- }
- }
-
- SymbolContextList indirect_symbols;
- images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver, indirect_symbols);
- size_t num_indirect_symbols = indirect_symbols.GetSize();
- if (num_indirect_symbols > 0)
- {
- for (uint32_t i = 0; i < num_indirect_symbols; i++)
- {
- SymbolContext context;
- AddressRange addr_range;
- if (indirect_symbols.GetContextAtIndex(i, context))
- {
- context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
- addresses.push_back(addr_range.GetBaseAddress());
- if (log)
- {
- addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
-
- log->Printf ("Found an indirect target symbol at 0x%" PRIx64 ".", load_addr);
- }
- }
- }
- }
+DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
+ bool stop_others) {
+ ThreadPlanSP thread_plan_sp;
+ StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
+ const SymbolContext &current_context =
+ current_frame->GetSymbolContext(eSymbolContextSymbol);
+ Symbol *current_symbol = current_context.symbol;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ TargetSP target_sp(thread.CalculateTarget());
+
+ if (current_symbol != NULL) {
+ std::vector<Address> addresses;
+
+ if (current_symbol->IsTrampoline()) {
+ const ConstString &trampoline_name = current_symbol->GetMangled().GetName(
+ current_symbol->GetLanguage(), Mangled::ePreferMangled);
+
+ if (trampoline_name) {
+ const ModuleList &images = target_sp->GetImages();
+
+ SymbolContextList code_symbols;
+ images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode,
+ code_symbols);
+ size_t num_code_symbols = code_symbols.GetSize();
+
+ if (num_code_symbols > 0) {
+ for (uint32_t i = 0; i < num_code_symbols; i++) {
+ SymbolContext context;
+ AddressRange addr_range;
+ if (code_symbols.GetContextAtIndex(i, context)) {
+ context.GetAddressRange(eSymbolContextEverything, 0, false,
+ addr_range);
+ addresses.push_back(addr_range.GetBaseAddress());
+ if (log) {
+ addr_t load_addr =
+ addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
+
+ log->Printf("Found a trampoline target symbol at 0x%" PRIx64
+ ".",
+ load_addr);
+ }
}
+ }
}
- else if (current_symbol->GetType() == eSymbolTypeReExported)
- {
- // I am not sure we could ever end up stopped AT a re-exported symbol. But just in case:
-
- const Symbol *actual_symbol = current_symbol->ResolveReExportedSymbol(*(target_sp.get()));
- if (actual_symbol)
- {
- Address target_addr(actual_symbol->GetAddress());
- if (target_addr.IsValid())
- {
- if (log)
- log->Printf ("Found a re-exported symbol: %s pointing to: %s at 0x%" PRIx64 ".",
- current_symbol->GetName().GetCString(),
- actual_symbol->GetName().GetCString(),
- target_addr.GetLoadAddress(target_sp.get()));
- addresses.push_back (target_addr.GetLoadAddress(target_sp.get()));
-
+
+ SymbolContextList reexported_symbols;
+ images.FindSymbolsWithNameAndType(
+ trampoline_name, eSymbolTypeReExported, reexported_symbols);
+ size_t num_reexported_symbols = reexported_symbols.GetSize();
+ if (num_reexported_symbols > 0) {
+ for (uint32_t i = 0; i < num_reexported_symbols; i++) {
+ SymbolContext context;
+ if (reexported_symbols.GetContextAtIndex(i, context)) {
+ if (context.symbol) {
+ Symbol *actual_symbol =
+ context.symbol->ResolveReExportedSymbol(*target_sp.get());
+ if (actual_symbol) {
+ const Address actual_symbol_addr =
+ actual_symbol->GetAddress();
+ if (actual_symbol_addr.IsValid()) {
+ addresses.push_back(actual_symbol_addr);
+ if (log) {
+ lldb::addr_t load_addr =
+ actual_symbol_addr.GetLoadAddress(target_sp.get());
+ log->Printf(
+ "Found a re-exported symbol: %s at 0x%" PRIx64 ".",
+ actual_symbol->GetName().GetCString(), load_addr);
+ }
+ }
}
+ }
}
+ }
}
-
- if (addresses.size() > 0)
- {
- // First check whether any of the addresses point to Indirect symbols, and if they do, resolve them:
- std::vector<lldb::addr_t> load_addrs;
- for (Address address : addresses)
- {
- Symbol *symbol = address.CalculateSymbolContextSymbol();
- if (symbol && symbol->IsIndirect())
- {
- Error error;
- Address symbol_address = symbol->GetAddress();
- addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction(&symbol_address, error);
- if (error.Success())
- {
- load_addrs.push_back(resolved_addr);
- if (log)
- log->Printf("ResolveIndirectFunction found resolved target for %s at 0x%" PRIx64 ".",
- symbol->GetName().GetCString(), resolved_addr);
- }
- }
- else
- {
- load_addrs.push_back(address.GetLoadAddress(target_sp.get()));
- }
-
+
+ SymbolContextList indirect_symbols;
+ images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver,
+ indirect_symbols);
+ size_t num_indirect_symbols = indirect_symbols.GetSize();
+ if (num_indirect_symbols > 0) {
+ for (uint32_t i = 0; i < num_indirect_symbols; i++) {
+ SymbolContext context;
+ AddressRange addr_range;
+ if (indirect_symbols.GetContextAtIndex(i, context)) {
+ context.GetAddressRange(eSymbolContextEverything, 0, false,
+ addr_range);
+ addresses.push_back(addr_range.GetBaseAddress());
+ if (log) {
+ addr_t load_addr =
+ addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
+
+ log->Printf("Found an indirect target symbol at 0x%" PRIx64 ".",
+ load_addr);
+ }
}
- thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, load_addrs, stop_others));
+ }
}
+ }
+ } else if (current_symbol->GetType() == eSymbolTypeReExported) {
+ // I am not sure we could ever end up stopped AT a re-exported symbol.
+ // But just in case:
+
+ const Symbol *actual_symbol =
+ current_symbol->ResolveReExportedSymbol(*(target_sp.get()));
+ if (actual_symbol) {
+ Address target_addr(actual_symbol->GetAddress());
+ if (target_addr.IsValid()) {
+ if (log)
+ log->Printf(
+ "Found a re-exported symbol: %s pointing to: %s at 0x%" PRIx64
+ ".",
+ current_symbol->GetName().GetCString(),
+ actual_symbol->GetName().GetCString(),
+ target_addr.GetLoadAddress(target_sp.get()));
+ addresses.push_back(target_addr.GetLoadAddress(target_sp.get()));
+ }
+ }
}
- else
- {
- if (log)
- log->Printf ("Could not find symbol for step through.");
+
+ if (addresses.size() > 0) {
+ // First check whether any of the addresses point to Indirect symbols, and
+ // if they do, resolve them:
+ std::vector<lldb::addr_t> load_addrs;
+ for (Address address : addresses) {
+ Symbol *symbol = address.CalculateSymbolContextSymbol();
+ if (symbol && symbol->IsIndirect()) {
+ Error error;
+ Address symbol_address = symbol->GetAddress();
+ addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction(
+ &symbol_address, error);
+ if (error.Success()) {
+ load_addrs.push_back(resolved_addr);
+ if (log)
+ log->Printf("ResolveIndirectFunction found resolved target for "
+ "%s at 0x%" PRIx64 ".",
+ symbol->GetName().GetCString(), resolved_addr);
+ }
+ } else {
+ load_addrs.push_back(address.GetLoadAddress(target_sp.get()));
+ }
+ }
+ thread_plan_sp.reset(
+ new ThreadPlanRunToAddress(thread, load_addrs, stop_others));
}
+ } else {
+ if (log)
+ log->Printf("Could not find symbol for step through.");
+ }
- return thread_plan_sp;
+ return thread_plan_sp;
}
-size_t
-DynamicLoaderDarwin::FindEquivalentSymbols (lldb_private::Symbol *original_symbol,
- lldb_private::ModuleList &images,
- lldb_private::SymbolContextList &equivalent_symbols)
-{
- const ConstString &trampoline_name = original_symbol->GetMangled().GetName(original_symbol->GetLanguage(), Mangled::ePreferMangled);
- if (!trampoline_name)
- return 0;
-
- size_t initial_size = equivalent_symbols.GetSize();
-
- static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Za-z0-9\\$]+)$";
- std::string equivalent_regex_buf("^");
- equivalent_regex_buf.append (trampoline_name.GetCString());
- equivalent_regex_buf.append (resolver_name_regex);
-
- RegularExpression equivalent_name_regex (equivalent_regex_buf.c_str());
- const bool append = true;
- images.FindSymbolsMatchingRegExAndType (equivalent_name_regex, eSymbolTypeCode, equivalent_symbols, append);
-
- return equivalent_symbols.GetSize() - initial_size;
+size_t DynamicLoaderDarwin::FindEquivalentSymbols(
+ lldb_private::Symbol *original_symbol, lldb_private::ModuleList &images,
+ lldb_private::SymbolContextList &equivalent_symbols) {
+ const ConstString &trampoline_name = original_symbol->GetMangled().GetName(
+ original_symbol->GetLanguage(), Mangled::ePreferMangled);
+ if (!trampoline_name)
+ return 0;
+
+ size_t initial_size = equivalent_symbols.GetSize();
+
+ static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Za-z0-9\\$]+)$";
+ std::string equivalent_regex_buf("^");
+ equivalent_regex_buf.append(trampoline_name.GetCString());
+ equivalent_regex_buf.append(resolver_name_regex);
+
+ RegularExpression equivalent_name_regex(equivalent_regex_buf);
+ const bool append = true;
+ images.FindSymbolsMatchingRegExAndType(equivalent_name_regex, eSymbolTypeCode,
+ equivalent_symbols, append);
+
+ return equivalent_symbols.GetSize() - initial_size;
}
-lldb::ModuleSP
-DynamicLoaderDarwin::GetPThreadLibraryModule()
-{
- ModuleSP module_sp = m_libpthread_module_wp.lock();
- if (!module_sp)
- {
- SymbolContextList sc_list;
- ModuleSpec module_spec;
- module_spec.GetFileSpec().GetFilename().SetCString("libsystem_pthread.dylib");
- ModuleList module_list;
- if (m_process->GetTarget().GetImages().FindModules(module_spec, module_list))
- {
- if (module_list.GetSize() == 1)
- {
- module_sp = module_list.GetModuleAtIndex(0);
- if (module_sp)
- m_libpthread_module_wp = module_sp;
- }
- }
+lldb::ModuleSP DynamicLoaderDarwin::GetPThreadLibraryModule() {
+ ModuleSP module_sp = m_libpthread_module_wp.lock();
+ if (!module_sp) {
+ SymbolContextList sc_list;
+ ModuleSpec module_spec;
+ module_spec.GetFileSpec().GetFilename().SetCString(
+ "libsystem_pthread.dylib");
+ ModuleList module_list;
+ if (m_process->GetTarget().GetImages().FindModules(module_spec,
+ module_list)) {
+ if (module_list.GetSize() == 1) {
+ module_sp = module_list.GetModuleAtIndex(0);
+ if (module_sp)
+ m_libpthread_module_wp = module_sp;
+ }
}
- return module_sp;
+ }
+ return module_sp;
}
-Address
-DynamicLoaderDarwin::GetPthreadSetSpecificAddress()
-{
- if (!m_pthread_getspecific_addr.IsValid())
- {
- ModuleSP module_sp = GetPThreadLibraryModule();
- if (module_sp)
- {
- lldb_private::SymbolContextList sc_list;
- module_sp->FindSymbolsWithNameAndType(ConstString("pthread_getspecific"), eSymbolTypeCode, sc_list);
- SymbolContext sc;
- if (sc_list.GetContextAtIndex(0, sc))
- {
- if (sc.symbol)
- m_pthread_getspecific_addr = sc.symbol->GetAddress();
- }
- }
+Address DynamicLoaderDarwin::GetPthreadSetSpecificAddress() {
+ if (!m_pthread_getspecific_addr.IsValid()) {
+ ModuleSP module_sp = GetPThreadLibraryModule();
+ if (module_sp) {
+ lldb_private::SymbolContextList sc_list;
+ module_sp->FindSymbolsWithNameAndType(ConstString("pthread_getspecific"),
+ eSymbolTypeCode, sc_list);
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(0, sc)) {
+ if (sc.symbol)
+ m_pthread_getspecific_addr = sc.symbol->GetAddress();
+ }
}
- return m_pthread_getspecific_addr;
+ }
+ return m_pthread_getspecific_addr;
}
lldb::addr_t
-DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp, const lldb::ThreadSP thread_sp,
- lldb::addr_t tls_file_addr)
-{
- if (!thread_sp || !module_sp)
- return LLDB_INVALID_ADDRESS;
-
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
-
- const uint32_t addr_size = m_process->GetAddressByteSize();
- uint8_t buf[sizeof(lldb::addr_t) * 3];
-
- lldb_private::Address tls_addr;
- if (module_sp->ResolveFileAddress(tls_file_addr, tls_addr))
- {
- Error error;
- const size_t tsl_data_size = addr_size * 3;
- Target &target = m_process->GetTarget();
- if (target.ReadMemory(tls_addr, false, buf, tsl_data_size, error) == tsl_data_size)
- {
- const ByteOrder byte_order = m_process->GetByteOrder();
- DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
- lldb::offset_t offset = addr_size; // Skip the first pointer
- const lldb::addr_t pthread_key = data.GetAddress(&offset);
- const lldb::addr_t tls_offset = data.GetAddress(&offset);
- if (pthread_key != 0)
- {
- // First check to see if we have already figured out the location
- // of TLS data for the pthread_key on a specific thread yet. If we
- // have we can re-use it since its location will not change unless
- // the process execs.
- const tid_t tid = thread_sp->GetID();
- auto tid_pos = m_tid_to_tls_map.find(tid);
- if (tid_pos != m_tid_to_tls_map.end())
- {
- auto tls_pos = tid_pos->second.find(pthread_key);
- if (tls_pos != tid_pos->second.end())
- {
- return tls_pos->second + tls_offset;
- }
- }
- StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(0);
- if (frame_sp)
- {
- ClangASTContext *clang_ast_context = target.GetScratchClangASTContext();
-
- if (!clang_ast_context)
- return LLDB_INVALID_ADDRESS;
-
- CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- Address pthread_getspecific_addr = GetPthreadSetSpecificAddress();
- if (pthread_getspecific_addr.IsValid())
- {
- EvaluateExpressionOptions options;
-
- lldb::ThreadPlanSP thread_plan_sp(
- new ThreadPlanCallFunction(*thread_sp, pthread_getspecific_addr, clang_void_ptr_type,
- llvm::ArrayRef<lldb::addr_t>(pthread_key), options));
-
- DiagnosticManager execution_errors;
- ExecutionContext exe_ctx(thread_sp);
- lldb::ExpressionResults results =
- m_process->RunThreadPlan(exe_ctx, thread_plan_sp, options, execution_errors);
-
- if (results == lldb::eExpressionCompleted)
- {
- lldb::ValueObjectSP result_valobj_sp = thread_plan_sp->GetReturnValueObject();
- if (result_valobj_sp)
- {
- const lldb::addr_t pthread_key_data = result_valobj_sp->GetValueAsUnsigned(0);
- if (pthread_key_data)
- {
- m_tid_to_tls_map[tid].insert(std::make_pair(pthread_key, pthread_key_data));
- return pthread_key_data + tls_offset;
- }
- }
- }
- }
+DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp,
+ const lldb::ThreadSP thread_sp,
+ lldb::addr_t tls_file_addr) {
+ if (!thread_sp || !module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+
+ const uint32_t addr_size = m_process->GetAddressByteSize();
+ uint8_t buf[sizeof(lldb::addr_t) * 3];
+
+ lldb_private::Address tls_addr;
+ if (module_sp->ResolveFileAddress(tls_file_addr, tls_addr)) {
+ Error error;
+ const size_t tsl_data_size = addr_size * 3;
+ Target &target = m_process->GetTarget();
+ if (target.ReadMemory(tls_addr, false, buf, tsl_data_size, error) ==
+ tsl_data_size) {
+ const ByteOrder byte_order = m_process->GetByteOrder();
+ DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
+ lldb::offset_t offset = addr_size; // Skip the first pointer
+ const lldb::addr_t pthread_key = data.GetAddress(&offset);
+ const lldb::addr_t tls_offset = data.GetAddress(&offset);
+ if (pthread_key != 0) {
+ // First check to see if we have already figured out the location
+ // of TLS data for the pthread_key on a specific thread yet. If we
+ // have we can re-use it since its location will not change unless
+ // the process execs.
+ const tid_t tid = thread_sp->GetID();
+ auto tid_pos = m_tid_to_tls_map.find(tid);
+ if (tid_pos != m_tid_to_tls_map.end()) {
+ auto tls_pos = tid_pos->second.find(pthread_key);
+ if (tls_pos != tid_pos->second.end()) {
+ return tls_pos->second + tls_offset;
+ }
+ }
+ StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(0);
+ if (frame_sp) {
+ ClangASTContext *clang_ast_context =
+ target.GetScratchClangASTContext();
+
+ if (!clang_ast_context)
+ return LLDB_INVALID_ADDRESS;
+
+ CompilerType clang_void_ptr_type =
+ clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ Address pthread_getspecific_addr = GetPthreadSetSpecificAddress();
+ if (pthread_getspecific_addr.IsValid()) {
+ EvaluateExpressionOptions options;
+
+ lldb::ThreadPlanSP thread_plan_sp(new ThreadPlanCallFunction(
+ *thread_sp, pthread_getspecific_addr, clang_void_ptr_type,
+ llvm::ArrayRef<lldb::addr_t>(pthread_key), options));
+
+ DiagnosticManager execution_errors;
+ ExecutionContext exe_ctx(thread_sp);
+ lldb::ExpressionResults results = m_process->RunThreadPlan(
+ exe_ctx, thread_plan_sp, options, execution_errors);
+
+ if (results == lldb::eExpressionCompleted) {
+ lldb::ValueObjectSP result_valobj_sp =
+ thread_plan_sp->GetReturnValueObject();
+ if (result_valobj_sp) {
+ const lldb::addr_t pthread_key_data =
+ result_valobj_sp->GetValueAsUnsigned(0);
+ if (pthread_key_data) {
+ m_tid_to_tls_map[tid].insert(
+ std::make_pair(pthread_key, pthread_key_data));
+ return pthread_key_data + tls_offset;
}
+ }
}
+ }
}
+ }
}
- return LLDB_INVALID_ADDRESS;
+ }
+ return LLDB_INVALID_ADDRESS;
}
+bool DynamicLoaderDarwin::UseDYLDSPI(Process *process) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ uint32_t major, minor, update;
+
+ bool use_new_spi_interface = false;
+
+ if (process->GetHostOSVersion(major, minor, update)) {
+ const llvm::Triple::OSType os_type =
+ process->GetTarget().GetArchitecture().GetTriple().getOS();
+
+ // macOS 10.12 and newer
+ if (os_type == llvm::Triple::MacOSX &&
+ (major > 10 || (major == 10 && minor >= 12))) {
+ use_new_spi_interface = true;
+ }
+
+ // iOS 10 and newer
+ if (os_type == llvm::Triple::IOS && major >= 10) {
+ use_new_spi_interface = true;
+ }
+
+ // tvOS 10 and newer
+ if (os_type == llvm::Triple::TvOS && major >= 10) {
+ use_new_spi_interface = true;
+ }
+
+ // watchOS 3 and newer
+ if (os_type == llvm::Triple::WatchOS && major >= 3) {
+ use_new_spi_interface = true;
+ }
+ }
+
+ if (log) {
+ if (use_new_spi_interface)
+ log->Printf(
+ "DynamicLoaderDarwin::UseDYLDSPI: Use new DynamicLoader plugin");
+ else
+ log->Printf(
+ "DynamicLoaderDarwin::UseDYLDSPI: Use old DynamicLoader plugin");
+ }
+ return use_new_spi_interface;
+}