Skip to content

Commit

Permalink
Switch to abseil symbolization / stack tracing routines
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Korobeynikov <[email protected]>
  • Loading branch information
asl committed Dec 26, 2024
1 parent 5dc7f87 commit e060ffc
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 103 deletions.
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

0 comments on commit e060ffc

Please sign in to comment.