diff options
| -rw-r--r-- | lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp | 143 | ||||
| -rw-r--r-- | lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h | 54 |
2 files changed, 123 insertions, 74 deletions
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index d9391a017e8..1ca314d9815 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -39,7 +39,8 @@ using namespace lldb_private; PlatformDarwin::PlatformDarwin (bool is_host) : PlatformPOSIX(is_host), // This is the local host platform m_developer_directory (), - m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS) + m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS), + m_libdispatch_offsets() { } @@ -873,89 +874,89 @@ PlatformDarwin::GetQueueNameForThreadQAddress (Process *process, addr_t thread_d if (thread_dispatch_qaddr == LLDB_INVALID_ADDRESS || thread_dispatch_qaddr == 0 || process == NULL) return ""; - Target &target = process->GetTarget(); - - // Cache the dispatch_queue_offsets_addr value so we don't always have - // to look it up - if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS) + ReadLibdispatchOffsets (process); + if (m_libdispatch_offsets.IsValid ()) { - static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets"); - const Symbol *dispatch_queue_offsets_symbol = NULL; - - // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6 ("Snow Leopard") - ModuleSpec libSystem_module_spec (FileSpec("libSystem.B.dylib", false)); - ModuleSP module_sp(target.GetImages().FindFirstModule (libSystem_module_spec)); - if (module_sp) - dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); - - // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion") and later - if (dispatch_queue_offsets_symbol == NULL) + Error error; + addr_t queue_addr = process->ReadPointerFromMemory (thread_dispatch_qaddr, error); + if (error.Success()) { - ModuleSpec libdispatch_module_spec (FileSpec("libdispatch.dylib", false)); - module_sp = target.GetImages().FindFirstModule (libdispatch_module_spec); - if (module_sp) - dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); + if (m_libdispatch_offsets.dqo_version >= 4) + { + // libdispatch versions 4+, pointer to dispatch name is in the + // queue structure. + addr_t pointer_to_label_address = queue_addr + m_libdispatch_offsets.dqo_label; + addr_t label_addr = process->ReadPointerFromMemory (pointer_to_label_address, error); + if (error.Success()) + { + process->ReadCStringFromMemory (label_addr, dispatch_queue_name, error); + } + } + else + { + // libdispatch versions 1-3, dispatch name is a fixed width char array + // in the queue structure. + addr_t label_addr = queue_addr + m_libdispatch_offsets.dqo_label; + dispatch_queue_name.resize (m_libdispatch_offsets.dqo_label_size, '\0'); + size_t bytes_read = process->ReadMemory (label_addr, &dispatch_queue_name[0], m_libdispatch_offsets.dqo_label_size, error); + if (bytes_read < m_libdispatch_offsets.dqo_label_size) + dispatch_queue_name.erase (bytes_read); + } } - if (dispatch_queue_offsets_symbol) - m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetAddress().GetLoadAddress(&target); + } + return dispatch_queue_name; +} - if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS) - return ""; +void +PlatformDarwin::ReadLibdispatchOffsetsAddress (Process *process) +{ + if (m_dispatch_queue_offsets_addr != LLDB_INVALID_ADDRESS) + return; + + static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets"); + const Symbol *dispatch_queue_offsets_symbol = NULL; + + // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6 ("Snow Leopard") + ModuleSpec libSystem_module_spec (FileSpec("libSystem.B.dylib", false)); + ModuleSP module_sp(process->GetTarget().GetImages().FindFirstModule (libSystem_module_spec)); + if (module_sp) + dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); + + // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion") and later + if (dispatch_queue_offsets_symbol == NULL) + { + ModuleSpec libdispatch_module_spec (FileSpec("libdispatch.dylib", false)); + module_sp = process->GetTarget().GetImages().FindFirstModule (libdispatch_module_spec); + if (module_sp) + dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); } + if (dispatch_queue_offsets_symbol) + m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetAddress().GetLoadAddress(&process->GetTarget()); +} + +void +PlatformDarwin::ReadLibdispatchOffsets (Process *process) +{ + if (m_libdispatch_offsets.IsValid()) + return; - uint8_t memory_buffer[8]; + ReadLibdispatchOffsetsAddress (process); + + uint8_t memory_buffer[sizeof (struct LibdispatchOffsets)]; DataExtractor data (memory_buffer, sizeof(memory_buffer), - target.GetArchitecture().GetByteOrder(), - target.GetArchitecture().GetAddressByteSize()); - - // Excerpt from src/queue_private.h - // version 4 of this struct first appears in Mac OS X 10.9 ("Mavericks") and iOS 7. - // TODO When version 1-3 no longer needs to be supported, the dqo_label offset should be - // read from the inferior one time and saved in an ivar like m_dispatch_queue_offsets_addr. - struct dispatch_queue_offsets_s - { - uint16_t dqo_version; - uint16_t dqo_label; // in version 1-3, offset to string; in version 4+, offset to a pointer to a string - uint16_t dqo_label_size; // in version 1-3, length of string; in version 4+, size of a (void*) in this process - } dispatch_queue_offsets; + process->GetTarget().GetArchitecture().GetByteOrder(), + process->GetTarget().GetArchitecture().GetAddressByteSize()); Error error; - if (process->ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets)) + if (process->ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(memory_buffer), error) == sizeof(memory_buffer)) { lldb::offset_t data_offset = 0; - if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t))) - { - if (process->ReadMemory (thread_dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize()) - { - data_offset = 0; - lldb::addr_t queue_addr = data.GetAddress(&data_offset); - if (dispatch_queue_offsets.dqo_version >= 4) - { - // libdispatch versions 4+, pointer to dispatch name is in the - // queue structure. - lldb::addr_t pointer_to_label_address = queue_addr + dispatch_queue_offsets.dqo_label; - if (process->ReadMemory (pointer_to_label_address, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize()) - { - data_offset = 0; - lldb::addr_t label_addr = data.GetAddress(&data_offset); - process->ReadCStringFromMemory (label_addr, dispatch_queue_name, error); - } - } - else - { - // libdispatch versions 1-3, dispatch name is a fixed width char array - // in the queue structure. - lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label; - dispatch_queue_name.resize(dispatch_queue_offsets.dqo_label_size, '\0'); - size_t bytes_read = process->ReadMemory (label_addr, &dispatch_queue_name[0], dispatch_queue_offsets.dqo_label_size, error); - if (bytes_read < dispatch_queue_offsets.dqo_label_size) - dispatch_queue_name.erase (bytes_read); - } - } - } + + // The struct LibdispatchOffsets is a series of uint16_t's - extract them all + // in one big go. + data.GetU16 (&data_offset, &m_libdispatch_offsets.dqo_version, sizeof (struct LibdispatchOffsets) / sizeof (uint16_t)); } - return dispatch_queue_name; } lldb::queue_id_t diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h index 7a28d3c7e6e..e3d96179b36 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -134,6 +134,13 @@ public: GetResumeCountForLaunchInfo (lldb_private::ProcessLaunchInfo &launch_info); protected: + + lldb::addr_t + ReadLibdispatchOffsetsAddress (lldb_private::Process *process); + + void + ReadLibdispatchOffsets (lldb_private::Process *process); + virtual lldb_private::Error GetSharedModuleWithLocalCache (const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, @@ -141,9 +148,50 @@ protected: lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr); - std::string m_developer_directory; - lldb::addr_t m_dispatch_queue_offsets_addr; - + // Based on libdispatch src/queue_private.h, struct dispatch_queue_offsets_s + // With dqo_version 1-3, the dqo_label field is a per-queue value and cannot be cached. + // With dqo_version 4 (Mac OS X 10.9 / iOS 7), dqo_label is a constant value that can be cached. + struct LibdispatchOffsets + { + uint16_t dqo_version; + uint16_t dqo_label; + uint16_t dqo_label_size; + uint16_t dqo_flags; + uint16_t dqo_flags_size; + uint16_t dqo_serialnum; + uint16_t dqo_serialnum_size; + uint16_t dqo_width; + uint16_t dqo_width_size; + uint16_t dqo_running; + uint16_t dqo_running_size; + + LibdispatchOffsets () + { + dqo_version = UINT16_MAX; + dqo_flags = UINT16_MAX; + dqo_serialnum = UINT16_MAX; + dqo_label = UINT16_MAX; + dqo_width = UINT16_MAX; + dqo_running = UINT16_MAX; + }; + + bool + IsValid () + { + return dqo_version != UINT16_MAX; + } + + bool + LabelIsValid () + { + return dqo_label != UINT16_MAX; + } + }; + + std::string m_developer_directory; + lldb::addr_t m_dispatch_queue_offsets_addr; + struct LibdispatchOffsets m_libdispatch_offsets; + const char * GetDeveloperDirectory(); |

