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