about summary refs log tree commit diff
path: root/absl/debugging
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@google.com>2020-06-17T13·53+0100
committerVincent Ambo <tazjin@google.com>2020-06-17T13·53+0100
commit8f2828c4b4ce502d242eca80a80269448857f4a6 (patch)
treecc3fad62dff6f279ce77f17047c4eef5ebbaf251 /absl/debugging
parent768eb2ca2857342673fcd462792ce04b8bac3fa3 (diff)
Squashed 'third_party/abseil_cpp/' changes from 768eb2ca2..ccdbb5941
ccdbb5941 Export of internal Abseil changes
01f5f81f9 Export of internal Abseil changes
2c92bdc7c Export of internal Abseil changes
e7ebf9803 Export of internal Abseil changes
2eba343b5 Export of internal Abseil changes
a8b03d90e Export of internal Abseil changes
1d31b5c36 Export of internal Abseil changes
da3a87690 Export of internal Abseil changes
8faf20461 Exclude empty directories (#697)
2069dc796 Export of internal Abseil changes
4832bf6bf Added a BUILD file in root to expose license. (#695)
af8f994af Export of internal Abseil changes
33caf1097 Export of internal Abseil changes
cf1a02e2d Export of internal Abseil changes

git-subtree-dir: third_party/abseil_cpp
git-subtree-split: ccdbb5941f992fabda7eae3ce72f55efc17c826a
Diffstat (limited to 'absl/debugging')
-rw-r--r--absl/debugging/BUILD.bazel3
-rw-r--r--absl/debugging/CMakeLists.txt3
-rw-r--r--absl/debugging/internal/examine_stack.cc30
-rw-r--r--absl/debugging/internal/stacktrace_config.h23
-rw-r--r--absl/debugging/internal/symbolize.h9
-rw-r--r--absl/debugging/symbolize.cc2
-rw-r--r--absl/debugging/symbolize_darwin.inc101
-rw-r--r--absl/debugging/symbolize_elf.inc8
-rw-r--r--absl/debugging/symbolize_test.cc13
9 files changed, 182 insertions, 10 deletions
diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel
index 8f521bec4692..d336246777fa 100644
--- a/absl/debugging/BUILD.bazel
+++ b/absl/debugging/BUILD.bazel
@@ -55,6 +55,7 @@ cc_library(
     name = "symbolize",
     srcs = [
         "symbolize.cc",
+        "symbolize_darwin.inc",
         "symbolize_elf.inc",
         "symbolize_unimplemented.inc",
         "symbolize_win32.inc",
@@ -77,6 +78,7 @@ cc_library(
         "//absl/base:dynamic_annotations",
         "//absl/base:malloc_internal",
         "//absl/base:raw_logging_internal",
+        "//absl/strings",
     ],
 )
 
@@ -98,6 +100,7 @@ cc_test(
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/memory",
+        "//absl/strings",
         "@com_google_googletest//:gtest",
     ],
 )
diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt
index 77336159393d..c597df86b0b5 100644
--- a/absl/debugging/CMakeLists.txt
+++ b/absl/debugging/CMakeLists.txt
@@ -46,6 +46,7 @@ absl_cc_library(
     "internal/symbolize.h"
   SRCS
     "symbolize.cc"
+    "symbolize_darwin.inc"
     "symbolize_elf.inc"
     "symbolize_unimplemented.inc"
     "symbolize_win32.inc"
@@ -63,6 +64,7 @@ absl_cc_library(
     absl::dynamic_annotations
     absl::malloc_internal
     absl::raw_logging_internal
+    absl::strings
   PUBLIC
 )
 
@@ -83,6 +85,7 @@ absl_cc_test(
     absl::core_headers
     absl::memory
     absl::raw_logging_internal
+    absl::strings
     gmock
 )
 
diff --git a/absl/debugging/internal/examine_stack.cc b/absl/debugging/internal/examine_stack.cc
index a3dd893a9dfe..6e5ff1fbd836 100644
--- a/absl/debugging/internal/examine_stack.cc
+++ b/absl/debugging/internal/examine_stack.cc
@@ -20,6 +20,10 @@
 #include <unistd.h>
 #endif
 
+#ifdef __APPLE__
+#include <sys/ucontext.h>
+#endif
+
 #include <csignal>
 #include <cstdio>
 
@@ -66,6 +70,32 @@ void* GetProgramCounter(void* vuc) {
 #error "Undefined Architecture."
 #endif
   }
+#elif defined(__APPLE__)
+  if (vuc != nullptr) {
+    ucontext_t* signal_ucontext = reinterpret_cast<ucontext_t*>(vuc);
+#if defined(__aarch64__)
+    return reinterpret_cast<void*>(
+        __darwin_arm_thread_state64_get_pc(signal_ucontext->uc_mcontext->__ss));
+#elif defined(__arm__)
+#if __DARWIN_UNIX03
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__pc);
+#else
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.pc);
+#endif
+#elif defined(__i386__)
+#if __DARWIN_UNIX03
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__eip);
+#else
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.eip);
+#endif
+#elif defined(__x86_64__)
+#if __DARWIN_UNIX03
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__rip);
+#else
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.rip);
+#endif
+#endif
+  }
 #elif defined(__akaros__)
   auto* ctx = reinterpret_cast<struct user_context*>(vuc);
   return reinterpret_cast<void*>(get_user_ctx_pc(ctx));
diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h
index d4e8480a8e28..d5cc17401396 100644
--- a/absl/debugging/internal/stacktrace_config.h
+++ b/absl/debugging/internal/stacktrace_config.h
@@ -28,6 +28,27 @@
 #define ABSL_STACKTRACE_INL_HEADER \
     "absl/debugging/internal/stacktrace_win32-inl.inc"
 
+#elif defined(__APPLE__)
+// Thread local support required for UnwindImpl.
+// Notes:
+// * Xcode's clang did not support `thread_local` until version 8, and
+//   even then not for all iOS < 9.0.
+// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator
+//   targeting iOS 9.x.
+// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time
+//   making __has_feature unreliable there.
+//
+// Otherwise, `__has_feature` is only supported by Clang so it has be inside
+// `defined(__APPLE__)` check.
+#if __has_feature(cxx_thread_local) && \
+    !(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)
@@ -40,7 +61,7 @@
 # elif defined(__aarch64__)
 #define ABSL_STACKTRACE_INL_HEADER \
     "absl/debugging/internal/stacktrace_aarch64-inl.inc"
-# elif defined(__arm__)
+#elif defined(__arm__) && defined(__GLIBC__)
 // Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_generic-inl.inc"
diff --git a/absl/debugging/internal/symbolize.h b/absl/debugging/internal/symbolize.h
index 5d0858b5c7e1..663d774d42fa 100644
--- a/absl/debugging/internal/symbolize.h
+++ b/absl/debugging/internal/symbolize.h
@@ -22,6 +22,7 @@
 #include <cstdint>
 
 #include "absl/base/config.h"
+#include "absl/strings/string_view.h"
 
 #ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
 #error ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE cannot be directly set
@@ -45,7 +46,7 @@ namespace debugging_internal {
 //
 // This is not async-signal-safe.
 bool ForEachSection(int fd,
-                    const std::function<bool(const std::string& name,
+                    const std::function<bool(absl::string_view name,
                                              const ElfW(Shdr) &)>& callback);
 
 // Gets the section header for the given name, if it exists. Returns true on
@@ -59,6 +60,12 @@ ABSL_NAMESPACE_END
 
 #endif  // ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
 
+#ifdef ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
+#error ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE cannot be directly set
+#elif defined(__APPLE__)
+#define ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE 1
+#endif
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
diff --git a/absl/debugging/symbolize.cc b/absl/debugging/symbolize.cc
index 54ed97002a1c..eec7a6e86118 100644
--- a/absl/debugging/symbolize.cc
+++ b/absl/debugging/symbolize.cc
@@ -20,6 +20,8 @@
 // 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"
+#elif defined(__APPLE__)
+#include "absl/debugging/symbolize_darwin.inc"
 #else
 #include "absl/debugging/symbolize_unimplemented.inc"
 #endif
diff --git a/absl/debugging/symbolize_darwin.inc b/absl/debugging/symbolize_darwin.inc
new file mode 100644
index 000000000000..cdadd40e97d1
--- /dev/null
+++ b/absl/debugging/symbolize_darwin.inc
@@ -0,0 +1,101 @@
+// Copyright 2020 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 <cxxabi.h>
+#include <execinfo.h>
+
+#include <algorithm>
+#include <cstring>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/debugging/internal/demangle.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+void InitializeSymbolizer(const char*) {}
+
+namespace debugging_internal {
+namespace {
+
+static std::string GetSymbolString(absl::string_view backtrace_line) {
+  // Example Backtrace lines:
+  // 0   libimaging_shared.dylib             0x018c152a
+  // _ZNSt11_Deque_baseIN3nik7mediadb4PageESaIS2_EE17_M_initialize_mapEm + 3478
+  //
+  // or
+  // 0   libimaging_shared.dylib             0x0000000001895c39
+  // _ZN3nik4util19register_shared_ptrINS_3gpu7TextureEEEvPKvS5_ + 39
+  //
+  // or
+  // 0   mysterious_app                      0x0124000120120009 main + 17
+  auto address_pos = backtrace_line.find(" 0x");
+  if (address_pos == absl::string_view::npos) return std::string();
+  absl::string_view symbol_view = backtrace_line.substr(address_pos + 1);
+
+  auto space_pos = symbol_view.find(" ");
+  if (space_pos == absl::string_view::npos) return std::string();
+  symbol_view = symbol_view.substr(space_pos + 1);  // to mangled symbol
+
+  auto plus_pos = symbol_view.find(" + ");
+  if (plus_pos == absl::string_view::npos) return std::string();
+  symbol_view = symbol_view.substr(0, plus_pos);  // strip remainng
+
+  return std::string(symbol_view);
+}
+
+}  // namespace
+}  // namespace debugging_internal
+
+bool Symbolize(const void* pc, char* out, int out_size) {
+  if (out_size <= 0 || pc == nullptr) {
+    out = nullptr;
+    return false;
+  }
+
+  // This allocates a char* array.
+  char** frame_strings = backtrace_symbols(const_cast<void**>(&pc), 1);
+
+  if (frame_strings == nullptr) return false;
+
+  std::string symbol = debugging_internal::GetSymbolString(frame_strings[0]);
+  free(frame_strings);
+
+  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'
+      assert(len < sizeof(tmp_buf));
+      memmove(out, tmp_buf, len + 1);
+    }
+  } else {
+    strncpy(out, symbol.c_str(), out_size);
+  }
+
+  if (out[out_size - 1] != '\0') {
+    // strncpy() does not '\0' terminate when it truncates.
+    static constexpr char kEllipsis[] = "...";
+    int ellipsis_size = std::min<int>(sizeof(kEllipsis) - 1, out_size - 1);
+    memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);
+    out[out_size - 1] = '\0';
+  }
+
+  return true;
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc
index ec86f9a93327..c05424e05b7d 100644
--- a/absl/debugging/symbolize_elf.inc
+++ b/absl/debugging/symbolize_elf.inc
@@ -74,6 +74,7 @@
 #include "absl/base/port.h"
 #include "absl/debugging/internal/demangle.h"
 #include "absl/debugging/internal/vdso_support.h"
+#include "absl/strings/string_view.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -498,7 +499,7 @@ static ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType(
 const int kMaxSectionNameLen = 64;
 
 bool ForEachSection(int fd,
-                    const std::function<bool(const std::string &name,
+                    const std::function<bool(absl::string_view name,
                                              const ElfW(Shdr) &)> &callback) {
   ElfW(Ehdr) elf_header;
   if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
@@ -520,7 +521,7 @@ bool ForEachSection(int fd,
       return false;
     }
     off_t name_offset = shstrtab.sh_offset + out.sh_name;
-    char header_name[kMaxSectionNameLen + 1];
+    char header_name[kMaxSectionNameLen];
     ssize_t n_read =
         ReadFromOffset(fd, &header_name, kMaxSectionNameLen, name_offset);
     if (n_read == -1) {
@@ -529,9 +530,8 @@ bool ForEachSection(int fd,
       // Long read?
       return false;
     }
-    header_name[n_read] = '\0';
 
-    std::string name(header_name);
+    absl::string_view name(header_name, strnlen(header_name, n_read));
     if (!callback(name, out)) {
       break;
     }
diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc
index a1d03aab531b..43f655493afb 100644
--- a/absl/debugging/symbolize_test.cc
+++ b/absl/debugging/symbolize_test.cc
@@ -32,6 +32,7 @@
 #include "absl/base/optimization.h"
 #include "absl/debugging/internal/stack_consumption.h"
 #include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
 
 using testing::Contains;
 
@@ -144,7 +145,8 @@ static const char *TrySymbolize(void *pc) {
   return TrySymbolizeWithLimit(pc, sizeof(try_symbolize_buffer));
 }
 
-#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
+#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
+    defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
 
 TEST(Symbolize, Cached) {
   // Compilers should give us pointers to them.
@@ -258,6 +260,7 @@ TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) {
 
 #endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
 
+#ifndef ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
 // Use a 64K page size for PPC.
 const size_t kPageSize = 64 << 10;
 // We place a read-only symbols into the .text section and verify that we can
@@ -399,8 +402,8 @@ TEST(Symbolize, ForEachSection) {
 
   std::vector<std::string> sections;
   ASSERT_TRUE(absl::debugging_internal::ForEachSection(
-      fd, [&sections](const std::string &name, const ElfW(Shdr) &) {
-        sections.push_back(name);
+      fd, [&sections](const absl::string_view name, const ElfW(Shdr) &) {
+        sections.emplace_back(name);
         return true;
       }));
 
@@ -413,6 +416,7 @@ TEST(Symbolize, ForEachSection) {
 
   close(fd);
 }
+#endif  // !ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
 
 // x86 specific tests.  Uses some inline assembler.
 extern "C" {
@@ -541,7 +545,8 @@ int main(int argc, char **argv) {
   absl::InitializeSymbolizer(argv[0]);
   testing::InitGoogleTest(&argc, argv);
 
-#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
+#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
+    defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
   TestWithPCInsideInlineFunction();
   TestWithPCInsideNonInlineFunction();
   TestWithReturnAddress();