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