@@ -1048,74 +1048,104 @@ DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp,
10481048
10491049 std::lock_guard<std::recursive_mutex> guard (m_mutex);
10501050
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+
10511102 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;
10531110
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;
11171140 }
11181141 }
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+ }
11191149 }
11201150 return LLDB_INVALID_ADDRESS;
11211151}
0 commit comments