Skip to content

Commit

Permalink
Enable libunwind stacktrace printing with additional debug informatio…
Browse files Browse the repository at this point in the history
…n (1014) (#1015)

* Enable libunwind stacktrace printing with additional debug information (1014)
 * it will also print command to fetch function and line from external debug symbols file

* logging agent version, improved labels and fixed logging in case of error
  • Loading branch information
intuibase authored Jul 5, 2023
1 parent 8650c9c commit 5257f69
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 23 deletions.
8 changes: 7 additions & 1 deletion agent/native/ext/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,20 @@ foreach(_php_version ${_supported_php_versions})
"PHP_ATOM_INC"
"PHP_ABI=${CMAKE_C_COMPILER_ABI}")

if(MUSL_BUILD)
target_compile_definitions(${_Target}
PRIVATE
"__ELASTIC_LIBC_MUSL__"
)
endif()

target_include_directories(${_Target} PUBLIC "${CONAN_INCLUDE_DIRS_PHP-HEADERS-${_php_version}}"
"${CONAN_INCLUDE_DIRS_PHP-HEADERS-${_php_version}}/ext"
"${CONAN_INCLUDE_DIRS_PHP-HEADERS-${_php_version}}/main"
"${CONAN_INCLUDE_DIRS_PHP-HEADERS-${_php_version}}/TSRM"
"${CONAN_INCLUDE_DIRS_PHP-HEADERS-${_php_version}}/Zend"
"${CONAN_INCLUDE_DIRS_LIBCURL}"
"${CONAN_INCLUDE_DIRS_LIBUNWIND}"

)

