4343#include < algorithm>
4444#include < atomic>
4545#include < iterator>
46+ #include < type_traits>
4647
4748#include " absl/base/attributes.h"
4849#include " absl/base/config.h"
@@ -74,36 +75,37 @@ namespace {
7475typedef int (*Unwinder)(void **, int *, int , int , const void *, int *);
7576std::atomic<Unwinder> custom;
7677
77- template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
78- ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind (void ** result, uintptr_t * frames,
79- int * sizes, size_t max_depth,
80- int skip_count, const void * uc,
81- int * min_dropped_frames,
82- bool unwind_with_fixup = true ) {
83- static constexpr size_t kMaxStackElements = 128 ;
78+ constexpr size_t kMinPageSize = 4096 ;
8479
85- static constexpr size_t kMinPageSize = 4096 ;
86- static_assert (
87- kMaxStackElements * (sizeof (*frames) + sizeof (*sizes)) < kMinPageSize / 2 ,
88- " buffer size should be a fraction of a page to avoid stack overflows" );
80+ struct FixupBuffer {
81+ static constexpr size_t kMaxStackElements = 128 ; // Can be reduced if needed
82+ uintptr_t frames[kMaxStackElements ];
83+ int sizes[kMaxStackElements ];
84+ };
85+ static_assert (std::is_trivially_default_constructible_v<FixupBuffer>);
86+ static_assert (sizeof (FixupBuffer) < kMinPageSize / 2 ,
87+ " buffer size should no larger than a small fraction of a page, "
88+ " to avoid stack overflows" );
8989
90+ template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
91+ ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind (
92+ void ** result, uintptr_t * frames, int * sizes, size_t max_depth,
93+ int skip_count, const void * uc, int * min_dropped_frames,
94+ FixupBuffer* fixup_buffer /* if NULL, fixups are skipped */ ) {
9095 // Allocate a buffer dynamically, using the signal-safe allocator.
9196 static constexpr auto allocate = [](size_t num_bytes) -> void * {
9297 base_internal::InitSigSafeArena ();
9398 return base_internal::LowLevelAlloc::AllocWithArena (
9499 num_bytes, base_internal::SigSafeArena ());
95100 };
96101
97- uintptr_t frames_stackbuf[kMaxStackElements ];
98- int sizes_stackbuf[kMaxStackElements ];
99-
100102 // We only need to free the buffers if we allocated them with the signal-safe
101103 // allocator.
102104 bool must_free_frames = false ;
103105 bool must_free_sizes = false ;
104106
105- unwind_with_fixup =
106- unwind_with_fixup && internal_stacktrace::ShouldFixUpStack ();
107+ bool unwind_with_fixup =
108+ fixup_buffer != nullptr && internal_stacktrace::ShouldFixUpStack ();
107109
108110#ifdef _WIN32
109111 if (unwind_with_fixup) {
@@ -122,17 +124,17 @@ ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind(void** result, uintptr_t* frames,
122124 // here.
123125
124126 if (frames == nullptr ) {
125- if (max_depth <= std::size (frames_stackbuf )) {
126- frames = frames_stackbuf ;
127+ if (max_depth <= std::size (fixup_buffer-> frames )) {
128+ frames = fixup_buffer-> frames ;
127129 } else {
128130 frames = static_cast <uintptr_t *>(allocate (max_depth * sizeof (*frames)));
129131 must_free_frames = true ;
130132 }
131133 }
132134
133135 if (sizes == nullptr ) {
134- if (max_depth <= std::size (sizes_stackbuf )) {
135- sizes = sizes_stackbuf ;
136+ if (max_depth <= std::size (fixup_buffer-> sizes )) {
137+ sizes = fixup_buffer-> sizes ;
136138 } else {
137139 sizes = static_cast <int *>(allocate (max_depth * sizeof (*sizes)));
138140 must_free_sizes = true ;
@@ -182,42 +184,46 @@ ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind(void** result, uintptr_t* frames,
182184ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
183185internal_stacktrace::GetStackFrames (void ** result, uintptr_t * frames,
184186 int * sizes, int max_depth, int skip_count) {
187+ FixupBuffer fixup_stack_buf;
185188 return Unwind<true , false >(result, frames, sizes,
186189 static_cast <size_t >(max_depth), skip_count,
187- nullptr , nullptr );
190+ nullptr , nullptr , &fixup_stack_buf );
188191}
189192
190193ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
191194internal_stacktrace::GetStackFramesWithContext (void ** result, uintptr_t * frames,
192195 int * sizes, int max_depth,
193196 int skip_count, const void * uc,
194197 int * min_dropped_frames) {
198+ FixupBuffer fixup_stack_buf;
195199 return Unwind<true , true >(result, frames, sizes,
196200 static_cast <size_t >(max_depth), skip_count, uc,
197- min_dropped_frames);
201+ min_dropped_frames, &fixup_stack_buf );
198202}
199203
200204ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
201205internal_stacktrace::GetStackTraceNoFixup (void ** result, int max_depth,
202206 int skip_count) {
203207 return Unwind<false , false >(result, nullptr , nullptr ,
204208 static_cast <size_t >(max_depth), skip_count,
205- nullptr , nullptr , /* unwind_with_fixup= */ false );
209+ nullptr , nullptr , nullptr );
206210}
207211
208212ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace (
209213 void ** result, int max_depth, int skip_count) {
214+ FixupBuffer fixup_stack_buf;
210215 return Unwind<false , false >(result, nullptr , nullptr ,
211216 static_cast <size_t >(max_depth), skip_count,
212- nullptr , nullptr );
217+ nullptr , nullptr , &fixup_stack_buf );
213218}
214219
215220ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
216221GetStackTraceWithContext (void ** result, int max_depth, int skip_count,
217222 const void * uc, int * min_dropped_frames) {
223+ FixupBuffer fixup_stack_buf;
218224 return Unwind<false , true >(result, nullptr , nullptr ,
219225 static_cast <size_t >(max_depth), skip_count, uc,
220- min_dropped_frames);
226+ min_dropped_frames, &fixup_stack_buf );
221227}
222228
223229void SetStackUnwinder (Unwinder w) {
0 commit comments