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:
Vincent Ambo 2020-11-21 14:43:54 +01:00
parent cc27324d02
commit 082c006c04
854 changed files with 11260 additions and 5296 deletions

View file

@ -26,7 +26,7 @@ package(
default_visibility = ["//visibility:public"],
)
licenses(["notice"]) # Apache 2.0
licenses(["notice"])
cc_library(
name = "stacktrace",
@ -97,6 +97,7 @@ cc_test(
":stack_consumption",
":symbolize",
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
"//absl/memory",
@ -148,6 +149,7 @@ cc_test(
copts = ABSL_TEST_COPTS,
linkopts = select({
"//absl:windows": [],
"//absl:wasm": [],
"//conditions:default": ["-pthread"],
}) + ABSL_DEFAULT_LINKOPTS,
deps = [
@ -203,6 +205,7 @@ cc_test(
deps = [
":demangle_internal",
":stack_consumption",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
"//absl/memory",
@ -236,7 +239,7 @@ cc_library(
# These targets exists for use in tests only, explicitly configuring the
# LEAK_SANITIZER macro. It must be linked with -fsanitize=leak for lsan.
ABSL_LSAN_LINKOPTS = select({
"//absl:llvm_compiler": ["-fsanitize=leak"],
"//absl:clang_compiler": ["-fsanitize=leak"],
"//conditions:default": [],
})
@ -246,7 +249,7 @@ cc_library(
srcs = ["leak_check.cc"],
hdrs = ["leak_check.h"],
copts = select({
"//absl:llvm_compiler": ["-DLEAK_SANITIZER"],
"//absl:clang_compiler": ["-DLEAK_SANITIZER"],
"//conditions:default": [],
}),
linkopts = ABSL_DEFAULT_LINKOPTS,
@ -273,7 +276,7 @@ cc_test(
name = "leak_check_test",
srcs = ["leak_check_test.cc"],
copts = select({
"//absl:llvm_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
"//absl:clang_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
"//conditions:default": [],
}),
linkopts = ABSL_LSAN_LINKOPTS + ABSL_DEFAULT_LINKOPTS,

View file

@ -82,6 +82,7 @@ absl_cc_test(
absl::stack_consumption
absl::symbolize
absl::base
absl::config
absl::core_headers
absl::memory
absl::raw_logging_internal
@ -189,6 +190,7 @@ absl_cc_test(
DEPS
absl::demangle_internal
absl::stack_consumption
absl::config
absl::core_headers
absl::memory
absl::raw_logging_internal

View file

@ -136,8 +136,8 @@ static bool SetupAlternateStackOnce() {
const size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
#endif
size_t stack_size = (std::max(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
defined(THREAD_SANITIZER)
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
// Account for sanitizer instrumentation requiring additional stack space.
stack_size *= 5;
#endif

View file

@ -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);

View file

@ -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

View file

@ -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];

View file

@ -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

View file

@ -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 {

View file

@ -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.

View file

@ -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_

View file

@ -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_

View file

@ -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

View file

@ -14,9 +14,18 @@
#include "absl/debugging/symbolize.h"
#ifdef _WIN32
#include <winapifamily.h>
#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \
WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
// UWP doesn't have access to win32 APIs.
#define ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32
#endif
#endif
#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE)
#include "absl/debugging/symbolize_elf.inc"
#elif defined(_WIN32)
#elif defined(ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32)
// The Windows Symbolizer only works if PDB files containing the debug info
// are available to the program at runtime.
#include "absl/debugging/symbolize_win32.inc"

View file

@ -77,8 +77,8 @@ bool Symbolize(const void* pc, char* out, int out_size) {
char tmp_buf[1024];
if (debugging_internal::Demangle(symbol.c_str(), tmp_buf, sizeof(tmp_buf))) {
int len = strlen(tmp_buf);
if (len + 1 <= out_size) { // +1 for '\0'
size_t len = strlen(tmp_buf);
if (len + 1 <= static_cast<size_t>(out_size)) { // +1 for '\0'
assert(len < sizeof(tmp_buf));
memmove(out, tmp_buf, len + 1);
}

View file

@ -57,6 +57,7 @@
#include <unistd.h>
#include <algorithm>
#include <array>
#include <atomic>
#include <cerrno>
#include <cinttypes>
@ -83,6 +84,12 @@ ABSL_NAMESPACE_BEGIN
static char *argv0_value = nullptr;
void InitializeSymbolizer(const char *argv0) {
#ifdef ABSL_HAVE_VDSO_SUPPORT
// We need to make sure VDSOSupport::Init() is called before any setuid or
// chroot calls, so InitializeSymbolizer() should be called very early in the
// life of a program.
absl::debugging_internal::VDSOSupport::Init();
#endif
if (argv0_value != nullptr) {
free(argv0_value);
argv0_value = nullptr;
@ -178,6 +185,7 @@ struct ObjFile {
fd(-1),
elf_type(-1) {
SafeMemZero(&elf_header, sizeof(elf_header));
SafeMemZero(&phdr[0], sizeof(phdr));
}
char *filename;
@ -190,6 +198,10 @@ struct ObjFile {
int fd;
int elf_type;
ElfW(Ehdr) elf_header;
// PT_LOAD program header describing executable code.
// Normally we expect just one, but SWIFT binaries have two.
std::array<ElfW(Phdr), 2> phdr;
};
// Build 4-way associative cache for symbols. Within each cache line, symbols
@ -1266,6 +1278,36 @@ static bool MaybeInitializeObjFile(ObjFile *obj) {
ABSL_RAW_LOG(WARNING, "%s: failed to read elf header", obj->filename);
return false;
}
const int phnum = obj->elf_header.e_phnum;
const int phentsize = obj->elf_header.e_phentsize;
size_t phoff = obj->elf_header.e_phoff;
size_t num_executable_load_segments = 0;
for (int j = 0; j < phnum; j++) {
ElfW(Phdr) phdr;
if (!ReadFromOffsetExact(obj->fd, &phdr, sizeof(phdr), phoff)) {
ABSL_RAW_LOG(WARNING, "%s: failed to read program header %d",
obj->filename, j);
return false;
}
phoff += phentsize;
constexpr int rx = PF_X | PF_R;
if (phdr.p_type != PT_LOAD || (phdr.p_flags & rx) != rx) {
// Not a LOAD segment, or not executable code.
continue;
}
if (num_executable_load_segments < obj->phdr.size()) {
memcpy(&obj->phdr[num_executable_load_segments++], &phdr, sizeof(phdr));
} else {
ABSL_RAW_LOG(WARNING, "%s: too many executable LOAD segments",
obj->filename);
break;
}
}
if (num_executable_load_segments == 0) {
// This object has no "r-x" LOAD segments. That's unexpected.
ABSL_RAW_LOG(WARNING, "%s: no executable LOAD segments", obj->filename);
return false;
}
}
return true;
}
@ -1289,23 +1331,52 @@ const char *Symbolizer::GetSymbol(const void *const pc) {
int fd = -1;
if (obj != nullptr) {
if (MaybeInitializeObjFile(obj)) {
if (obj->elf_type == ET_DYN &&
reinterpret_cast<uint64_t>(obj->start_addr) >= obj->offset) {
const size_t start_addr = reinterpret_cast<size_t>(obj->start_addr);
if (obj->elf_type == ET_DYN && start_addr >= obj->offset) {
// This object was relocated.
//
// For obj->offset > 0, adjust the relocation since a mapping at offset
// X in the file will have a start address of [true relocation]+X.
relocation = reinterpret_cast<ptrdiff_t>(obj->start_addr) - obj->offset;
relocation = start_addr - obj->offset;
// Note: some binaries have multiple "rx" LOAD segments. We must
// find the right one.
ElfW(Phdr) *phdr = nullptr;
for (size_t j = 0; j < obj->phdr.size(); j++) {
ElfW(Phdr) &p = obj->phdr[j];
if (p.p_type != PT_LOAD) {
// We only expect PT_LOADs. This must be PT_NULL that we didn't
// write over (i.e. we exhausted all interesting PT_LOADs).
ABSL_RAW_CHECK(p.p_type == PT_NULL, "unexpected p_type");
break;
}
if (pc < reinterpret_cast<void *>(start_addr + p.p_memsz)) {
phdr = &p;
break;
}
}
if (phdr == nullptr) {
// That's unexpected. Hope for the best.
ABSL_RAW_LOG(
WARNING,
"%s: unable to find LOAD segment for pc: %p, start_addr: %zx",
obj->filename, pc, start_addr);
} else {
// Adjust relocation in case phdr.p_vaddr != 0.
// This happens for binaries linked with `lld --rosegment`, and for
// binaries linked with BFD `ld -z separate-code`.
relocation -= phdr->p_vaddr - phdr->p_offset;
}
}
fd = obj->fd;
}
if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,
sizeof(symbol_buf_), tmp_buf_,
sizeof(tmp_buf_)) == SYMBOL_FOUND) {
// Only try to demangle the symbol name if it fit into symbol_buf_.
DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,
sizeof(tmp_buf_));
if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,
sizeof(symbol_buf_), tmp_buf_,
sizeof(tmp_buf_)) == SYMBOL_FOUND) {
// Only try to demangle the symbol name if it fit into symbol_buf_.
DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,
sizeof(tmp_buf_));
}
}
} else {
#if ABSL_HAVE_VDSO_SUPPORT
@ -1376,7 +1447,7 @@ int InstallSymbolDecorator(SymbolDecorator decorator, void *arg) {
if (!g_decorators_mu.TryLock()) {
// Someone else is using decorators. Get out.
return false;
return -2;
}
int ret = ticket;
if (g_num_decorators >= kMaxDecorators) {
@ -1455,7 +1526,7 @@ bool GetFileMappingHint(const void **start, const void **end, uint64_t *offset,
bool Symbolize(const void *pc, char *out, int out_size) {
// Symbolization is very slow under tsan.
ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
SAFE_ASSERT(out_size >= 0);
debugging_internal::Symbolizer *s = debugging_internal::AllocateSymbolizer();
const char *name = s->GetSymbol(pc);
@ -1474,9 +1545,16 @@ bool Symbolize(const void *pc, char *out, int out_size) {
}
}
debugging_internal::FreeSymbolizer(s);
ANNOTATE_IGNORE_READS_AND_WRITES_END();
ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
return ok;
}
ABSL_NAMESPACE_END
} // namespace absl
extern "C" bool AbslInternalGetFileMappingHint(const void **start,
const void **end, uint64_t *offset,
const char **filename) {
return absl::debugging_internal::GetFileMappingHint(start, end, offset,
filename);
}

View file

@ -27,6 +27,7 @@
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/base/casts.h"
#include "absl/base/config.h"
#include "absl/base/internal/per_thread_tls.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/optimization.h"
@ -220,8 +221,8 @@ static const char *SymbolizeStackConsumption(void *pc, int *stack_consumed) {
static int GetStackConsumptionUpperLimit() {
// Symbolize stack consumption should be within 2kB.
int stack_consumption_upper_limit = 2048;
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
defined(THREAD_SANITIZER)
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
// Account for sanitizer instrumentation requiring additional stack space.
stack_consumption_upper_limit *= 5;
#endif