16 #include "absl/debugging/internal/stack_consumption.h"
18 #ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
26 #include "absl/base/attributes.h"
27 #include "absl/base/internal/raw_logging.h"
31 namespace debugging_internal {
45 #if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
46 defined(__aarch64__) || defined(__riscv)
47 constexpr
bool kStackGrowsDown =
true;
49 #error Need to define kStackGrowsDown
66 void EmptySignalHandler(
int) {}
70 constexpr
int kAlternateStackSize = 64 << 10;
72 constexpr
int kSafetyMargin = 32;
73 constexpr
char kAlternateStackFillValue = 0x55;
81 int GetStackConsumption(
const void*
const altstack) {
84 if (kStackGrowsDown) {
85 begin =
reinterpret_cast<const char*
>(altstack);
88 begin =
reinterpret_cast<const char*
>(altstack) + kAlternateStackSize - 1;
92 for (
int usage_count = kAlternateStackSize; usage_count > 0; --usage_count) {
93 if (*
begin != kAlternateStackFillValue) {
95 "Buffer has overflowed or is about to overflow");
107 int GetSignalHandlerStackConsumption(
void (*
signal_handler)(
int)) {
113 void* altstack = mmap(
nullptr, kAlternateStackSize, PROT_READ | PROT_WRITE,
114 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
119 memset(&sigstk, 0,
sizeof(sigstk));
120 sigstk.ss_sp = altstack;
121 sigstk.ss_size = kAlternateStackSize;
124 memset(&old_sigstk, 0,
sizeof(old_sigstk));
126 "sigaltstack() failed");
130 memset(&sa, 0,
sizeof(sa));
131 struct sigaction old_sa1, old_sa2;
132 sigemptyset(&sa.sa_mask);
133 sa.sa_flags = SA_ONSTACK;
136 sa.sa_handler = EmptySignalHandler;
137 ABSL_RAW_CHECK(sigaction(SIGUSR1, &sa, &old_sa1) == 0,
"sigaction() failed");
141 ABSL_RAW_CHECK(sigaction(SIGUSR2, &sa, &old_sa2) == 0,
"sigaction() failed");
149 memset(altstack, kAlternateStackFillValue, kAlternateStackSize);
151 int base_stack_consumption = GetStackConsumption(altstack);
155 int signal_handler_stack_consumption = GetStackConsumption(altstack);
158 if (old_sigstk.ss_sp ==
nullptr && old_sigstk.ss_size == 0 &&
159 (old_sigstk.ss_flags & SS_DISABLE)) {
165 old_sigstk.ss_size = MINSIGSTKSZ;
168 "sigaltstack() failed");
170 "sigaction() failed");
172 "sigaction() failed");
174 ABSL_RAW_CHECK(munmap(altstack, kAlternateStackSize) == 0,
"munmap() failed");
175 if (signal_handler_stack_consumption != -1 && base_stack_consumption != -1) {
176 return signal_handler_stack_consumption - base_stack_consumption;
185 #endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION