chromium/third_party/abseil-cpp/absl/debugging/internal/stack_consumption.cc

//
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "absl/debugging/internal/stack_consumption.h"

#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION

#include <signal.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

#include "absl/base/attributes.h"
#include "absl/base/internal/raw_logging.h"

#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
#define MAP_ANONYMOUS
#endif

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
namespace {

// This code requires that we know the direction in which the stack
// grows. It is commonly believed that this can be detected by putting
// a variable on the stack and then passing its address to a function
// that compares the address of this variable to the address of a
// variable on the function's own stack. However, this is unspecified
// behavior in C++: If two pointers p and q of the same type point to
// different objects that are not members of the same object or
// elements of the same array or to different functions, or if only
// one of them is null, the results of p<q, p>q, p<=q, and p>=q are
// unspecified. Therefore, instead we hardcode the direction of the
// stack on platforms we know about.
#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
    defined(__aarch64__) || defined(__riscv)
constexpr bool kStackGrowsDown =;
#else
#error Need to define kStackGrowsDown
#endif

// To measure the stack footprint of some code, we create a signal handler
// (for SIGUSR2 say) that exercises this code on an alternate stack. This
// alternate stack is initialized to some known pattern (0x55, 0x55, 0x55,
// ...). We then self-send this signal, and after the signal handler returns,
// look at the alternate stack buffer to see what portion has been touched.
//
// This trick gives us the the stack footprint of the signal handler.  But the
// signal handler, even before the code for it is exercised, consumes some
// stack already. We however only want the stack usage of the code inside the
// signal handler. To measure this accurately, we install two signal handlers:
// one that does nothing and just returns, and the user-provided signal
// handler. The difference between the stack consumption of these two signals
// handlers should give us the stack foorprint of interest.

void EmptySignalHandler(int) {}

// This is arbitrary value, and could be increase further, at the cost of
// memset()ting it all to known sentinel value.
constexpr int kAlternateStackSize =;  // 64KiB

constexpr int kSafetyMargin =;
constexpr char kAlternateStackFillValue =;

// These helper functions look at the alternate stack buffer, and figure
// out what portion of this buffer has been touched - this is the stack
// consumption of the signal handler running on this alternate stack.
// This function will return -1 if the alternate stack buffer has not been
// touched. It will abort the program if the buffer has overflowed or is about
// to overflow.
int GetStackConsumption(const void* const altstack) {}

}  // namespace

int GetSignalHandlerStackConsumption(void (*signal_handler)(int)) {}

}  // namespace debugging_internal
ABSL_NAMESPACE_END
}  // namespace absl

#else

// https://github.com/abseil/abseil-cpp/issues/1465
// CMake builds on Apple platforms error when libraries are empty.
// Our CMake configuration can avoid this error on header-only libraries,
// but since this library is conditionally empty, including a single
// variable is an easy workaround.
#ifdef __APPLE__
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
extern const char kAvoidEmptyStackConsumptionLibraryWarning;
const char kAvoidEmptyStackConsumptionLibraryWarning = 0;
}  // namespace debugging_internal
ABSL_NAMESPACE_END
}  // namespace absl
#endif  // __APPLE__

#endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION