@@ -1076,74 +1076,104 @@ DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp,
10761076
10771077 std::lock_guard<std::recursive_mutex> guard (m_mutex);
10781078
1079+ lldb_private::Address tls_addr;
1080+ if (!module_sp->ResolveFileAddress (tls_file_addr, tls_addr))
1081+ return LLDB_INVALID_ADDRESS;
1082+
1083+ Target &target = m_process->GetTarget ();
1084+ TypeSystemClangSP scratch_ts_sp =
1085+ ScratchTypeSystemClang::GetForTarget (target);
1086+ if (!scratch_ts_sp)
1087+ return LLDB_INVALID_ADDRESS;
1088+
1089+ CompilerType clang_void_ptr_type =
1090+ scratch_ts_sp->GetBasicType (eBasicTypeVoid).GetPointerType ();
1091+
1092+ auto evaluate_tls_address = [this , &thread_sp, &clang_void_ptr_type](
1093+ Address func_ptr,
1094+ llvm::ArrayRef<addr_t > args) -> addr_t {
1095+ EvaluateExpressionOptions options;
1096+
1097+ lldb::ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (
1098+ *thread_sp, func_ptr, clang_void_ptr_type, args, options));
1099+
1100+ DiagnosticManager execution_errors;
1101+ ExecutionContext exe_ctx (thread_sp);
1102+ lldb::ExpressionResults results = m_process->RunThreadPlan (
1103+ exe_ctx, thread_plan_sp, options, execution_errors);
1104+
1105+ if (results == lldb::eExpressionCompleted) {
1106+ if (lldb::ValueObjectSP result_valobj_sp =
1107+ thread_plan_sp->GetReturnValueObject ()) {
1108+ return result_valobj_sp->GetValueAsUnsigned (LLDB_INVALID_ADDRESS);
1109+ }
1110+ }
1111+ return LLDB_INVALID_ADDRESS;
1112+ };
1113+
1114+ // On modern apple platforms, there is a small data structure that looks
1115+ // approximately like this:
1116+ // struct TLS_Thunk {
1117+ // void *(*get_addr)(struct TLS_Thunk *);
1118+ // size_t key;
1119+ // size_t offset;
1120+ // }
1121+ //
1122+ // The strategy is to take get_addr, call it with the address of the
1123+ // containing TLS_Thunk structure, and add the offset to the resulting
1124+ // pointer to get the data block.
1125+ //
1126+ // On older apple platforms, the key is treated as a pthread_key_t and passed
1127+ // to pthread_getspecific. The pointer returned from that call is added to
1128+ // offset to get the relevant data block.
1129+
10791130 const uint32_t addr_size = m_process->GetAddressByteSize ();
1080- uint8_t buf[sizeof (lldb::addr_t ) * 3 ];
1131+ uint8_t buf[sizeof (addr_t ) * 3 ];
1132+ Status error;
1133+ const size_t tls_data_size = addr_size * 3 ;
1134+ const size_t bytes_read = target.ReadMemory (
1135+ tls_addr, buf, tls_data_size, error, /* force_live_memory = */ true );
1136+ if (bytes_read != tls_data_size || error.Fail ())
1137+ return LLDB_INVALID_ADDRESS;
10811138
1082- lldb_private::Address tls_addr;
1083- if (module_sp->ResolveFileAddress (tls_file_addr, tls_addr)) {
1084- Status error;
1085- const size_t tsl_data_size = addr_size * 3 ;
1086- Target &target = m_process->GetTarget ();
1087- if (target.ReadMemory (tls_addr, buf, tsl_data_size, error, true ) ==
1088- tsl_data_size) {
1089- const ByteOrder byte_order = m_process->GetByteOrder ();
1090- DataExtractor data (buf, sizeof (buf), byte_order, addr_size);
1091- lldb::offset_t offset = addr_size; // Skip the first pointer
1092- const lldb::addr_t pthread_key = data.GetAddress (&offset);
1093- const lldb::addr_t tls_offset = data.GetAddress (&offset);
1094- if (pthread_key != 0 ) {
1095- // First check to see if we have already figured out the location of
1096- // TLS data for the pthread_key on a specific thread yet. If we have we
1097- // can re-use it since its location will not change unless the process
1098- // execs.
1099- const tid_t tid = thread_sp->GetID ();
1100- auto tid_pos = m_tid_to_tls_map.find (tid);
1101- if (tid_pos != m_tid_to_tls_map.end ()) {
1102- auto tls_pos = tid_pos->second .find (pthread_key);
1103- if (tls_pos != tid_pos->second .end ()) {
1104- return tls_pos->second + tls_offset;
1105- }
1106- }
1107- StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex (0 );
1108- if (frame_sp) {
1109- TypeSystemClangSP scratch_ts_sp =
1110- ScratchTypeSystemClang::GetForTarget (target);
1111-
1112- if (!scratch_ts_sp)
1113- return LLDB_INVALID_ADDRESS;
1114-
1115- CompilerType clang_void_ptr_type =
1116- scratch_ts_sp->GetBasicType (eBasicTypeVoid).GetPointerType ();
1117- Address pthread_getspecific_addr = GetPthreadSetSpecificAddress ();
1118- if (pthread_getspecific_addr.IsValid ()) {
1119- EvaluateExpressionOptions options;
1120-
1121- lldb::ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (
1122- *thread_sp, pthread_getspecific_addr, clang_void_ptr_type,
1123- llvm::ArrayRef<lldb::addr_t >(pthread_key), options));
1124-
1125- DiagnosticManager execution_errors;
1126- ExecutionContext exe_ctx (thread_sp);
1127- lldb::ExpressionResults results = m_process->RunThreadPlan (
1128- exe_ctx, thread_plan_sp, options, execution_errors);
1129-
1130- if (results == lldb::eExpressionCompleted) {
1131- lldb::ValueObjectSP result_valobj_sp =
1132- thread_plan_sp->GetReturnValueObject ();
1133- if (result_valobj_sp) {
1134- const lldb::addr_t pthread_key_data =
1135- result_valobj_sp->GetValueAsUnsigned (0 );
1136- if (pthread_key_data) {
1137- m_tid_to_tls_map[tid].insert (
1138- std::make_pair (pthread_key, pthread_key_data));
1139- return pthread_key_data + tls_offset;
1140- }
1141- }
1142- }
1143- }
1144- }
1139+ DataExtractor data (buf, sizeof (buf), m_process->GetByteOrder (), addr_size);
1140+ lldb::offset_t offset = 0 ;
1141+ const addr_t tls_thunk = data.GetAddress (&offset);
1142+ const addr_t key = data.GetAddress (&offset);
1143+ const addr_t tls_offset = data.GetAddress (&offset);
1144+
1145+ if (tls_thunk != 0 ) {
1146+ const addr_t fixed_tls_thunk = m_process->FixCodeAddress (tls_thunk);
1147+ Address thunk_load_addr;
1148+ if (target.ResolveLoadAddress (fixed_tls_thunk, thunk_load_addr)) {
1149+ const addr_t tls_load_addr = tls_addr.GetLoadAddress (&target);
1150+ const addr_t tls_data = evaluate_tls_address (
1151+ thunk_load_addr, llvm::ArrayRef<addr_t >(tls_load_addr));
1152+ if (tls_data != LLDB_INVALID_ADDRESS)
1153+ return tls_data + tls_offset;
1154+ }
1155+ }
1156+
1157+ if (key != 0 ) {
1158+ // First check to see if we have already figured out the location of
1159+ // TLS data for the pthread_key on a specific thread yet. If we have we
1160+ // can re-use it since its location will not change unless the process
1161+ // execs.
1162+ const tid_t tid = thread_sp->GetID ();
1163+ auto tid_pos = m_tid_to_tls_map.find (tid);
1164+ if (tid_pos != m_tid_to_tls_map.end ()) {
1165+ auto tls_pos = tid_pos->second .find (key);
1166+ if (tls_pos != tid_pos->second .end ()) {
1167+ return tls_pos->second + tls_offset;
11451168 }
11461169 }
1170+ Address pthread_getspecific_addr = GetPthreadSetSpecificAddress ();
1171+ if (pthread_getspecific_addr.IsValid ()) {
1172+ const addr_t tls_data = evaluate_tls_address (pthread_getspecific_addr,
1173+ llvm::ArrayRef<addr_t >(key));
1174+ if (tls_data != LLDB_INVALID_ADDRESS)
1175+ return tls_data + tls_offset;
1176+ }
11471177 }
11481178 return LLDB_INVALID_ADDRESS;
11491179}
0 commit comments