llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Alex Langford (bulbazord) <details> <summary>Changes</summary> I decided to resubmit #<!-- -->77854 but broken up into multiple commits for better reviewability. I recommend reviewing each commit individually, the overall change is quite large. rdar://120676969 --- Full diff: https://github.com/llvm/llvm-project/pull/77988.diff 1 Files Affected: - (modified) lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp (+92-63) ``````````diff diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp index 1e3e2e5641ad83..3bfa3778ad8f9c 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -1048,74 +1048,103 @@ DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp, std::lock_guard<std::recursive_mutex> guard(m_mutex); + lldb_private::Address tls_addr; + if (!module_sp->ResolveFileAddress(tls_file_addr, tls_addr)) + return LLDB_INVALID_ADDRESS; + + Target &target = m_process->GetTarget(); + TypeSystemClangSP scratch_ts_sp = + ScratchTypeSystemClang::GetForTarget(target); + if (!scratch_ts_sp) + return LLDB_INVALID_ADDRESS; + + CompilerType clang_void_ptr_type = + scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); + + auto evaluate_tls_address = [this, &thread_sp, &clang_void_ptr_type]( + Address func_ptr, + llvm::ArrayRef<addr_t> args) -> lldb::addr_t { + EvaluateExpressionOptions options; + + lldb::ThreadPlanSP thread_plan_sp(new ThreadPlanCallFunction( + *thread_sp, func_ptr, clang_void_ptr_type, args, 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) { + if (lldb::ValueObjectSP result_valobj_sp = + thread_plan_sp->GetReturnValueObject()) { + return result_valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + } + } + return LLDB_INVALID_ADDRESS; + }; + + // On modern apple platforms, there is a small data structure that looks + // approximately like this: + // struct TLS_Thunk { + // void *(*get_addr)(struct TLS_Thunk *); + // size_t key; + // size_t offset; + // } + // + // The strategy is to take get_addr, call it with the address of the + // containing TLS_Thunk structure, and add the offset to the resulting + // pointer to get the data block. + // + // On older apple platforms, the key is treated as a pthread_key_t and passed + // to pthread_getspecific. The pointer returned from that call is added to + // offset to get the relevant data block. + const uint32_t addr_size = m_process->GetAddressByteSize(); uint8_t buf[sizeof(lldb::addr_t) * 3]; + Status error; + const size_t tls_data_size = addr_size * 3; + const size_t bytes_read = target.ReadMemory( + tls_addr, buf, tls_data_size, error, /*force_live_memory = */ true); + if (bytes_read != tls_data_size || error.Fail()) + return LLDB_INVALID_ADDRESS; - lldb_private::Address tls_addr; - if (module_sp->ResolveFileAddress(tls_file_addr, tls_addr)) { - Status error; - const size_t tsl_data_size = addr_size * 3; - Target &target = m_process->GetTarget(); - if (target.ReadMemory(tls_addr, buf, tsl_data_size, error, true) == - 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) { - TypeSystemClangSP scratch_ts_sp = - ScratchTypeSystemClang::GetForTarget(target); - - if (!scratch_ts_sp) - return LLDB_INVALID_ADDRESS; - - CompilerType clang_void_ptr_type = - scratch_ts_sp->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; - } - } - } - } - } + DataExtractor data(buf, sizeof(buf), m_process->GetByteOrder(), addr_size); + lldb::offset_t offset = 0; + const lldb::addr_t tls_thunk = data.GetAddress(&offset); + const lldb::addr_t key = data.GetAddress(&offset); + const lldb::addr_t tls_offset = data.GetAddress(&offset); + + if (tls_thunk != 0) { + Address thunk_load_addr; + if (target.ResolveLoadAddress(tls_thunk, thunk_load_addr)) { + const lldb::addr_t tls_load_addr = tls_addr.GetLoadAddress(&target); + const lldb::addr_t tls_data = evaluate_tls_address( + thunk_load_addr, llvm::ArrayRef<lldb::addr_t>(tls_load_addr)); + if (tls_data != LLDB_INVALID_ADDRESS) + return tls_data + tls_offset; + } + } + + if (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(key); + if (tls_pos != tid_pos->second.end()) { + return tls_pos->second + tls_offset; } } + Address pthread_getspecific_addr = GetPthreadSetSpecificAddress(); + if (pthread_getspecific_addr.IsValid()) { + const lldb::addr_t tls_data = evaluate_tls_address( + pthread_getspecific_addr, llvm::ArrayRef<lldb::addr_t>(key)); + if (tls_data != LLDB_INVALID_ADDRESS) + return tls_data + tls_offset; + } } return LLDB_INVALID_ADDRESS; } `````````` </details> https://github.com/llvm/llvm-project/pull/77988 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits