Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to abseil symbolization / stack tracing routines #5077

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,6 @@ list (APPEND P4C_LIB_DEPS ${P4C_ABSL_LIBRARIES})
p4c_add_library (rt clock_gettime HAVE_CLOCK_GETTIME)

# Check includes.
check_include_file(execinfo.h HAVE_EXECINFO_H)
check_include_file(ucontext.h HAVE_UCONTEXT_H)
check_include_file(backtrace-supported.h HAVE_LIBBACKTRACE)
check_include_file_cxx(mm_malloc.h HAVE_MM_MALLOC_H)
Expand Down
2 changes: 2 additions & 0 deletions backends/bmv2/simple_switch/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ limitations under the License.
#include "ir/json_generator.h"
#include "ir/json_loader.h"
#include "lib/algorithm.h"
#include "lib/crash.h"
#include "lib/error.h"
#include "lib/exceptions.h"
#include "lib/gc.h"
Expand All @@ -42,6 +43,7 @@ using namespace P4;

int main(int argc, char *const argv[]) {
setup_gc_logging();
setup_signals();

AutoCompileContext autoBMV2Context(new BMV2::SimpleSwitchContext);
auto &options = BMV2::SimpleSwitchContext::get().options();
Expand Down
3 changes: 0 additions & 3 deletions cmake/config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
/* Define to 1 if you have the boost graph headers */
#cmakedefine HAVE_LIBBOOST_GRAPH 1

/* Define to 1 if you have the execinfo.h header */
#cmakedefine HAVE_EXECINFO_H 1

/* Define to 1 if you have libbacktrace */
#cmakedefine HAVE_LIBBACKTRACE 1

Expand Down
2 changes: 2 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ add_library(p4ctoolkit STATIC ${LIBP4CTOOLKIT_SRCS})
# Disable libcall (realloc, malloc) optimizations which may cause infinite loops.
set_target_properties(p4ctoolkit PROPERTIES COMPILE_FLAGS -fno-builtin)
target_link_libraries(p4ctoolkit
PRIVATE absl::stacktrace
PRIVATE absl::symbolize
# These libraries are exposed by a header.
PUBLIC absl::bits
PUBLIC absl::strings
Expand Down
36 changes: 17 additions & 19 deletions lib/alloc_trace.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#include "alloc_trace.h"

#include "absl/debugging/symbolize.h"
#include "hex.h"
#include "log.h"
#include "n4.h"

#if HAVE_EXECINFO_H
#include <execinfo.h>
#endif
#if HAVE_LIBBACKTRACE
#include <backtrace.h>

Expand Down Expand Up @@ -45,15 +43,11 @@ int bt_print_callback(void *out_, uintptr_t pc, const char *file, int line, cons
file = "??";
}
out << Log::endl << file << ":" << line;

if (func) {
#if HAVE_CXXABI_H
int status;
if (char *fn = abi::__cxa_demangle(func, 0, 0, &status)) {
if (strlen(fn) < 100) out << " (" << fn << ")";
free(fn);
} else
#endif
out << " (" << func << ")";
char tmp[1024];
if (absl::Symbolize((void *)pc, tmp, sizeof(tmp))) func = tmp;
out << " (" << func << ")";
}
out << " [" << hex(pc) << "]";
return 0;
Expand All @@ -69,7 +63,7 @@ std::ostream &operator<<(std::ostream &out, const AllocTrace &at) {
#if HAVE_LIBGC
PauseTrace temp_pause;
#endif
typedef decltype(at.data)::value_type data_t;
using data_t = decltype(at.data)::value_type;
std::vector<std::pair<size_t, const data_t *>> sorted;
size_t total_total = 0;
for (auto &e : at.data) {
Expand All @@ -83,14 +77,15 @@ std::ostream &operator<<(std::ostream &out, const AllocTrace &at) {
if (!global_backtrace_state)
global_backtrace_state = backtrace_create_state(exename(), 1, bt_error, &out);
#endif

out << "Allocated a total of " << n4(total_total) << "B memory";
for (auto &s : sorted) {
if (s.first < 1000000) break; // ignore little stuff
if (s.first < 1000000) break; // ignore little stuff
size_t count = 0;
for (auto &al : s.second->second) count += al.second;
out << Log::endl << "allocated " << n4(s.first) << "B in " << count << " calls";
#if HAVE_EXECINFO_H
out << " from:" << Log::indent;

#if HAVE_LIBBACKTRACE
for (int i = 1; i < ALLOC_TRACE_DEPTH; ++i) {
/* due to calling the callback multiple times for inlined functions, we need to
Expand All @@ -100,15 +95,18 @@ std::ostream &operator<<(std::ostream &out, const AllocTrace &at) {
bt_print_callback, bt_error, &out);
}
#else
char **syms = backtrace_symbols(s.second->first.trace, ALLOC_TRACE_DEPTH);
char tmp[1024];
for (int i = ALLOC_TRACE_DEPTH - 1; i >= 1; --i) {
const char *alt = addr2line(s.second->first.trace[i], syms[i]);
out << Log::endl << (alt ? alt : syms[i]) << ' ' << s.second->first.trace[i];
void *pc = s.second->first.trace[i];
const char *symbol = "(unknown)";
if (absl::Symbolize(pc, tmp, sizeof(tmp))) {
symbol = tmp;
}
const char *alt = addr2line(pc, nullptr);
out << "\n " << (alt ? alt : "??: ") << symbol << " [" << hex(pc) << "]";
}
free(syms);
#endif
out << Log::unindent;
#endif
}
return out;
}
Expand Down
41 changes: 20 additions & 21 deletions lib/backtrace_exception.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ limitations under the License.
#include <backtrace.h>
#endif

#include <functional>
#include <regex>
#include <sstream>
#include <stdexcept>
#include <system_error>
#include <typeinfo>

#include "absl/debugging/symbolize.h"
#include "crash.h"
#include "exename.h"
#include "hex.h"
Expand All @@ -38,40 +38,39 @@ extern struct backtrace_state *global_backtrace_state;

int append_message(void *msg_, uintptr_t pc, const char *file, int line, const char *func) {
std::string &msg = *static_cast<std::string *>(msg_);
std::stringstream tmp;
tmp << "\n 0x" << hex(pc) << " " << (func ? func : "??");
if (file) tmp << "\n " << file << ":" << line;
msg += tmp.str();
std::stringstream str;
char *demangled = nullptr;
char tmp[1024];
if (func && absl::Symbolize((void *)pc, tmp, sizeof(tmp))) demangled = tmp;
str << "\n 0x" << hex(pc) << " " << (demangled ? demangled : func ? func : "??");
if (file) str << "\n " << file << ":" << line;
msg += str.str();
return 0;
}
#endif

void backtrace_fill_stacktrace(std::string &msg, void *const *backtrace, int size) {
// backtrace_symbols is only available with libexecinfo
#if HAVE_LIBBACKTRACE
if (!global_backtrace_state)
global_backtrace_state = backtrace_create_state(exename(), 1, nullptr, nullptr);
backtrace_full(global_backtrace_state, 1, append_message, nullptr, &msg);
(void)backtrace;
(void)size;
#elif HAVE_EXECINFO_H
char **strings = backtrace_symbols(backtrace, size);
#else
char tmp[1024];
std::stringstream str;
for (int i = 0; i < size; i++) {
if (strings) {
msg += "\n ";
msg += strings[i];
void *pc = backtrace[i];
const char *symbol = "??";
if (absl::Symbolize(pc, tmp, sizeof(tmp))) {
symbol = tmp;
}
if (const char *line = addr2line(backtrace[i], strings ? strings[i] : 0)) {
msg += "\n ";
msg += line;
str << "\n 0x" << hex(pc) << " " << symbol;
if (const char *line = addr2line(pc, nullptr)) {
str << "\n " << line;
}
msg += str.str();
}
free(strings);
#else
// unused
(void)msg;
(void)backtrace;
(void)size;
#endif
}

Expand Down
11 changes: 2 additions & 9 deletions lib/backtrace_exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,9 @@ limitations under the License.
#include <exception>
#include <string>

#include "absl/debugging/stacktrace.h"
#include "config.h"

#if HAVE_EXECINFO_H
#include <execinfo.h>
#endif

namespace P4 {

void backtrace_fill_stacktrace(std::string &msg, void *const *backtrace, int size);
Expand All @@ -40,11 +37,7 @@ class backtrace_exception : public E {
public:
template <class... Args>
explicit backtrace_exception(Args &&...args) : E(std::forward<Args>(args)...) {
#if HAVE_EXECINFO_H
backtrace_size = backtrace(backtrace_buffer, buffer_size);
#else
backtrace_size = 0;
#endif
backtrace_size = absl::GetStackTrace(backtrace_buffer, buffer_size, 1);
}

const char *what() const noexcept {
Expand Down
67 changes: 32 additions & 35 deletions lib/crash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,30 @@ limitations under the License.
#include "crash.h"

#include <config.h>
#include <errno.h>
#if HAVE_EXECINFO_H
#include <execinfo.h>
#endif
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <string.h>

#include <sys/wait.h>

#include <cerrno>
#include <climits>
#include <csignal>
#include <cstring>
#if HAVE_UCONTEXT_H
#include <ucontext.h>
#endif
#include <unistd.h>
#if HAVE_LIBBACKTRACE
#include <backtrace.h>
#endif
#if HAVE_CXXABI_H
#include <cxxabi.h>
#endif

#include <iostream>

#ifdef MULTITHREAD
#include <pthread.h>

#include <mutex>
#endif

#include "absl/debugging/stacktrace.h"
#include "absl/debugging/symbolize.h"
#include "exceptions.h"
#include "exename.h"
#include "hex.h"
Expand Down Expand Up @@ -87,20 +82,17 @@ static void sigint_shutdown(int sig, siginfo_t *, void *) {
#if HAVE_LIBBACKTRACE
static int backtrace_log(void *, uintptr_t pc, const char *fname, int lineno, const char *func) {
char *demangled = nullptr;
#if HAVE_CXXABI_H
int status;
demangled = func ? abi::__cxa_demangle(func, 0, 0, &status) : nullptr;
#endif
char tmp[1024];
if (func && absl::Symbolize((void *)pc, tmp, sizeof(tmp))) demangled = tmp;
LOG1(" 0x" << hex(pc) << " " << (demangled ? demangled : func ? func : "??"));
free(demangled);
if (fname) {
LOG1(" " << fname << ":" << lineno);
}
return 0;
}
static void backtrace_error(void *, const char *msg, int) { perror(msg); }
#endif

#elif HAVE_EXECINFO_H
/*
* call external program addr2line WITHOUT using malloc or stdio or anything
* else that might be problematic if there's memory corruption or exhaustion
Expand Down Expand Up @@ -170,7 +162,8 @@ const char *addr2line(void *addr, const char *text) {
close(pfd2[0]);
to_child = pfd2[1];
}
if (child == -1) return 0;
if (child == -1) return nullptr;

char *p = buffer;
uintptr_t a = (uintptr_t)addr;
int shift = (CHAR_BIT * sizeof(uintptr_t) - 1) & ~3;
Expand All @@ -180,8 +173,8 @@ const char *addr2line(void *addr, const char *text) {
shift -= 4;
}
*p++ = '\n';
auto _unused = write(to_child, buffer, p - buffer);
(void)_unused;
auto written = write(to_child, buffer, p - buffer);
if (written != p - buffer) return nullptr;
p = buffer;
int len;
while (p < buffer + sizeof(buffer) - 1 &&
Expand All @@ -190,10 +183,9 @@ const char *addr2line(void *addr, const char *text) {
}
*p = 0;
if ((p = strchr(buffer, '\n'))) *p = 0;
if (buffer[0] == 0 || buffer[0] == '?') return 0;
if (buffer[0] == 0 || buffer[0] == '?') return nullptr;
return buffer;
}
#endif /* HAVE_EXECINFO_H */

#if HAVE_UCONTEXT_H

Expand Down Expand Up @@ -278,24 +270,25 @@ static void crash_shutdown(int sig, siginfo_t *info, void *uctxt) {
(void)uctxt; // Suppress unused parameter warning.
#endif

#if HAVE_LIBBACKTRACE
if (LOGGING(1)) {
#if HAVE_LIBBACKTRACE
backtrace_full(global_backtrace_state, 1, backtrace_log, backtrace_error, nullptr);
}
#elif HAVE_EXECINFO_H
if (LOGGING(1)) {
#else
static void *buffer[64];
int size = backtrace(buffer, 64);
char **strings = backtrace_symbols(buffer, size);
for (int i = 1; i < size; i++) {
if (strings) LOG1(" " << strings[i]);
if (const char *line = addr2line(buffer[i], strings ? strings[i] : 0))
LOG1(" " << line);
static char tmp[1024];
int size = absl::GetStackTrace(buffer, 64, 1);
for (int i = 0; i < size; i++) {
void *pc = buffer[i];
const char *symbol = "(unknown)";
if (absl::Symbolize(pc, tmp, sizeof(tmp))) {
symbol = tmp;
}
const char *alt = addr2line(pc, nullptr);
LOG1(" 0x" << hex(pc) << " " << (alt ? alt : symbol));
}
if (size < 1) LOG1("backtrace failed");
free(strings);
}
#endif
}
MTONLY(
if (++threads_dumped < int(thread_ids.size())) {
lock.unlock();
Expand All @@ -314,6 +307,7 @@ void setup_signals() {
sigaction(SIGINT, &sigact, 0);
sigaction(SIGQUIT, &sigact, 0);
sigaction(SIGTERM, &sigact, 0);

sigact.sa_sigaction = crash_shutdown;
sigaction(SIGILL, &sigact, 0);
sigaction(SIGABRT, &sigact, 0);
Expand All @@ -322,9 +316,12 @@ void setup_signals() {
sigaction(SIGBUS, &sigact, 0);
sigaction(SIGTRAP, &sigact, 0);
signal(SIGPIPE, SIG_IGN);

#if HAVE_LIBBACKTRACE
if (LOGGING(1)) global_backtrace_state = backtrace_create_state(exename(), 1, nullptr, nullptr);
#endif

absl::InitializeSymbolizer(exename());
}

} // namespace P4
Loading
Loading