diff --git a/CMakeLists.txt b/CMakeLists.txt index 7cb6cf9..38dcb60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,8 @@ option (WITH_GFLAGS "Use gflags" ON) option (WITH_THREADS "Enable multithreading support" ON) option (WITH_TLS "Enable Thread Local Storage (TLS) support" ON) option (BUILD_SHARED_LIBS "Build shared libraries" OFF) +option (PRINT_UNSYMBOLIZED_STACK_TRACES + "Print raw pc values on symbolization failure" OFF) list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) diff --git a/configure.ac b/configure.ac index 6a19cd0..a181d25 100644 --- a/configure.ac +++ b/configure.ac @@ -207,6 +207,15 @@ AC_PC_FROM_UCONTEXT(AC_MSG_WARN(Could not find the PC. Will not output failed a AC_DEFINE_UNQUOTED(TEST_SRC_DIR, "$srcdir", [location of source code]) +AC_ARG_ENABLE(unsymbolized-traces, + AS_HELP_STRING([--enable-unsymbolized-traces], + [Print raw pc values when symbolization is failed.]), + enable_unsymbolized_traces=yes) +if test x"$enable_unsymbolized_traces" = x"yes"; then + AC_DEFINE(PRINT_UNSYMBOLIZED_STACK_TRACES, 1, + [define if we should print raw pc values on symbolization failure.]) +fi + # These are what's needed by logging.h.in and raw_logging.h.in AC_SUBST(ac_google_start_namespace) AC_SUBST(ac_google_end_namespace) diff --git a/src/config.h.cmake.in b/src/config.h.cmake.in index d5c281c..2ee3291 100644 --- a/src/config.h.cmake.in +++ b/src/config.h.cmake.in @@ -167,6 +167,9 @@ /* How to access the PC from a struct ucontext */ #cmakedefine PC_FROM_UCONTEXT +/* define if we should print raw pc values on symbolization failure. */ +#cmakedefine PRINT_UNSYMBOLIZED_STACK_TRACES + /* Define to necessary symbol if this constant uses a non-standard name on your system. */ #cmakedefine PTHREAD_CREATE_JOINABLE diff --git a/src/config.h.in b/src/config.h.in index 8190f23..4505366 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -154,6 +154,9 @@ /* How to access the PC from a struct ucontext */ #undef PC_FROM_UCONTEXT +/* define if we should print raw pc values on symbolization failure. */ +#undef PRINT_UNSYMBOLIZED_STACK_TRACES + /* Define to necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE diff --git a/src/symbolize.cc b/src/symbolize.cc index 62eff1f..1ffc607 100644 --- a/src/symbolize.cc +++ b/src/symbolize.cc @@ -58,6 +58,7 @@ #include +#include #include #include "symbolize.h" @@ -292,13 +293,12 @@ FindSymbol(uint64_t pc, const int fd, char *out, int out_size, // Read at most NUM_SYMBOLS symbols at once to save read() calls. ElfW(Sym) buf[NUM_SYMBOLS]; - const ssize_t len = ReadFromOffset(fd, &buf, sizeof(buf), offset); - if (len == -1) { - return false; - } + int num_symbols_to_read = std::min(NUM_SYMBOLS, num_symbols - i); + const ssize_t len = + ReadFromOffset(fd, &buf, sizeof(buf[0]) * num_symbols_to_read, offset); SAFE_ASSERT(len % sizeof(buf[0]) == 0); const ssize_t num_symbols_in_buf = len / sizeof(buf[0]); - SAFE_ASSERT(num_symbols_in_buf <= sizeof(buf)/sizeof(buf[0])); + SAFE_ASSERT(num_symbols_in_buf <= num_symbols_to_read); for (int j = 0; j < num_symbols_in_buf; ++j) { const ElfW(Sym)& symbol = buf[j]; uint64_t start_address = symbol.st_value; @@ -684,7 +684,8 @@ static char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) // Handle negative numbers (only for base 10). if (i < 0 && base == 10) { - j = -i; + // This does "j = -i" while avoiding integer overflow. + j = static_cast(-(i + 1)) + 1; // Make sure we can write the '-' character. if (++n > sz) { @@ -780,8 +781,13 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, out_size - 1); } +#if defined(PRINT_UNSYMBOLIZED_STACK_TRACES) + { + FileDescriptor wrapped_object_fd(object_fd); +#else // Check whether a file name was returned. if (object_fd < 0) { +#endif if (out[1]) { // The object file containing PC was determined successfully however the // object file was not opened successfully. This is still considered @@ -805,7 +811,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, // Run the call back if it's installed. // Note: relocation (and much of the rest of this code) will be // wrong for prelinked shared libraries and PIE executables. - uint64 relocation = (elf_type == ET_DYN) ? start_address : 0; + uint64_t relocation = (elf_type == ET_DYN) ? start_address : 0; int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(), pc, out, out_size, relocation); diff --git a/src/symbolize.h b/src/symbolize.h index 9ff16c1..c6f9ec4 100644 --- a/src/symbolize.h +++ b/src/symbolize.h @@ -116,8 +116,11 @@ _START_GOOGLE_NAMESPACE_ // counter "pc". The callback function should write output to "out" // and return the size of the output written. On error, the callback // function should return -1. -typedef int (*SymbolizeCallback)(int fd, void *pc, char *out, size_t out_size, - uint64 relocation); +typedef int (*SymbolizeCallback)(int fd, + void* pc, + char* out, + size_t out_size, + uint64_t relocation); void InstallSymbolizeCallback(SymbolizeCallback callback); // Installs a callback function, which will be called instead of @@ -130,10 +133,10 @@ void InstallSymbolizeCallback(SymbolizeCallback callback); // file is opened successfully, returns the file descriptor. Otherwise, // returns -1. |out_file_name_size| is the size of the file name buffer // (including the null-terminator). -typedef int (*SymbolizeOpenObjectFileCallback)(uint64 pc, - uint64 &start_address, - uint64 &base_address, - char *out_file_name, +typedef int (*SymbolizeOpenObjectFileCallback)(uint64_t pc, + uint64_t& start_address, + uint64_t& base_address, + char* out_file_name, int out_file_name_size); void InstallSymbolizeOpenObjectFileCallback( SymbolizeOpenObjectFileCallback callback);