From c8264291238e0bd199e4babab7013060e7fcba7d Mon Sep 17 00:00:00 2001 From: David Steele Date: Wed, 11 Jan 2023 11:19:26 +0700 Subject: [PATCH] Improve libbacktrace implementation. The libbacktrace feature has not been working since the move to meson because libbacktrace detection was not added to the meson build. Add libbacktrace to meson and improve the feature so that it can be compiled into release builds. The prior implementation fetched line numbers with each stack trace push. Not only was this slow but it missed any functions that were not being tracked on our stack. Instead just examine the backtrace when an error happens and merge it with the info we have on our stack. If the backtrace is not available then the output remains as before. Also remove --backtrace from test.pl since the library is now auto-detected. Leave this library out of the production build for now to give it a little time to shake out in testing. --- .github/workflows/symbol.out | 20 +++ meson.build | 7 + src/common/stackTrace.c | 190 ++++++++++++++++------ src/common/stackTrace.h | 5 - src/main.c | 4 - src/meson.build | 2 + test/lib/pgBackRestTest/Common/JobTest.pm | 2 - test/lib/pgBackRestTest/Common/VmTest.pm | 17 -- test/src/command/test/build.c | 1 + test/src/common/harnessDebug.h | 8 - test/src/meson.build | 1 + test/src/module/common/errorTest.c | 2 +- test/src/module/common/stackTraceTest.c | 182 +++++++++++++++++++-- test/src/module/test/testTest.c | 4 + test/src/test.c | 3 - test/test.pl | 15 +- 16 files changed, 348 insertions(+), 115 deletions(-) diff --git a/.github/workflows/symbol.out b/.github/workflows/symbol.out index def70a991..6cc0b4f29 100644 --- a/.github/workflows/symbol.out +++ b/.github/workflows/symbol.out @@ -9,6 +9,26 @@ _end _fini _init _start +backtrace_alloc +backtrace_close +backtrace_create_state +backtrace_dwarf_add +backtrace_free +backtrace_full +backtrace_get_view +backtrace_initialize +backtrace_open +backtrace_pcinfo +backtrace_qsort +backtrace_release_view +backtrace_syminfo +backtrace_syminfo_to_full_callback +backtrace_syminfo_to_full_error_callback +backtrace_uncompress_lzma +backtrace_uncompress_zdebug +backtrace_vector_finish +backtrace_vector_grow +backtrace_vector_release data_start environ@GLIBC_2.2.5 main diff --git a/meson.build b/meson.build index af5aea3bc..d809f4492 100644 --- a/meson.build +++ b/meson.build @@ -133,6 +133,13 @@ add_project_arguments(cc.get_supported_arguments('-fmacro-prefix-map=@0@/test/sr #################################################################################################################################### configuration = configuration_data() +# Find optional backtrace library +lib_backtrace = cc.find_library('backtrace', required: false) + +if lib_backtrace.found() + configuration.set('HAVE_LIBBACKTRACE', true, description: 'Is libbacktrace present?') +endif + # Find required bz2 library lib_bz2 = cc.find_library('bz2') diff --git a/src/common/stackTrace.c b/src/common/stackTrace.c index b5fbd0542..b1453f20d 100644 --- a/src/common/stackTrace.c +++ b/src/common/stackTrace.c @@ -7,7 +7,7 @@ Stack Trace Handler #include #include -#ifdef WITH_BACKTRACE +#ifdef HAVE_LIBBACKTRACE #include #include #endif @@ -45,46 +45,11 @@ static struct StackTraceLocal int stackSize; // Stack size StackTraceData stack[STACK_TRACE_MAX]; // Stack data char functionParamBuffer[32 * 1024]; // Buffer to hold function parameters -} stackTraceLocal; -/**********************************************************************************************************************************/ -#ifdef WITH_BACKTRACE - -static struct StackTraceBackLocal -{ +#ifdef HAVE_LIBBACKTRACE struct backtrace_state *backTraceState; // Backtrace state struct -} stackTraceBackLocal; - -FN_EXTERN void -stackTraceInit(const char *exe) -{ - if (stackTraceBackLocal.backTraceState == NULL) - stackTraceBackLocal.backTraceState = backtrace_create_state(exe, false, NULL, NULL); -} - -static int -backTraceCallback(void *data, uintptr_t pc, const char *filename, int lineno, const char *function) -{ - (void)(data); - (void)(pc); - (void)(filename); - (void)(function); - - if (stackTraceLocal.stackSize > 0) - stackTraceLocal.stack[stackTraceLocal.stackSize - 1].fileLine = (unsigned int)lineno; - - return 1; -} - -static void -backTraceCallbackError(void *data, const char *msg, int errnum) -{ - (void)data; - (void)msg; - (void)errnum; -} - #endif +} stackTraceLocal; /**********************************************************************************************************************************/ #ifdef DEBUG @@ -128,11 +93,6 @@ stackTracePush(const char *fileName, const char *functionName, LogLevel function { ASSERT(stackTraceLocal.stackSize < STACK_TRACE_MAX - 1); - // Get line number from backtrace if available -#ifdef WITH_BACKTRACE - backtrace_full(stackTraceBackLocal.backTraceState, 2, backTraceCallback, backTraceCallbackError, NULL); -#endif - // Set function info StackTraceData *data = &stackTraceLocal.stack[stackTraceLocal.stackSize]; @@ -303,16 +263,118 @@ stackTraceFmt(char *buffer, size_t bufferSize, size_t bufferUsed, const char *fo return (size_t)result; } +/*********************************************************************************************************************************** +Helper to trim off extra path before the src path +***********************************************************************************************************************************/ +static const char * +stackTraceTrimSrc(const char *const fileName) +{ + const char *const src = strstr(fileName, "src/"); + return src == NULL ? fileName : src + 4; +} + /**********************************************************************************************************************************/ -FN_EXTERN size_t -stackTraceToZ(char *buffer, size_t bufferSize, const char *fileName, const char *functionName, unsigned int fileLine) +#ifdef HAVE_LIBBACKTRACE + +typedef struct StackTraceBackData +{ + bool firstCall; + bool firstLine; + int stackIdx; + size_t result; + char *const buffer; + const size_t bufferSize; +} StackTraceBackData; + +// Callback to add backtrace data when available +static int +stackTraceBackCallback( + void *const dataVoid, const uintptr_t pc, const char *fileName, const int fileLine, const char *const functionName) +{ + (void)(pc); + StackTraceBackData *const data = dataVoid; + + // Stop if the stack has been exhausted + if (data->stackIdx < 0) + return true; + + // Catch any unset parameters which indicates the debug data is not available + if (fileName == NULL || fileLine == 0 || functionName == NULL) + { + // If this is the first call then stop because the top of the backtrace must be one of our functions + if (data->firstCall) + return true; + + // Else return but do not stop + data->firstCall = false; + return false; + } + + // Reset first call + data->firstCall = false; + + // If the function name matches combine backtrace data with stack data + const StackTraceData *const traceData = &stackTraceLocal.stack[data->stackIdx]; + + if (strcmp(functionName, traceData->functionName) == 0) + { + data->result += stackTraceFmt( + data->buffer, data->bufferSize, data->result, "%s%s:%s:%d:(%s)", data->firstLine ? "" : "\n", + stackTraceTrimSrc(traceData->fileName), functionName, fileLine, stackTraceParamIdx(data->stackIdx)); + + data->stackIdx--; + } + // Else just use stack data. Skip any functions in the error module since they are not useful for the user + else + { + fileName = stackTraceTrimSrc(fileName); + + if (strcmp(fileName, "common/error.c") == 0) + return false; + + data->result += stackTraceFmt( + data->buffer, data->bufferSize, data->result, "%s%s:%s:%d:(no parameters available)", data->firstLine ? "" : "\n", + fileName, functionName, fileLine); + } + + // Reset first line + data->firstLine = false; + + // Stop when the main function has been processed + return strcmp(functionName, "main") == 0; +} + +// Dummy error callback. If there is an error just generate the default stack trace. +static void +stackTraceBackErrorCallback(void *data, const char *msg, int errnum) +{ + (void)data; + (void)msg; + (void)errnum; +} + +#endif + +// Helper to build stack trace when backtrace is not available +#ifdef HAVE_LIBBACKTRACE + static size_t + stackTraceToZDefault( +#else + FN_EXTERN size_t + stackTraceToZ( +#endif // HAVE_LIBBACKTRACE + + char *const buffer, const size_t bufferSize, const char *fileName, const char *const functionName, + const unsigned int fileLine) { size_t result = 0; const char *param = "test build required for parameters"; int stackIdx = stackTraceLocal.stackSize - 1; // If the current function passed in is the same as the top function on the stack then use the parameters for that function - if (stackTraceLocal.stackSize > 0 && strcmp(fileName, stackTraceLocal.stack[stackIdx].fileName) == 0 && + fileName = stackTraceTrimSrc(fileName); + + if (stackTraceLocal.stackSize > 0 && strcmp(fileName, stackTraceTrimSrc(stackTraceLocal.stack[stackIdx].fileName)) == 0 && strcmp(functionName, stackTraceLocal.stack[stackIdx].functionName) == 0) { param = stackTraceParamIdx(stackTraceLocal.stackSize - 1); @@ -332,9 +394,9 @@ stackTraceToZ(char *buffer, size_t bufferSize, const char *fileName, const char // Output the rest of the stack for (; stackIdx >= 0; stackIdx--) { - StackTraceData *data = &stackTraceLocal.stack[stackIdx]; + const StackTraceData *const data = &stackTraceLocal.stack[stackIdx]; - result += stackTraceFmt(buffer, bufferSize, result, "\n%s:%s", data->fileName, data->functionName); + result += stackTraceFmt(buffer, bufferSize, result, "\n%s:%s", stackTraceTrimSrc(data->fileName), data->functionName); if (data->fileLine > 0) result += stackTraceFmt(buffer, bufferSize, result, ":%u", data->fileLine); @@ -346,6 +408,38 @@ stackTraceToZ(char *buffer, size_t bufferSize, const char *fileName, const char return result; } +#ifdef HAVE_LIBBACKTRACE + +FN_EXTERN size_t +stackTraceToZ( + char *const buffer, const size_t bufferSize, const char *const fileName, const char *const functionName, + const unsigned int fileLine) +{ + // Attempt to use backtrace data + StackTraceBackData data = + { + .firstCall = true, + .firstLine = true, + .stackIdx = stackTraceLocal.stackSize - 1, + .result = 0, + .buffer = buffer, + .bufferSize = bufferSize, + }; + + if (stackTraceLocal.backTraceState == NULL) + stackTraceLocal.backTraceState = backtrace_create_state(NULL, false, NULL, NULL); + + backtrace_full(stackTraceLocal.backTraceState, 2, stackTraceBackCallback, stackTraceBackErrorCallback, &data); + + // If the backtrace was not available generate default stack trace + if (data.result == 0) + return stackTraceToZDefault(buffer, bufferSize, fileName, functionName, fileLine); + + return data.result; +} + +#endif // HAVE_LIBBACKTRACE + /**********************************************************************************************************************************/ FN_EXTERN void stackTraceClean(const unsigned int tryDepth, const bool fatal) diff --git a/src/common/stackTrace.h b/src/common/stackTrace.h index 25647a0ce..2570d0481 100644 --- a/src/common/stackTrace.h +++ b/src/common/stackTrace.h @@ -31,11 +31,6 @@ Macros to access internal functions /*********************************************************************************************************************************** Internal Functions ***********************************************************************************************************************************/ -// Backtrace init -#ifdef WITH_BACKTRACE - void stackTraceInit(const char *exe); -#endif - #ifdef DEBUG // Enable/disable test function logging FN_EXTERN void stackTraceTestStart(void); diff --git a/src/main.c b/src/main.c index 8d7864fea..99f6a0aad 100644 --- a/src/main.c +++ b/src/main.c @@ -73,10 +73,6 @@ main(int argListSize, const char *argList[]) storageHelperInit(storageHelperList); -#ifdef WITH_BACKTRACE - stackTraceInit(argList[0]); -#endif - FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(INT, argListSize); FUNCTION_LOG_PARAM(CHARPY, argList); diff --git a/src/meson.build b/src/meson.build index 89ed70ff8..11a9aa1ab 100644 --- a/src/meson.build +++ b/src/meson.build @@ -93,6 +93,7 @@ build_code = executable( src_common, src_build_code, dependencies: [ + lib_backtrace, lib_bz2, lib_xml, lib_yaml @@ -253,6 +254,7 @@ executable( help_auto_c_inc, interface_auto_c_inc, dependencies : [ + lib_backtrace, lib_bz2, lib_openssl, lib_lz4, diff --git a/test/lib/pgBackRestTest/Common/JobTest.pm b/test/lib/pgBackRestTest/Common/JobTest.pm index efd21dfd5..2a584b654 100644 --- a/test/lib/pgBackRestTest/Common/JobTest.pm +++ b/test/lib/pgBackRestTest/Common/JobTest.pm @@ -69,7 +69,6 @@ sub new $self->{bCoverageUnit}, $self->{bCoverageSummary}, $self->{bOptimize}, - $self->{bBackTrace}, $self->{bProfile}, $self->{iScale}, $self->{strTimeZone}, @@ -102,7 +101,6 @@ sub new {name => 'bCoverageUnit'}, {name => 'bCoverageSummary'}, {name => 'bOptimize'}, - {name => 'bBackTrace'}, {name => 'bProfile'}, {name => 'iScale'}, {name => 'strTimeZone', required => false}, diff --git a/test/lib/pgBackRestTest/Common/VmTest.pm b/test/lib/pgBackRestTest/Common/VmTest.pm index ec9449449..bf47cafa6 100644 --- a/test/lib/pgBackRestTest/Common/VmTest.pm +++ b/test/lib/pgBackRestTest/Common/VmTest.pm @@ -44,8 +44,6 @@ use constant VMDEF_PGSQL_BIN => 'psql-bin push @EXPORT, qw(VMDEF_PGSQL_BIN); use constant VMDEF_LCOV_VERSION => 'lcov-version'; push @EXPORT, qw(VMDEF_LCOV_VERSION); -use constant VMDEF_WITH_BACKTRACE => 'with-backtrace'; - push @EXPORT, qw(VMDEF_WITH_BACKTRACE); use constant VMDEF_WITH_LZ4 => 'with-lz4'; push @EXPORT, qw(VMDEF_WITH_LZ4); use constant VMDEF_WITH_ZST => 'with-zst'; @@ -191,7 +189,6 @@ my $oyVm = &VM_ARCH => VM_ARCH_I386, &VMDEF_PGSQL_BIN => '/usr/lib/postgresql/{[version]}/bin', - &VMDEF_WITH_BACKTRACE => true, &VMDEF_WITH_ZST => true, &VM_DB => @@ -218,7 +215,6 @@ my $oyVm = &VMDEF_COVERAGE_C => true, &VMDEF_PGSQL_BIN => '/usr/lib/postgresql/{[version]}/bin', - &VMDEF_WITH_BACKTRACE => true, &VMDEF_WITH_ZST => true, &VM_DB => @@ -252,7 +248,6 @@ my $oyVm = &VMDEF_COVERAGE_C => true, &VMDEF_PGSQL_BIN => '/usr/lib/postgresql/{[version]}/bin', - &VMDEF_WITH_BACKTRACE => true, &VMDEF_WITH_ZST => true, &VM_DB => @@ -433,18 +428,6 @@ sub hostArch push @EXPORT, qw(hostArch); -#################################################################################################################################### -# Does the VM support libbacktrace? -#################################################################################################################################### -sub vmWithBackTrace -{ - my $strVm = shift; - - return ($oyVm->{$strVm}{&VMDEF_WITH_BACKTRACE} ? true : false); -} - -push @EXPORT, qw(vmWithBackTrace); - #################################################################################################################################### # Does the VM support liblz4? #################################################################################################################################### diff --git a/test/src/command/test/build.c b/test/src/command/test/build.c index 0bda249c8..39a844341 100644 --- a/test/src/command/test/build.c +++ b/test/src/command/test/build.c @@ -533,6 +533,7 @@ testBldUnit(TestBuild *const this) " '%s/test/src',\n" " ),\n" " dependencies: [\n" + " lib_backtrace,\n" " lib_bz2,\n" " lib_openssl,\n" " lib_lz4,\n" diff --git a/test/src/common/harnessDebug.h b/test/src/common/harnessDebug.h index 1ace19610..9e3344cf6 100644 --- a/test/src/common/harnessDebug.h +++ b/test/src/common/harnessDebug.h @@ -7,13 +7,6 @@ C Debug Harness #ifdef HRN_FEATURE_DEBUG #include "common/debug.h" - #ifdef WITH_BACKTRACE - #define FUNCTION_HARNESS_INIT(exe) \ - stackTraceInit(exe) - #else - #define FUNCTION_HARNESS_INIT(exe) - #endif - // Set line numer of the current function in the stack trace. This is used to give more detailed info about which test macro // caused an error. #ifdef DEBUG @@ -61,7 +54,6 @@ C Debug Harness #define FUNCTION_HARNESS_RETURN_VOID() \ STACK_TRACE_POP(false); #else - #define FUNCTION_HARNESS_INIT(exe) #define FUNCTION_HARNESS_STACK_TRACE_LINE_SET(lineNo) #define FUNCTION_HARNESS_BEGIN() #define FUNCTION_HARNESS_PARAM(typeMacroPrefix, param) diff --git a/test/src/meson.build b/test/src/meson.build index ddb2ac634..66a27ecb1 100644 --- a/test/src/meson.build +++ b/test/src/meson.build @@ -64,6 +64,7 @@ executable( arg_unity, ], dependencies: [ + lib_backtrace, lib_bz2, lib_yaml, ], diff --git a/test/src/module/common/errorTest.c b/test/src/module/common/errorTest.c index 45e21199b..cdf8d3fb4 100644 --- a/test/src/module/common/errorTest.c +++ b/test/src/module/common/errorTest.c @@ -253,7 +253,7 @@ testRun(void) assert( strcmp( errorStackTrace(), - TEST_PGB_PATH "/test/src/module/common/errorTest.c:testTryRecurse:29:(test build required for parameters)") + "module/common/errorTest.c:testTryRecurse:29:(test build required for parameters)") == 0); assert(strcmp(errorMessage(), "too many nested try blocks") == 0); assert(strcmp(errorName(), AssertError.name) == 0); diff --git a/test/src/module/common/stackTraceTest.c b/test/src/module/common/stackTraceTest.c index 550aaa2f0..e673d3bad 100644 --- a/test/src/module/common/stackTraceTest.c +++ b/test/src/module/common/stackTraceTest.c @@ -3,6 +3,43 @@ Test Stack Trace Handler ***********************************************************************************************************************************/ #include +#ifdef HAVE_LIBBACKTRACE + +FN_NO_RETURN void +testStackTraceError3(void) +{ + stackTracePush("module/common/stackTraceTest.c", "testStackTraceError3", logLevelTrace); + THROW(FormatError, "test error"); +} + +FN_NO_RETURN void +testStackTraceError2(void) +{ + testStackTraceError3(); +} + +FN_NO_RETURN void +testStackTraceError1(void) +{ + stackTracePush("src/file1.c", "testStackTraceError1", logLevelDebug); + testStackTraceError2(); +} + +FN_NO_RETURN void +testStackTraceError5(void) +{ + THROW_FMT(FormatError, "test error fmt"); +} + +FN_NO_RETURN void +testStackTraceError4(void) +{ + stackTracePush("file4.c", "testStackTraceError4", logLevelTrace); + testStackTraceError5(); +} + +#endif + /*********************************************************************************************************************************** Test Run ***********************************************************************************************************************************/ @@ -25,19 +62,107 @@ testRun(void) } // ***************************************************************************************************************************** - if (testBegin("stackTraceInit() and stackTraceError()")) + if (testBegin("libBackTrace")) { -#ifdef WITH_BACKTRACE - stackTraceInit(BOGUS_STR); +#ifdef HAVE_LIBBACKTRACE + // ************************************************************************************************************************* + TEST_TITLE("empty error function"); - // This time does nothing - stackTraceInit(BOGUS_STR); + TEST_RESULT_VOID(stackTraceBackErrorCallback(NULL, NULL, 0), "call error"); - // This will call the error routine since we passed a bogus exe - assert(stackTracePush("file1.c", "function1", logLevelDebug) == logLevelDebug); - stackTracePop("file1.c", "function1", false); + // ************************************************************************************************************************* + TEST_TITLE("missing backtrace data"); - stackTraceLocal.backTraceState = NULL; + StackTraceBackData data = + { + .firstCall = true, + }; + + TEST_RESULT_INT(stackTraceBackCallback(&data, 0, NULL, 0, NULL), true, "all null, first call"); + + data.firstCall = false; + + TEST_RESULT_INT(stackTraceBackCallback(&data, 0, "fileName", 0, NULL), false, "two null"); + TEST_RESULT_INT(stackTraceBackCallback(&data, 0, "fileName", 2, NULL), false, "one null"); + + // Note that it is possible for libbacktrace to be present but not have any debug symbols to work with so handle that by + // looking for an alternative error. However this will not work when coverage is required. + // ************************************************************************************************************************* + TEST_TITLE("backtrace data"); + + TRY_BEGIN() + { + testStackTraceError1(); + } + CATCH_ANY() + { + TRY_BEGIN() + { + TEST_RESULT_Z( + errorStackTrace(), + "module/common/stackTraceTest.c:testStackTraceError3:12:(trace log level required for parameters)\n" + "module/common/stackTraceTest.c:testStackTraceError2:18:(no parameters available)\n" + "file1.c:testStackTraceError1:25:(debug log level required for parameters)", + "check stack trace"); + } + CATCH(TestError) + { + hrnTestResultEnd(); + + TRY_BEGIN() + { + testStackTraceError1(); + } + CATCH_ANY() + { + TEST_RESULT_Z( + errorStackTrace(), + "module/common/stackTraceTest.c:testStackTraceError3:12:(trace log level required for parameters)\n" + "file1.c:testStackTraceError1:(debug log level required for parameters)", + "check stack trace"); + } + TRY_END(); + } + TRY_END(); + } + TRY_END(); + + TRY_BEGIN() + { + testStackTraceError4(); + } + CATCH_ANY() + { + TRY_BEGIN() + { + TEST_RESULT_Z( + errorStackTrace(), + "module/common/stackTraceTest.c:testStackTraceError5:31:(no parameters available)\n" + "file4.c:testStackTraceError4:38:(trace log level required for parameters)", + "check stack trace"); + } + CATCH(TestError) + { + hrnTestResultEnd(); + + TRY_BEGIN() + { + testStackTraceError4(); + } + CATCH_ANY() + { + TEST_RESULT_Z( + errorStackTrace(), + "module/common/stackTraceTest.c:testStackTraceError5:31:(test build required for parameters)\n" + " ... function(s) omitted ...\n" + "file4.c:testStackTraceError4:(trace log level required for parameters)", + "check stack trace"); + } + TRY_END(); + } + TRY_END(); + } + TRY_END(); #endif } @@ -65,9 +190,6 @@ testRun(void) { char buffer[4096]; -#ifdef WITH_BACKTRACE - stackTraceInit(testExe()); -#endif // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("check size of StackTraceData"); @@ -94,7 +216,12 @@ testRun(void) stackTraceParamLog(); assert(strcmp(stackTraceParam(), "void") == 0); - stackTraceToZ(buffer, sizeof(buffer), "file1.c", "function2", 99); +#ifdef HAVE_LIBBACKTRACE + stackTraceToZDefault( +#else + stackTraceToZ( +#endif + buffer, sizeof(buffer), "file1.c", "function2", 99); TEST_RESULT_Z( buffer, @@ -135,7 +262,7 @@ testRun(void) // Munge the previous previous param in the stack so that the next one will just barely fit stackTraceLocal.stack[stackTraceLocal.stackSize - 1].paramSize = bufferOverflow - 1; - assert(stackTracePush("file4.c", "function4", logLevelDebug) == logLevelTrace); + assert(stackTracePush("src/file4.c", "function4", logLevelDebug) == logLevelTrace); stackTraceLocal.stack[stackTraceLocal.stackSize - 2].fileLine = 7777; stackTraceParamLog(); assert(stackTraceLocal.stackSize == 5); @@ -150,7 +277,12 @@ testRun(void) stackTraceParamAdd((size_t)snprintf(stackTraceParamBuffer("param1"), STACK_TRACE_PARAM_MAX, "value1")); assert(strcmp(stackTraceParam(), "buffer full - parameters not available") == 0); - stackTraceToZ(buffer, sizeof(buffer), "file4.c", "function4", 99); +#ifdef HAVE_LIBBACKTRACE + stackTraceToZDefault( +#else + stackTraceToZ( +#endif + buffer, sizeof(buffer), "../pgbackrest/src/file4.c", "function4", 99); TEST_RESULT_Z( buffer, @@ -161,7 +293,25 @@ testRun(void) "file1.c:function1:7777:(void)", "stack trace"); - stackTracePop("file4.c", "function4", false); +#ifdef HAVE_LIBBACKTRACE + stackTraceToZDefault( +#else + stackTraceToZ( +#endif + buffer, sizeof(buffer), "file5.c", "function4", 99); + + TEST_RESULT_Z( + buffer, + "file5.c:function4:99:(test build required for parameters)\n" + " ... function(s) omitted ...\n" + "file4.c:function4:(buffer full - parameters not available)\n" + "file3.c:function3:7777:(param1: value1, param2: value2)\n" + "file2.c:function2:7777:(param1: value1)\n" + "file1.c:function2:7777:(debug log level required for parameters)\n" + "file1.c:function1:7777:(void)", + "stack trace"); + + stackTracePop("src/file4.c", "function4", false); assert(stackTraceLocal.stackSize == 4); // Check that stackTracePop() works with test tracing diff --git a/test/src/module/test/testTest.c b/test/src/module/test/testTest.c index 0f5c05e76..d2388b7a9 100644 --- a/test/src/module/test/testTest.c +++ b/test/src/module/test/testTest.c @@ -295,6 +295,7 @@ testRun(void) " '../../../repo/test/src',\n" " ),\n" " dependencies: [\n" + " lib_backtrace,\n" " lib_bz2,\n" " lib_openssl,\n" " lib_lz4,\n" @@ -399,6 +400,7 @@ testRun(void) " '../../../repo/test/src',\n" " ),\n" " dependencies: [\n" + " lib_backtrace,\n" " lib_bz2,\n" " lib_openssl,\n" " lib_lz4,\n" @@ -605,6 +607,7 @@ testRun(void) " '../../../repo/test/src',\n" " ),\n" " dependencies: [\n" + " lib_backtrace,\n" " lib_bz2,\n" " lib_openssl,\n" " lib_lz4,\n" @@ -764,6 +767,7 @@ testRun(void) " '../../../repo/test/src',\n" " ),\n" " dependencies: [\n" + " lib_backtrace,\n" " lib_bz2,\n" " lib_openssl,\n" " lib_lz4,\n" diff --git a/test/src/test.c b/test/src/test.c index 4ee7bc757..5acf2b68a 100644 --- a/test/src/test.c +++ b/test/src/test.c @@ -151,9 +151,6 @@ main(int argListSize, const char *argList[]) exit(25); } - // Initialize stack trace for the harness - FUNCTION_HARNESS_INIT(argList[0]); - FUNCTION_HARNESS_BEGIN(); FUNCTION_HARNESS_PARAM(INT, argListSize); FUNCTION_HARNESS_PARAM(CHARPY, argList); diff --git a/test/test.pl b/test/test.pl index fc5cc13ab..ef18fd4d7 100755 --- a/test/test.pl +++ b/test/test.pl @@ -84,7 +84,6 @@ test.pl [options] --no-coverage don't run coverage on C unit tests (saves time) --no-coverage-report run coverage but don't generate coverage report (saves time) --no-optimize don't do compile optimization for C (saves compile time) - --backtrace enable backtrace when available (adds stack trace line numbers -- very slow) --profile generate profile info --no-debug don't generate a debug build --scale scale performance tests @@ -158,7 +157,6 @@ my $bGenOnly = false; my $bGenCheck = false; my $bMinGen = false; my $bCodeCount = false; -my $bBackTrace = false; my $bProfile = false; my $bNoValgrind = false; my $bNoOptimize = false; @@ -208,7 +206,6 @@ GetOptions ('q|quiet' => \$bQuiet, 'gen-check' => \$bGenCheck, 'min-gen' => \$bMinGen, 'code-count' => \$bCodeCount, - 'backtrace' => \$bBackTrace, 'profile' => \$bProfile, 'no-valgrind' => \$bNoValgrind, 'no-optimize' => \$bNoOptimize, @@ -729,12 +726,9 @@ eval $rhBinBuild->{$strBuildVM} = false; # Build configure/compile options and see if they have changed from the previous build - my $strCFlags = - (vmWithBackTrace($strBuildVM) && $bBackTrace ? ' -DWITH_BACKTRACE' : '') . - ($bDebugTestTrace ? ' -DDEBUG_TEST_TRACE' : ''); - my $strLdFlags = vmWithBackTrace($strBuildVM) && $bBackTrace ? '-lbacktrace' : ''; + my $strCFlags = ($bDebugTestTrace ? ' -DDEBUG_TEST_TRACE' : ''); my $strConfigOptions = (vmDebugIntegration($strBuildVM) ? ' --enable-test' : ''); - my $strBuildFlags = "CFLAGS_EXTRA=${strCFlags}\nLDFLAGS_EXTRA=${strLdFlags}\nCONFIGURE=${strConfigOptions}"; + my $strBuildFlags = "CFLAGS_EXTRA=${strCFlags}\nCONFIGURE=${strConfigOptions}"; my $strBuildFlagFile = "${strBinPath}/${strBuildVM}/build.flags"; my $bBuildOptionsDiffer = buildPutDiffers($oStorageBackRest, $strBuildFlagFile, $strBuildFlags); @@ -760,8 +754,7 @@ eval executeTest( 'docker exec -i -u ' . TEST_USER . ' test-build ' . "${strMakeCmd} -s -j ${iBuildMax}" . ($bLogDetail ? '' : ' --silent') . - " --directory ${strBuildPath} CFLAGS_EXTRA='${strCFlags}'" . - ($strLdFlags ne '' ? " LDFLAGS_EXTRA='${strLdFlags}'" : ''), + " --directory ${strBuildPath} CFLAGS_EXTRA='${strCFlags}'", {bShowOutputAsync => $bLogDetail}); } } @@ -1062,7 +1055,7 @@ eval $oStorageTest, $strBackRestBase, $strTestPath, $$oyTestRun[$iTestIdx], $bDryRun, $bVmOut, $iVmIdx, $iVmMax, $strMakeCmd, $iTestIdx, $iTestMax, $strLogLevel, $strLogLevelTest, $strLogLevelTestFile, !$bNoLogTimestamp, $bShowOutputAsync, $bNoCleanup, $iRetry, !$bNoValgrind, !$bNoCoverage, $bCoverageSummary, !$bNoOptimize, - $bBackTrace, $bProfile, $iScale, $strTimeZone, !$bNoDebug, $bDebugTestTrace, + $bProfile, $iScale, $strTimeZone, !$bNoDebug, $bDebugTestTrace, $iBuildMax / $iVmMax < 1 ? 1 : int($iBuildMax / $iVmMax)); $iTestIdx++;