merge(3p/absl): subtree merge of Abseil up to e19260f
... notably, this includes Abseil's own StatusOr type, which conflicted with our implementation (that was taken from TensorFlow). Change-Id: Ie7d6764b64055caaeb8dc7b6b9d066291e6b538f
This commit is contained in:
parent
cc27324d02
commit
082c006c04
854 changed files with 11260 additions and 5296 deletions
|
@ -68,6 +68,7 @@ static void Unpack(uint64_t x, int *pid, int *read_fd, int *write_fd) {
|
|||
// unimplemented.
|
||||
// This is a namespace-scoped variable for correct zero-initialization.
|
||||
static std::atomic<uint64_t> pid_and_fds; // initially 0, an invalid pid.
|
||||
|
||||
bool AddressIsReadable(const void *addr) {
|
||||
absl::base_internal::ErrnoSaver errno_saver;
|
||||
// We test whether a byte is readable by using write(). Normally, this would
|
||||
|
@ -86,7 +87,7 @@ bool AddressIsReadable(const void *addr) {
|
|||
int pid;
|
||||
int read_fd;
|
||||
int write_fd;
|
||||
uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
|
||||
uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire);
|
||||
Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
|
||||
while (current_pid != pid) {
|
||||
int p[2];
|
||||
|
@ -98,13 +99,13 @@ bool AddressIsReadable(const void *addr) {
|
|||
fcntl(p[1], F_SETFD, FD_CLOEXEC);
|
||||
uint64_t new_pid_and_fds = Pack(current_pid, p[0], p[1]);
|
||||
if (pid_and_fds.compare_exchange_strong(
|
||||
local_pid_and_fds, new_pid_and_fds, std::memory_order_relaxed,
|
||||
local_pid_and_fds, new_pid_and_fds, std::memory_order_release,
|
||||
std::memory_order_relaxed)) {
|
||||
local_pid_and_fds = new_pid_and_fds; // fds exposed to other threads
|
||||
} else { // fds not exposed to other threads; we can close them.
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
|
||||
local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire);
|
||||
}
|
||||
Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
|
||||
}
|
||||
|
@ -124,7 +125,7 @@ bool AddressIsReadable(const void *addr) {
|
|||
// If pid_and_fds contains the problematic file descriptors we just used,
|
||||
// this call will forget them, and the loop will try again.
|
||||
pid_and_fds.compare_exchange_strong(local_pid_and_fds, 0,
|
||||
std::memory_order_relaxed,
|
||||
std::memory_order_release,
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
} while (errno == EBADF);
|
||||
|
|
|
@ -126,6 +126,7 @@ static const AbbrevPair kBuiltinTypeList[] = {
|
|||
{"Dn", "std::nullptr_t", 0}, // i.e., decltype(nullptr)
|
||||
{"Df", "decimal32", 0}, // IEEE 754r decimal floating point (32 bits)
|
||||
{"Di", "char32_t", 0},
|
||||
{"Du", "char8_t", 0},
|
||||
{"Ds", "char16_t", 0},
|
||||
{"Dh", "float16", 0}, // IEEE 754r half-precision float (16 bits)
|
||||
{nullptr, nullptr, 0},
|
||||
|
@ -409,6 +410,7 @@ static bool IsFunctionCloneSuffix(const char *str) {
|
|||
|
||||
static bool EndsWith(State *state, const char chr) {
|
||||
return state->parse_state.out_cur_idx > 0 &&
|
||||
state->parse_state.out_cur_idx < state->out_end_idx &&
|
||||
chr == state->out[state->parse_state.out_cur_idx - 1];
|
||||
}
|
||||
|
||||
|
@ -421,8 +423,10 @@ static void MaybeAppendWithLength(State *state, const char *const str,
|
|||
if (str[0] == '<' && EndsWith(state, '<')) {
|
||||
Append(state, " ", 1);
|
||||
}
|
||||
// Remember the last identifier name for ctors/dtors.
|
||||
if (IsAlpha(str[0]) || str[0] == '_') {
|
||||
// Remember the last identifier name for ctors/dtors,
|
||||
// but only if we haven't yet overflown the buffer.
|
||||
if (state->parse_state.out_cur_idx < state->out_end_idx &&
|
||||
(IsAlpha(str[0]) || str[0] == '_')) {
|
||||
state->parse_state.prev_name_idx = state->parse_state.out_cur_idx;
|
||||
state->parse_state.prev_name_length = length;
|
||||
}
|
||||
|
@ -962,6 +966,7 @@ static bool ParseOperatorName(State *state, int *arity) {
|
|||
// ::= TT <type>
|
||||
// ::= TI <type>
|
||||
// ::= TS <type>
|
||||
// ::= TH <type> # thread-local
|
||||
// ::= Tc <call-offset> <call-offset> <(base) encoding>
|
||||
// ::= GV <(object) name>
|
||||
// ::= T <call-offset> <(base) encoding>
|
||||
|
@ -980,7 +985,7 @@ static bool ParseSpecialName(State *state) {
|
|||
ComplexityGuard guard(state);
|
||||
if (guard.IsTooComplex()) return false;
|
||||
ParseState copy = state->parse_state;
|
||||
if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "VTIS") &&
|
||||
if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "VTISH") &&
|
||||
ParseType(state)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1077,20 +1082,28 @@ static bool ParseVOffset(State *state) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// <ctor-dtor-name> ::= C1 | C2 | C3
|
||||
// <ctor-dtor-name> ::= C1 | C2 | C3 | CI1 <base-class-type> | CI2
|
||||
// <base-class-type>
|
||||
// ::= D0 | D1 | D2
|
||||
// # GCC extensions: "unified" constructor/destructor. See
|
||||
// # https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847
|
||||
// #
|
||||
// https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847
|
||||
// ::= C4 | D4
|
||||
static bool ParseCtorDtorName(State *state) {
|
||||
ComplexityGuard guard(state);
|
||||
if (guard.IsTooComplex()) return false;
|
||||
ParseState copy = state->parse_state;
|
||||
if (ParseOneCharToken(state, 'C') && ParseCharClass(state, "1234")) {
|
||||
const char *const prev_name = state->out + state->parse_state.prev_name_idx;
|
||||
MaybeAppendWithLength(state, prev_name,
|
||||
state->parse_state.prev_name_length);
|
||||
return true;
|
||||
if (ParseOneCharToken(state, 'C')) {
|
||||
if (ParseCharClass(state, "1234")) {
|
||||
const char *const prev_name =
|
||||
state->out + state->parse_state.prev_name_idx;
|
||||
MaybeAppendWithLength(state, prev_name,
|
||||
state->parse_state.prev_name_length);
|
||||
return true;
|
||||
} else if (ParseOneCharToken(state, 'I') && ParseCharClass(state, "12") &&
|
||||
ParseClassEnumType(state)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
state->parse_state = copy;
|
||||
|
||||
|
@ -1139,6 +1152,7 @@ static bool ParseDecltype(State *state) {
|
|||
// ::= <decltype>
|
||||
// ::= <substitution>
|
||||
// ::= Dp <type> # pack expansion of (C++0x)
|
||||
// ::= Dv <num-elems> _ # GNU vector extension
|
||||
//
|
||||
static bool ParseType(State *state) {
|
||||
ComplexityGuard guard(state);
|
||||
|
@ -1205,6 +1219,12 @@ static bool ParseType(State *state) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (ParseTwoCharToken(state, "Dv") && ParseNumber(state, nullptr) &&
|
||||
ParseOneCharToken(state, '_')) {
|
||||
return true;
|
||||
}
|
||||
state->parse_state = copy;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1253,13 +1273,42 @@ static bool ParseBuiltinType(State *state) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// <function-type> ::= F [Y] <bare-function-type> E
|
||||
// <exception-spec> ::= Do # non-throwing
|
||||
// exception-specification (e.g.,
|
||||
// noexcept, throw())
|
||||
// ::= DO <expression> E # computed (instantiation-dependent)
|
||||
// noexcept
|
||||
// ::= Dw <type>+ E # dynamic exception specification
|
||||
// with instantiation-dependent types
|
||||
static bool ParseExceptionSpec(State *state) {
|
||||
ComplexityGuard guard(state);
|
||||
if (guard.IsTooComplex()) return false;
|
||||
|
||||
if (ParseTwoCharToken(state, "Do")) return true;
|
||||
|
||||
ParseState copy = state->parse_state;
|
||||
if (ParseTwoCharToken(state, "DO") && ParseExpression(state) &&
|
||||
ParseOneCharToken(state, 'E')) {
|
||||
return true;
|
||||
}
|
||||
state->parse_state = copy;
|
||||
if (ParseTwoCharToken(state, "Dw") && OneOrMore(ParseType, state) &&
|
||||
ParseOneCharToken(state, 'E')) {
|
||||
return true;
|
||||
}
|
||||
state->parse_state = copy;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// <function-type> ::= [exception-spec] F [Y] <bare-function-type> [O] E
|
||||
static bool ParseFunctionType(State *state) {
|
||||
ComplexityGuard guard(state);
|
||||
if (guard.IsTooComplex()) return false;
|
||||
ParseState copy = state->parse_state;
|
||||
if (ParseOneCharToken(state, 'F') &&
|
||||
if (Optional(ParseExceptionSpec(state)) && ParseOneCharToken(state, 'F') &&
|
||||
Optional(ParseOneCharToken(state, 'Y')) && ParseBareFunctionType(state) &&
|
||||
Optional(ParseOneCharToken(state, 'O')) &&
|
||||
ParseOneCharToken(state, 'E')) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1887,7 +1936,8 @@ static bool Overflowed(const State *state) {
|
|||
bool Demangle(const char *mangled, char *out, int out_size) {
|
||||
State state;
|
||||
InitState(&state, mangled, out, out_size);
|
||||
return ParseTopLevelMangledName(&state) && !Overflowed(&state);
|
||||
return ParseTopLevelMangledName(&state) && !Overflowed(&state) &&
|
||||
state.parse_state.out_cur_idx > 0;
|
||||
}
|
||||
|
||||
} // namespace debugging_internal
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/debugging/internal/stack_consumption.h"
|
||||
#include "absl/memory/memory.h"
|
||||
|
@ -82,9 +83,10 @@ TEST(Demangle, Clones) {
|
|||
// Tests that verify that Demangle footprint is within some limit.
|
||||
// They are not to be run under sanitizers as the sanitizers increase
|
||||
// stack consumption by about 4x.
|
||||
#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \
|
||||
!defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \
|
||||
!defined(THREAD_SANITIZER)
|
||||
#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \
|
||||
!defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
|
||||
!defined(ABSL_HAVE_MEMORY_SANITIZER) && \
|
||||
!defined(ABSL_HAVE_THREAD_SANITIZER)
|
||||
|
||||
static const char *g_mangled;
|
||||
static char g_demangle_buffer[4096];
|
||||
|
|
|
@ -42,7 +42,8 @@ namespace {
|
|||
// 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__)
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
|
||||
defined(__aarch64__)
|
||||
constexpr bool kStackGrowsDown = true;
|
||||
#else
|
||||
#error Need to define kStackGrowsDown
|
||||
|
|
|
@ -24,8 +24,9 @@
|
|||
// Use this feature test macro to detect its availability.
|
||||
#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
|
||||
#error ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION cannot be set directly
|
||||
#elif !defined(__APPLE__) && !defined(_WIN32) && \
|
||||
(defined(__i386__) || defined(__x86_64__) || defined(__ppc__))
|
||||
#elif !defined(__APPLE__) && !defined(_WIN32) && \
|
||||
(defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
|
||||
defined(__aarch64__))
|
||||
#define ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 1
|
||||
|
||||
namespace absl {
|
||||
|
|
|
@ -37,8 +37,11 @@ static const unsigned char* GetKernelRtSigreturnAddress() {
|
|||
absl::debugging_internal::VDSOSupport vdso;
|
||||
if (vdso.IsPresent()) {
|
||||
absl::debugging_internal::VDSOSupport::SymbolInfo symbol_info;
|
||||
if (!vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.6.39", STT_FUNC,
|
||||
&symbol_info) ||
|
||||
auto lookup = [&](int type) {
|
||||
return vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.6.39", type,
|
||||
&symbol_info);
|
||||
};
|
||||
if ((!lookup(STT_FUNC) && !lookup(STT_NOTYPE)) ||
|
||||
symbol_info.address == nullptr) {
|
||||
// Unexpected: VDSO is present, yet the expected symbol is missing
|
||||
// or null.
|
||||
|
|
|
@ -44,48 +44,46 @@
|
|||
!(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_generic-inl.inc"
|
||||
#else
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_unimplemented-inl.inc"
|
||||
#endif
|
||||
|
||||
#elif defined(__linux__) && !defined(__ANDROID__)
|
||||
|
||||
#if !defined(NO_FRAME_POINTER)
|
||||
# if defined(__i386__) || defined(__x86_64__)
|
||||
#if defined(NO_FRAME_POINTER) && \
|
||||
(defined(__i386__) || defined(__x86_64__) || defined(__aarch64__))
|
||||
// Note: The libunwind-based implementation is not available to open-source
|
||||
// users.
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_x86-inl.inc"
|
||||
# elif defined(__ppc__) || defined(__PPC__)
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_powerpc-inl.inc"
|
||||
# elif defined(__aarch64__)
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_aarch64-inl.inc"
|
||||
#elif defined(__arm__) && defined(__GLIBC__)
|
||||
"absl/debugging/internal/stacktrace_libunwind-inl.inc"
|
||||
#define STACKTRACE_USES_LIBUNWIND 1
|
||||
#elif defined(NO_FRAME_POINTER) && defined(__has_include)
|
||||
#if __has_include(<execinfo.h>)
|
||||
// Note: When using glibc this may require -funwind-tables to function properly.
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_generic-inl.inc"
|
||||
# else
|
||||
#endif
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_unimplemented-inl.inc"
|
||||
# endif
|
||||
#else // defined(NO_FRAME_POINTER)
|
||||
# if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
|
||||
"absl/debugging/internal/stacktrace_x86-inl.inc"
|
||||
#elif defined(__ppc__) || defined(__PPC__)
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_generic-inl.inc"
|
||||
# elif defined(__ppc__) || defined(__PPC__)
|
||||
"absl/debugging/internal/stacktrace_powerpc-inl.inc"
|
||||
#elif defined(__aarch64__)
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_generic-inl.inc"
|
||||
# else
|
||||
"absl/debugging/internal/stacktrace_aarch64-inl.inc"
|
||||
#elif defined(__has_include)
|
||||
#if __has_include(<execinfo.h>)
|
||||
// Note: When using glibc this may require -funwind-tables to function properly.
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_unimplemented-inl.inc"
|
||||
# endif
|
||||
#endif // NO_FRAME_POINTER
|
||||
|
||||
#else
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_unimplemented-inl.inc"
|
||||
"absl/debugging/internal/stacktrace_generic-inl.inc"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Fallback to the empty implementation.
|
||||
#if !defined(ABSL_STACKTRACE_INL_HEADER)
|
||||
#define ABSL_STACKTRACE_INL_HEADER \
|
||||
"absl/debugging/internal/stacktrace_unimplemented-inl.inc"
|
||||
#endif
|
||||
|
||||
#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#ifndef ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
|
||||
#define ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
|
@ -116,20 +118,30 @@ bool RemoveAllSymbolDecorators(void);
|
|||
// filename != nullptr
|
||||
//
|
||||
// Returns true if the file was successfully registered.
|
||||
bool RegisterFileMappingHint(
|
||||
const void* start, const void* end, uint64_t offset, const char* filename);
|
||||
bool RegisterFileMappingHint(const void* start, const void* end,
|
||||
uint64_t offset, const char* filename);
|
||||
|
||||
// Looks up the file mapping registered by RegisterFileMappingHint for an
|
||||
// address range. If there is one, the file name is stored in *filename and
|
||||
// *start and *end are modified to reflect the registered mapping. Returns
|
||||
// whether any hint was found.
|
||||
bool GetFileMappingHint(const void** start,
|
||||
const void** end,
|
||||
uint64_t * offset,
|
||||
bool GetFileMappingHint(const void** start, const void** end, uint64_t* offset,
|
||||
const char** filename);
|
||||
|
||||
} // namespace debugging_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
bool
|
||||
AbslInternalGetFileMappingHint(const void** start, const void** end,
|
||||
uint64_t* offset, const char** filename);
|
||||
|
||||
#endif // ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
|
||||
|
|
|
@ -76,15 +76,6 @@ const void *VDSOSupport::Init() {
|
|||
}
|
||||
#endif // __GLIBC_PREREQ(2, 16)
|
||||
if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {
|
||||
// Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[]
|
||||
// on stack, and so glibc works as if VDSO was not present.
|
||||
// But going directly to kernel via /proc/self/auxv below bypasses
|
||||
// Valgrind zapping. So we check for Valgrind separately.
|
||||
if (RunningOnValgrind()) {
|
||||
vdso_base_.store(nullptr, std::memory_order_relaxed);
|
||||
getcpu_fn_.store(&GetCPUViaSyscall, std::memory_order_relaxed);
|
||||
return nullptr;
|
||||
}
|
||||
int fd = open("/proc/self/auxv", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
// Kernel too old to have a VDSO.
|
||||
|
@ -175,18 +166,6 @@ int GetCPU() {
|
|||
return ret_code == 0 ? cpu : ret_code;
|
||||
}
|
||||
|
||||
// We need to make sure VDSOSupport::Init() is called before
|
||||
// InitGoogle() does any setuid or chroot calls. If VDSOSupport
|
||||
// is used in any global constructor, this will happen, since
|
||||
// VDSOSupport's constructor calls Init. But if not, we need to
|
||||
// ensure it here, with a global constructor of our own. This
|
||||
// is an allowed exception to the normal rule against non-trivial
|
||||
// global constructors.
|
||||
static class VDSOInitHelper {
|
||||
public:
|
||||
VDSOInitHelper() { VDSOSupport::Init(); }
|
||||
} vdso_init_helper;
|
||||
|
||||
} // namespace debugging_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue