Commit 7fda0996 by Abseil Team Committed by Gennadiy Rozental

Changes imported from Abseil "staging" branch:

  - f0a03a750a36dfbd7ab06d2913430ed5f988fd68 Add absl::RegisterSymbolizer() to mutex_nonprod.cc for AP... by Derek Mauro <dmauro@google.com>
  - f34a2ee35b4f6b321c570c51b0c381647176df63 Add the async signal-safe Symbolizer to Abseil. by Derek Mauro <dmauro@google.com>
  - 6a29ec2d6dc080691f6d32e1982201d1d173bdb3 Document preferred placement of ABSL_CONST_INIT attribute... by Abseil Team <absl-team@google.com>
  - 6f04ed6aa9c19bd717f0e8f422a97f3e3368cf30 Internal change. by Abseil Team <absl-team@google.com>
  - 0af9a330aff8fc0b41dcb3fe519930c36b01a9ef Declare absl::raw_logging_internal::SafeWriteToStderr in ... by Abseil Team <absl-team@google.com>
  - 223ff26745d31dfb4b59c36f3dee5441506af3c2 Fix ABSL_ARRAYSIZE() to handle rvalues. by Xiaoyi Zhang <zhangxy@google.com>

GitOrigin-RevId: f0a03a750a36dfbd7ab06d2913430ed5f988fd68
Change-Id: I491f9cc81ca3ee078fb737cbf8fa9bf6a730eee1
parent 0d40cb77
...@@ -543,11 +543,18 @@ ...@@ -543,11 +543,18 @@
// not compile (on supported platforms) unless the variable has a constant // not compile (on supported platforms) unless the variable has a constant
// initializer. This is useful for variables with static and thread storage // initializer. This is useful for variables with static and thread storage
// duration, because it guarantees that they will not suffer from the so-called // duration, because it guarantees that they will not suffer from the so-called
// "static init order fiasco". // "static init order fiasco". Prefer to put this attribute on the most visible
// declaration of the variable, if there's more than one, because code that
// accesses the variable can then use the attribute for optimization.
// //
// Example: // Example:
// //
// ABSL_CONST_INIT static MyType my_var = MakeMyType(...); // class MyClass {
// public:
// ABSL_CONST_INIT static MyType my_var;
// };
//
// MyType MyClass::my_var = MakeMyType(...);
// //
// Note that this attribute is redundant if the variable is declared constexpr. // Note that this attribute is redundant if the variable is declared constexpr.
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) #if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
......
...@@ -104,12 +104,6 @@ inline static bool VADoRawLog(char** buf, int* size, ...@@ -104,12 +104,6 @@ inline static bool VADoRawLog(char** buf, int* size,
static constexpr int kLogBufSize = 3000; static constexpr int kLogBufSize = 3000;
namespace absl {
namespace raw_logging_internal {
void SafeWriteToStderr(const char *s, size_t len);
} // namespace raw_logging_internal
} // namespace absl
namespace { namespace {
// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths // CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
...@@ -188,12 +182,6 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line, ...@@ -188,12 +182,6 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
namespace absl { namespace absl {
namespace raw_logging_internal { namespace raw_logging_internal {
// Writes the provided buffer directly to stderr, in a safe, low-level manner.
//
// In POSIX this means calling write(), which is async-signal safe and does
// not malloc. If the platform supports the SYS_write syscall, we invoke that
// directly to side-step any libc interception.
void SafeWriteToStderr(const char *s, size_t len) { void SafeWriteToStderr(const char *s, size_t len) {
#if defined(ABSL_HAVE_SYSCALL_WRITE) #if defined(ABSL_HAVE_SYSCALL_WRITE)
syscall(SYS_write, STDERR_FILENO, s, len); syscall(SYS_write, STDERR_FILENO, s, len);
......
...@@ -74,6 +74,13 @@ namespace raw_logging_internal { ...@@ -74,6 +74,13 @@ namespace raw_logging_internal {
void RawLog(absl::LogSeverity severity, const char* file, int line, void RawLog(absl::LogSeverity severity, const char* file, int line,
const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5); const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);
// Writes the provided buffer directly to stderr, in a safe, low-level manner.
//
// In POSIX this means calling write(), which is async-signal safe and does
// not malloc. If the platform supports the SYS_write syscall, we invoke that
// directly to side-step any libc interception.
void SafeWriteToStderr(const char *s, size_t len);
// compile-time function to get the "base" filename, that is, the part of // compile-time function to get the "base" filename, that is, the part of
// a filename after the last "/" or "\" path separator. The search starts at // a filename after the last "/" or "\" path separator. The search starts at
// the end of the std::string; the second parameter is the length of the std::string. // the end of the std::string; the second parameter is the length of the std::string.
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
namespace absl { namespace absl {
namespace macros_internal { namespace macros_internal {
template <typename T, size_t N> template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N]; auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
} // namespace macros_internal } // namespace macros_internal
} // namespace absl } // namespace absl
#define ABSL_ARRAYSIZE(array) \ #define ABSL_ARRAYSIZE(array) \
......
...@@ -41,6 +41,42 @@ cc_library( ...@@ -41,6 +41,42 @@ cc_library(
) )
cc_library( cc_library(
name = "symbolize",
srcs = [
"symbolize.cc",
"symbolize_elf.inc",
"symbolize_unimplemented.inc",
],
hdrs = [
"internal/symbolize.h",
"symbolize.h",
],
copts = ABSL_DEFAULT_COPTS,
deps = [
":debugging_internal",
":demangle_internal",
"//absl/base",
"//absl/base:core_headers",
"//absl/base:malloc_internal",
],
)
cc_test(
name = "symbolize_test",
srcs = ["symbolize_test.cc"],
copts = ABSL_TEST_COPTS,
deps = [
":stack_consumption",
":symbolize",
"//absl/base",
"//absl/base:core_headers",
"//absl/base:malloc_extension",
"//absl/memory",
"@com_google_googletest//:gtest",
],
)
cc_library(
name = "debugging_internal", name = "debugging_internal",
srcs = [ srcs = [
"internal/address_is_readable.cc", "internal/address_is_readable.cc",
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
list(APPEND DEBUGGING_PUBLIC_HEADERS list(APPEND DEBUGGING_PUBLIC_HEADERS
"leak_check.h" "leak_check.h"
"stacktrace.h" "stacktrace.h"
"symbolize.h"
) )
...@@ -25,6 +26,7 @@ list(APPEND DEBUGGING_INTERNAL_HEADERS ...@@ -25,6 +26,7 @@ list(APPEND DEBUGGING_INTERNAL_HEADERS
"internal/demangle.h" "internal/demangle.h"
"internal/elf_mem_image.h" "internal/elf_mem_image.h"
"internal/stacktrace_config.h" "internal/stacktrace_config.h"
"internal/symbolize.h"
"internal/vdso_support.h" "internal/vdso_support.h"
) )
...@@ -32,13 +34,21 @@ list(APPEND DEBUGGING_INTERNAL_HEADERS ...@@ -32,13 +34,21 @@ list(APPEND DEBUGGING_INTERNAL_HEADERS
list(APPEND STACKTRACE_SRC list(APPEND STACKTRACE_SRC
"stacktrace.cc" "stacktrace.cc"
"internal/address_is_readable.cc" "internal/address_is_readable.cc"
"internal/demangle.cc"
"internal/elf_mem_image.cc" "internal/elf_mem_image.cc"
"internal/vdso_support.cc" "internal/vdso_support.cc"
${DEBUGGING_PUBLIC_HEADERS} ${DEBUGGING_PUBLIC_HEADERS}
${DEBUGGING_INTERNAL_HEADERS} ${DEBUGGING_INTERNAL_HEADERS}
) )
list(APPEND SYMBOLIZE_SRC
"symbolize.cc"
"symbolize_elf.inc"
"symbolize_unimplemented.inc"
"internal/demangle.cc"
${DEBUGGING_PUBLIC_HEADERS}
${DEBUGGING_INTERNAL_HEADERS}
)
absl_library( absl_library(
TARGET TARGET
absl_stacktrace absl_stacktrace
...@@ -48,6 +58,14 @@ absl_library( ...@@ -48,6 +58,14 @@ absl_library(
stacktrace stacktrace
) )
absl_library(
TARGET
absl_symbolize
SOURCES
${SYMBOLIZE_SRC}
EXPORT_NAME
symbolize
)
list(APPEND LEAK_CHECK_SRC list(APPEND LEAK_CHECK_SRC
"leak_check.cc" "leak_check.cc"
...@@ -112,9 +130,19 @@ absl_test( ...@@ -112,9 +130,19 @@ absl_test(
SOURCES SOURCES
${DEMANGLE_TEST_SRC} ${DEMANGLE_TEST_SRC}
PUBLIC_LIBRARIES PUBLIC_LIBRARIES
absl_stacktrace absl_stack_consumption absl_symbolize absl_stack_consumption
) )
list(APPEND SYMBOLIZE_TEST_SRC "symbolize_test.cc")
absl_test(
TARGET
symbolize_test
SOURCES
${SYMBOLIZE_TEST_SRC}
PUBLIC_LIBRARIES
absl_symbolize absl_stack_consumption
)
# test leak_check_test # test leak_check_test
list(APPEND LEAK_CHECK_TEST_SRC "leak_check_test.cc") list(APPEND LEAK_CHECK_TEST_SRC "leak_check_test.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
//
// http://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.
// This file contains internal parts of the Abseil symbolizer.
// Do not depend on the anything in this file, it may change at anytime.
#ifndef ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
#define ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
#include <cstddef>
#include <cstdint>
#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
#error ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE cannot be directly set
#elif defined(__ELF__) && defined(__GLIBC__) && !defined(__native_client__) && \
!defined(__asmjs__)
#define ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE 1
#include <elf.h>
#include <link.h> // For ElfW() macro.
#include <functional>
#include <string>
namespace absl {
namespace debugging_internal {
// Iterates over all sections, invoking callback on each with the section name
// and the section header.
//
// Returns true on success; otherwise returns false in case of errors.
//
// This is not async-signal-safe.
bool ForEachSection(
int fd, const std::function<bool(const std::string& name, const ElfW(Shdr) &)>&
callback);
// Gets the section header for the given name, if it exists. Returns true on
// success. Otherwise, returns false.
bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
ElfW(Shdr) *out);
} // namespace debugging_internal
} // namespace absl
#endif // ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
namespace absl {
namespace debugging_internal {
struct SymbolDecoratorArgs {
// The program counter we are getting symbolic name for.
const void *pc;
// 0 for main executable, load address for shared libraries.
ptrdiff_t relocation;
// Read-only file descriptor for ELF image covering "pc",
// or -1 if no such ELF image exists in /proc/self/maps.
int fd;
// Output buffer, size.
// Note: the buffer may not be empty -- default symbolizer may have already
// produced some output, and earlier decorators may have adorned it in
// some way. You are free to replace or augment the contents (within the
// symbol_buf_size limit).
char *const symbol_buf;
size_t symbol_buf_size;
// Temporary scratch space, size.
// Use that space in preference to allocating your own stack buffer to
// conserve stack.
char *const tmp_buf;
size_t tmp_buf_size;
// User-provided argument
void* arg;
};
using SymbolDecorator = void (*)(const SymbolDecoratorArgs *);
// Installs a function-pointer as a decorator. Returns a value less than zero
// if the system cannot install the decorator. Otherwise, returns a unique
// identifier corresponding to the decorator. This identifier can be used to
// uninstall the decorator - See RemoveSymbolDecorator() below.
int InstallSymbolDecorator(SymbolDecorator decorator, void* arg);
// Removes a previously installed function-pointer decorator. Parameter "ticket"
// is the return-value from calling InstallSymbolDecorator().
bool RemoveSymbolDecorator(int ticket);
// Remove all installed decorators. Returns true if successful, false if
// symbolization is currently in progress.
bool RemoveAllSymbolDecorators(void);
// Registers an address range to a file mapping.
//
// Preconditions:
// start <= end
// filename != nullptr
//
// Returns true if the file was successfully registered.
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,
const char** filename);
} // namespace debugging_internal
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
// 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
//
// http://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/symbolize.h"
#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
#include "absl/debugging/symbolize_elf.inc"
#else
#include "absl/debugging/symbolize_unimplemented.inc"
#endif
// 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
//
// http://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.
#ifndef ABSL_DEBUGGING_SYMBOLIZE_H_
#define ABSL_DEBUGGING_SYMBOLIZE_H_
#include "absl/debugging/internal/symbolize.h"
namespace absl {
// Initializes this module. Symbolize() may fail prior calling this function.
// `argv0` is the path to this program, which is usually obtained in main()
// though argv[0].
void InitializeSymbolizer(const char* argv0);
// Symbolizes a program counter. On success, returns true and write the
// symbol name to "out". The symbol name is demangled if possible
// (supports symbols generated by GCC 3.x or newer), may be truncated, and
// will be '\0' terminated. Otherwise, returns false.
bool Symbolize(const void *pc, char *out, int out_size);
} // namespace absl
#endif // ABSL_DEBUGGING_SYMBOLIZE_H_
// 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
//
// http://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 <cstdint>
#include "absl/base/internal/raw_logging.h"
namespace absl {
namespace debugging_internal {
int InstallSymbolDecorator(SymbolDecorator, void*) { return -1; }
bool RemoveSymbolDecorator(int) { return false; }
bool RemoveAllSymbolDecorators(void) { return false; }
bool RegisterFileMappingHint(const void *, const void *, uint64_t, const char *) {
return false;
}
} // namespace debugging_internal
void InitializeSymbolizer(const char*) {}
bool Symbolize(const void *, char *, int) { return false; }
} // namespace absl
...@@ -313,4 +313,6 @@ bool Condition::Eval() const { ...@@ -313,4 +313,6 @@ bool Condition::Eval() const {
return (this->eval_ == nullptr) || (*this->eval_)(this); return (this->eval_ == nullptr) || (*this->eval_)(this);
} }
void RegisterSymbolizer(bool (*)(const void*, char*, int)) {}
} // namespace absl } // namespace absl
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment