@@ -1076,74 +1076,104 @@ DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp,
1076
1076
1077
1077
std::lock_guard<std::recursive_mutex> guard (m_mutex);
1078
1078
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
+
1079
1130
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;
1081
1138
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;
1145
1168
}
1146
1169
}
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
+ }
1147
1177
}
1148
1178
return LLDB_INVALID_ADDRESS;
1149
1179
}
0 commit comments