target_link_libraries(${_Target}
Expand Down
66 changes: 44 additions & 22 deletions agent/native/ext/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include "platform.h"
#include "elastic_apm_version.h"
#include <limits.h>
#include <string.h>
#include <stdlib.h>
Expand All @@ -36,6 +37,8 @@
# include <syslog.h>
# include <signal.h>
# include <errno.h>
#define __USE_GNU
#include <dlfcn.h>
#endif

#if defined( ELASTIC_APM_PLATFORM_HAS_LIBUNWIND )
Expand Down Expand Up @@ -378,30 +381,43 @@ void iterateOverCStackTraceLibUnwind( size_t numberOfFramesToSkip, IterateOverCS
for (;; ++frameIndex)
{
// +1 is for this function frame
if ( frameIndex >= numberOfFramesToSkip + 1 )
{
// https://www.nongnu.org/libunwind/man/unw_get_proc_name(3).html
int getProcNameRetVal = unw_get_proc_name( &unwindCursor, funcNameBuffer, funcNameBufferSize, &offsetInsideFunc );
if ( frameIndex >= numberOfFramesToSkip + 1 ) {
textOutputStreamRewind( &txtOutStream );
switch ( getProcNameRetVal ) // https://www.nongnu.org/libunwind/man/unw_get_proc_name(3).html
{
case 0: // On successful completion, unw_get_proc_name() returns 0
callback( streamPrintf( &txtOutStream, "%s + 0x%X", funcNameBuffer, (unsigned int)offsetInsideFunc ), callbackCtx );
break;
case UNW_EUNSPEC: // An unspecified error occurred.
logErrorCallback( streamPrintf( &txtOutStream, "unw_get_proc_name call failed with return value UNW_EUNSPEC - stopping iteration over call stack" ), callbackCtx );
return;
case UNW_ENOINFO: // Libunwind was unable to determine the name of the procedure.
callback( NULL, callbackCtx );
break;
case UNW_ENOMEM: // The procedure name is too long to fit in the buffer provided. A truncated version of the name has been returned.
callback( streamPrintf( &txtOutStream, "%s (truncated) + 0x%X", funcNameBuffer, (unsigned int)offsetInsideFunc ), callbackCtx );
break;
default:
logErrorCallback( streamPrintf( &txtOutStream, "unw_get_proc_name call failed with an unexpected return value (%d) - stopping iteration over call stack", getProcNameRetVal ), callbackCtx );
return;
unw_proc_info_t pi;
if (unw_get_proc_info(&unwindCursor, &pi) == 0) {
*funcNameBuffer = 0;
offsetInsideFunc = 0;
int getProcNameRetVal = unw_get_proc_name( &unwindCursor, funcNameBuffer, funcNameBufferSize, &offsetInsideFunc );
if (getProcNameRetVal != UNW_ESUCCESS && getProcNameRetVal != -UNW_ENOMEM) {
strcpy(funcNameBuffer, "???");
unw_word_t pc;
unw_get_reg(&unwindCursor, UNW_REG_IP, &pc);
offsetInsideFunc = pc - pi.start_ip;
}

Dl_info dlInfo;
if (dladdr((const void *)pi.gp, &dlInfo)) {
callback( streamPrintf( &txtOutStream,
"%s(%s+0x%lx) ModuleBase: %p FuncStart: 0x%lx FuncEnd: 0x%lx FuncStartRelative: 0x%lx FuncOffsetRelative: 0x%lx\n\t'addr2line -afCp -e \"%s\" %lx'\n",
dlInfo.dli_fname ? dlInfo.dli_fname : "???",
dlInfo.dli_sname ? dlInfo.dli_sname : funcNameBuffer,
offsetInsideFunc,
dlInfo.dli_fbase,
pi.start_ip,
pi.end_ip,
(void*)pi.start_ip - dlInfo.dli_fbase,
(void*)pi.start_ip - dlInfo.dli_fbase + offsetInsideFunc,
dlInfo.dli_fname ? dlInfo.dli_fname : "???",
(void*)pi.start_ip - dlInfo.dli_fbase + offsetInsideFunc
), callbackCtx );
} else {
logErrorCallback( streamPrintf( &txtOutStream, "dladdr failed on frame %zu", frameIndex), callbackCtx );
}
} else {
logErrorCallback( streamPrintf( &txtOutStream, "unw_get_proc_info failed on frame %zu", frameIndex), callbackCtx );
}
}

int unwindStepRetVal = 0;
ELASTIC_APM_LIBUNWIND_CALL_RETURN_ON_ERROR( unwindStepRetVal = unw_step( &unwindCursor ) );
if ( unwindStepRetVal == 0 )
Expand Down Expand Up @@ -532,7 +548,13 @@ OsSignalHandler g_oldSignalHandler = NULL;

void handleOsSignalLinux( int signalId )
{
ELASTIC_APM_LOG_FROM_CRASH_SIGNAL_HANDLER( "Received signal %d (%s)", signalId, osSignalIdToName( signalId ) );
#ifdef __ELASTIC_LIBC_MUSL__
#define LIBC_IMPL "musl"
#else
#define LIBC_IMPL ""
#endif

ELASTIC_APM_LOG_FROM_CRASH_SIGNAL_HANDLER( "Received signal %d (%s). Agent version: " PHP_ELASTIC_APM_VERSION " " LIBC_IMPL, signalId, osSignalIdToName( signalId ) );
handleOsSignalLinux_writeStackTraceToSyslog();

/* Call the default signal handler to have core dump generated... */
Expand Down
2 changes: 2 additions & 0 deletions agent/native/ext/unit_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ LIST( APPEND source_files ${src_ext_dir}/time_util.h ${src_ext_dir}/time_util.c
LIST( APPEND source_files ${src_ext_dir}/Tracer.h ${src_ext_dir}/Tracer.c )
LIST( APPEND source_files ${src_ext_dir}/Tracer.h ${src_ext_dir}/util.c )

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++ -pthread -ldl")

IF ( NOT WIN32 )
ADD_LINK_OPTIONS( -rdynamic )
ENDIF()
Expand Down

0 comments on commit 5257f69

Please sign in to comment.