@@ -2915,19 +2915,6 @@ std::optional<lldb::addr_t> SwiftLanguageRuntime::TrySkipVirtualParentProlog(
2915
2915
return pc_value;
2916
2916
}
2917
2917
2918
- // / Attempts to read the memory location at `task_addr_location`, producing
2919
- // / the Task pointer if possible.
2920
- static llvm::Expected<lldb::addr_t >
2921
- ReadTaskAddr (lldb::addr_t task_addr_location, Process &process) {
2922
- Status status;
2923
- addr_t task_addr = process.ReadPointerFromMemory (task_addr_location, status);
2924
- if (status.Fail ())
2925
- return llvm::joinErrors (
2926
- llvm::createStringError (" could not get current task from thread" ),
2927
- status.takeError ());
2928
- return task_addr;
2929
- }
2930
-
2931
2918
// / Compute the location where the Task pointer for `real_thread` is stored by
2932
2919
// / the runtime.
2933
2920
static llvm::Expected<lldb::addr_t >
@@ -2955,48 +2942,122 @@ ComputeTaskAddrLocationFromThreadLocalStorage(Thread &real_thread) {
2955
2942
#endif
2956
2943
}
2957
2944
2945
+ // / Helper function to read all `addresses` from process memory at once.
2946
+ static std::vector<llvm::Expected<addr_t >>
2947
+ vector_read_pointers_from_process_mem (
2948
+ Process &process, llvm::MutableArrayRef<llvm::Expected<addr_t >> addresses,
2949
+ StringRef error_msg) {
2950
+ std::vector<llvm::Expected<addr_t >> read_result;
2951
+ read_result.reserve (addresses.size ());
2952
+
2953
+ for (llvm::Expected<addr_t > &addr : addresses) {
2954
+ if (!addr) {
2955
+ read_result.push_back (std::move (addr));
2956
+ continue ;
2957
+ }
2958
+
2959
+ Status status;
2960
+ addr_t result = process.ReadPointerFromMemory (*addr, status);
2961
+ if (status.Fail ()) {
2962
+ read_result.push_back (llvm::joinErrors (llvm::createStringError (error_msg),
2963
+ status.takeError ()));
2964
+ } else
2965
+ read_result.push_back (result);
2966
+ }
2967
+
2968
+ return read_result;
2969
+ }
2970
+
2971
+ // / Helper function to read `addr` from process memory.
2972
+ static llvm::Expected<addr_t >
2973
+ read_pointer_from_process_mem (Process &process, llvm::Expected<addr_t > addr,
2974
+ StringRef error_msg) {
2975
+ auto read_result =
2976
+ vector_read_pointers_from_process_mem (process, addr, error_msg);
2977
+ return std::move (read_result[0 ]);
2978
+ }
2979
+
2958
2980
llvm::Expected<lldb::addr_t >
2959
2981
TaskInspector::GetTaskAddrFromThreadLocalStorage (Thread &thread) {
2960
- // Look through backing threads when inspecting TLS.
2961
- Thread &real_thread =
2962
- thread.GetBackingThread () ? *thread.GetBackingThread () : thread;
2982
+ return std::move (GetTaskAddrFromThreadLocalStorage (&thread)[0 ]);
2983
+ }
2984
+
2985
+ llvm::SmallVector<llvm::Expected<lldb::addr_t >>
2986
+ TaskInspector::GetTaskAddrLocations (llvm::ArrayRef<Thread *> threads) {
2987
+ llvm::SmallVector<llvm::Expected<addr_t >> addr_locations;
2988
+ addr_locations.reserve (threads.size ());
2963
2989
2964
- if (auto it = m_tid_to_task_addr_location.find (real_thread.GetID ());
2965
- it != m_tid_to_task_addr_location.end ()) {
2990
+ for (auto [idx, thread] : llvm::enumerate (threads)) {
2991
+ Thread &real_thread =
2992
+ thread->GetBackingThread () ? *thread->GetBackingThread () : *thread;
2993
+
2994
+ auto it = m_tid_to_task_addr_location.find (real_thread.GetID ());
2995
+ if (it != m_tid_to_task_addr_location.end ()) {
2996
+ addr_locations.push_back (it->second );
2966
2997
#ifndef NDEBUG
2967
- // In assert builds, check that caching did not produce incorrect results.
2968
- llvm::Expected<lldb::addr_t > task_addr_location =
2969
- ComputeTaskAddrLocationFromThreadLocalStorage (real_thread);
2970
- assert (task_addr_location);
2971
- assert (it->second == *task_addr_location);
2998
+ // In assert builds, check that caching did not produce incorrect results.
2999
+ llvm::Expected<lldb::addr_t > task_addr_location =
3000
+ ComputeTaskAddrLocationFromThreadLocalStorage (real_thread);
3001
+ assert (task_addr_location);
3002
+ assert (it->second == *task_addr_location);
2972
3003
#endif
2973
- llvm::Expected<lldb::addr_t > task_addr =
2974
- ReadTaskAddr (it->second , *thread.GetProcess ());
2975
- if (task_addr)
2976
- return task_addr;
2977
- // If the cached task addr location became invalid, invalidate the cache.
2978
- m_tid_to_task_addr_location.erase (it);
2979
- LLDB_LOG_ERROR (GetLog (LLDBLog::OS), task_addr.takeError (),
3004
+ continue ;
3005
+ }
3006
+ addr_locations.push_back (
3007
+ ComputeTaskAddrLocationFromThreadLocalStorage (real_thread));
3008
+ }
3009
+ return addr_locations;
3010
+ }
3011
+
3012
+ std::vector<llvm::Expected<addr_t >>
3013
+ TaskInspector::GetTaskAddrFromThreadLocalStorage (
3014
+ llvm::ArrayRef<Thread *> threads) {
3015
+ if (threads.empty ())
3016
+ return {};
3017
+
3018
+ llvm::SmallVector<llvm::Expected<addr_t >> addr_locations =
3019
+ GetTaskAddrLocations (threads);
3020
+
3021
+ Process &process = *threads[0 ]->GetProcess ();
3022
+ StringRef error_msg = " could not get current task from thread" ;
3023
+ std::vector<llvm::Expected<addr_t >> mem_read_results_vec =
3024
+ vector_read_pointers_from_process_mem (process, addr_locations, error_msg);
3025
+
3026
+ for (auto [idx, thread] : llvm::enumerate (threads)) {
3027
+ Thread &real_thread =
3028
+ thread->GetBackingThread () ? *thread->GetBackingThread () : *thread;
3029
+ user_id_t tid = real_thread.GetID ();
3030
+
3031
+ // If the read was successful, cache the address.
3032
+ if (mem_read_results_vec[idx]) {
3033
+ m_tid_to_task_addr_location[tid] = *addr_locations[idx];
3034
+ continue ;
3035
+ }
3036
+
3037
+ // For unsuccessful reads whose address was not cached, don't try again.
3038
+ if (!m_tid_to_task_addr_location.erase (tid))
3039
+ continue ;
3040
+
3041
+ LLDB_LOG_ERROR (GetLog (LLDBLog::OS), mem_read_results_vec[idx].takeError (),
2980
3042
" TaskInspector: evicted task location address due to "
2981
3043
" invalid memory read: {0}" );
2982
- }
2983
3044
2984
- llvm::Expected<lldb::addr_t > task_addr_location =
2985
- ComputeTaskAddrLocationFromThreadLocalStorage (real_thread);
2986
- if (!task_addr_location)
2987
- return task_addr_location;
3045
+ // The cached address could not be loaded. "This should never happen", but
3046
+ // recompute the address and try again for completeness.
3047
+ llvm::Expected<addr_t > task_addr_loc =
3048
+ ComputeTaskAddrLocationFromThreadLocalStorage (real_thread);
3049
+ if (!task_addr_loc) {
3050
+ mem_read_results_vec[idx] = std::move (task_addr_loc);
3051
+ continue ;
3052
+ }
2988
3053
2989
- llvm::Expected<lldb::addr_t > task_addr =
2990
- ReadTaskAddr (*task_addr_location, *thread.GetProcess ());
3054
+ mem_read_results_vec[idx] =
3055
+ read_pointer_from_process_mem (process, *task_addr_loc, error_msg);
3056
+ if (mem_read_results_vec[idx])
3057
+ m_tid_to_task_addr_location[tid] = *task_addr_loc;
3058
+ }
2991
3059
2992
- // If the read from this TLS address is successful, cache the TLS address.
2993
- // Caching without a valid read is dangerous: earlier in the thread
2994
- // lifetime, the result of GetExtendedInfo can be invalid.
2995
- if (task_addr &&
2996
- real_thread.GetProcess ()->GetTarget ().GetSwiftCacheTaskPointerLocation ())
2997
- m_tid_to_task_addr_location.try_emplace (real_thread.GetID (),
2998
- *task_addr_location);
2999
- return task_addr;
3060
+ return mem_read_results_vec;
3000
3061
}
3001
3062
3002
3063
namespace {
0 commit comments