================ @@ -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)) { ---------------- bulbazord wrote:
> Minor nit, but I don't like to prefix addr_ts with the lldb:: namespace, > except in headers where it's required. I'm also not a fan... I was mostly preserving existing convention here. I don't mind removing them :) 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