@@ -46,6 +46,51 @@ XSAVE_CET_U_FORMAT* LocateXStateCetU(CONTEXT* context) {
4646 locate_xstate_feature (context, XSTATE_CET_U, &cet_u_size));
4747}
4848#endif // defined(ARCH_CPU_X86_64)
49+
50+ // Helper function to adjust stack capture range based on current stack pointer
51+ bool AdjustStackCaptureRange (ProcessReaderWin* process_reader,
52+ const ProcessReaderWin::Thread& thread,
53+ WinVMAddress* stack_capture_address,
54+ WinVMSize* stack_capture_size) {
55+ WinVMAddress sp = 0 ;
56+ WinVMAddress stack_base = thread.stack_region_address + thread.stack_region_size ;
57+
58+ // Get the stack pointer from the context
59+ #if defined(ARCH_CPU_X86)
60+ sp = thread.context .context <CONTEXT>()->Esp ;
61+ #elif defined(ARCH_CPU_X86_64)
62+ if (process_reader->Is64Bit ()) {
63+ sp = thread.context .context <CONTEXT>()->Rsp ;
64+ } else {
65+ sp = thread.context .context <WOW64_CONTEXT>()->Esp ;
66+ }
67+ #elif defined(ARCH_CPU_ARM64)
68+ sp = thread.context .context <CONTEXT>()->Sp ;
69+ #endif
70+
71+ // Verify SP is within the valid stack region
72+ if (sp >= thread.stack_region_address && sp < stack_base) {
73+ // Account for potential red zone
74+ // Windows x64 follows Microsoft x64 calling convention and has no red zone
75+ // ARM64 has a 16-byte red zone
76+ const WinVMSize red_zone_size =
77+ #if defined(ARCH_CPU_ARM64)
78+ 16 ;
79+ #else
80+ 0 ;
81+ #endif
82+
83+ // Adjust stack capture to start from SP (minus red zone) to stack base
84+ WinVMAddress adjusted_start = sp > red_zone_size ? sp - red_zone_size : sp;
85+ if (adjusted_start >= thread.stack_region_address && adjusted_start < stack_base) {
86+ *stack_capture_address = adjusted_start;
87+ *stack_capture_size = stack_base - adjusted_start;
88+ return true ;
89+ }
90+ }
91+ return false ;
92+ }
93+
4994} // namespace
5095
5196ThreadSnapshotWin::ThreadSnapshotWin ()
@@ -61,16 +106,26 @@ ThreadSnapshotWin::~ThreadSnapshotWin() {}
61106bool ThreadSnapshotWin::Initialize (
62107 ProcessReaderWin* process_reader,
63108 const ProcessReaderWin::Thread& process_reader_thread,
64- uint32_t * gather_indirectly_referenced_memory_bytes_remaining) {
109+ uint32_t * gather_indirectly_referenced_memory_bytes_remaining,
110+ bool limit_stack_capture_to_sp) {
65111 INITIALIZATION_STATE_SET_INITIALIZING (initialized_);
66112
67113 thread_ = process_reader_thread;
114+
115+ WinVMAddress stack_capture_address = thread_.stack_region_address ;
116+ WinVMSize stack_capture_size = thread_.stack_region_size ;
117+
118+ // If limit_stack_capture_to_sp is enabled, calculate stack range based on current SP
119+ if (limit_stack_capture_to_sp) {
120+ AdjustStackCaptureRange (
121+ process_reader, thread_, &stack_capture_address, &stack_capture_size);
122+ }
123+
68124 if (process_reader->GetProcessInfo ().LoggingRangeIsFullyReadable (
69- CheckedRange<WinVMAddress, WinVMSize>(thread_.stack_region_address ,
70- thread_.stack_region_size ))) {
71- stack_.Initialize (process_reader->Memory (),
72- thread_.stack_region_address ,
73- thread_.stack_region_size );
125+ CheckedRange<WinVMAddress, WinVMSize>(stack_capture_address,
126+ stack_capture_size))) {
127+ stack_.Initialize (
128+ process_reader->Memory (), stack_capture_address, stack_capture_size);
74129 } else {
75130 stack_.Initialize (process_reader->Memory (), 0 , 0 );
76131 }
0 commit comments