3131void print_stacktrace (FILE* output, int start_idx, bool demangling, int maxdepth, bool omit_above_own)
3232{
3333 // 32 vs. 64bit
34- #define ADDRESSDISPLAYLENGTH ((sizeof (long )==8 )?12 :8 )
34+ static constexpr auto ADDRESSDISPLAYLENGTH = (sizeof (long ) == 8 ) ? 12 : 8 ;
35+
3536 void *callstackArray[32 ]= {nullptr }; // the less resources the better...
3637 const int currentdepth = backtrace (callstackArray, static_cast <int >(getArrayLength (callstackArray)));
38+ if (currentdepth == 0 ) {
39+ fputs (" Callstack could not be obtained (backtrace)\n " , output);
40+ return ;
41+ }
42+ if (currentdepth == getArrayLength (callstackArray)) {
43+ fputs (" Callstack might be truncated\n " , output);
44+ }
3745 // set offset to 1 to omit the printing function itself
3846 int offset=start_idx+1 ; // some entries on top are within our own exception handling code or libc
3947 if (maxdepth<0 )
@@ -43,61 +51,92 @@ void print_stacktrace(FILE* output, int start_idx, bool demangling, int maxdepth
4351
4452 char **symbolStringList = backtrace_symbols (callstackArray, currentdepth);
4553 if (!symbolStringList) {
46- fputs (" Callstack could not be obtained\n " , output);
54+ fputs (" Callstack could not be obtained (backtrace_symbols) \n " , output);
4755 return ;
4856 }
4957
5058 fputs (" Callstack:\n " , output);
5159 bool own_code = false ;
5260 char demangle_buffer[2048 ]= {0 };
61+ bool no_address = false ;
5362 for (int i = offset; i < maxdepth; ++i) {
5463 const char * const symbolString = symbolStringList[i];
5564 // TODO: implement parsing for __APPLE__
65+ // 0 test-signalhandler 0x0000000100dbf42c _Z16print_stacktraceP7__sFILEibib + 124
66+
67+ /*
68+ * examples:
69+ * ./test-signalhandler(_Z16print_stacktraceP8_IO_FILEibib+0xa1) [0x55cb65e41464]
70+ * ./test-signalhandler(+0xf9d9) [0x55cb65e3c9d9]
71+ */
72+
5673 // skip all leading libc symbols so the first symbol is our code
5774 if (omit_above_own && !own_code) {
5875 if (strstr (symbolString, " /libc.so.6" ) != nullptr )
5976 continue ;
6077 own_code = true ;
61- offset = i; // make sure the numbering is continous if we omit frames
78+ offset = i; // make sure the numbering is continuous if we omit frames
6279 }
6380 const char * realnameString = nullptr ;
64- const char * const firstBracketName = strchr (symbolString, ' (' );
65- const char * const firstBracketAddress = strchr (symbolString, ' [' );
66- const char * const secondBracketAddress = strchr (firstBracketAddress, ' ]' );
67- const char * const beginAddress = firstBracketAddress+3 ;
68- const int addressLen = int (secondBracketAddress-beginAddress);
69- const int padLen = (ADDRESSDISPLAYLENGTH-addressLen);
70- if (demangling && firstBracketName) {
71- const char * const plus = strchr (firstBracketName, ' +' );
72- if (plus && (plus>(firstBracketName+1 ))) {
73- char input_buffer[1024 ]= {0 };
74- strncpy (input_buffer, firstBracketName+1 , plus-firstBracketName-1 );
75- size_t length = getArrayLength (demangle_buffer);
76- int status=0 ;
77- // We're violating the specification - passing stack address instead of malloc'ed heap.
78- // Benefit is that no further heap is required, while there is sufficient stack...
79- realnameString = abi::__cxa_demangle (input_buffer, demangle_buffer, &length, &status); // non-NULL on success
81+ if (demangling) {
82+ const char * const firstBracketName = strchr (symbolString, ' (' );
83+ if (firstBracketName) {
84+ const char * const plus = strchr (firstBracketName, ' +' );
85+ if (plus && (plus>(firstBracketName+1 ))) {
86+ char input_buffer[1024 ]= {0 };
87+ strncpy (input_buffer, firstBracketName+1 , plus-firstBracketName-1 );
88+ size_t length = getArrayLength (demangle_buffer);
89+ int status=0 ;
90+ // We're violating the specification - passing stack address instead of malloc'ed heap.
91+ // Benefit is that no further heap is required, while there is sufficient stack...
92+ realnameString = abi::__cxa_demangle (input_buffer, demangle_buffer, &length, &status); // non-NULL on success
93+ }
8094 }
8195 }
96+
97+ const char * const firstBracketAddress = strchr (symbolString, ' [' );
98+ if (!firstBracketAddress) {
99+ no_address = true ;
100+ break ;
101+ }
102+ const char * const secondBracketAddress = strchr (firstBracketAddress, ' ]' );
103+ if (!secondBracketAddress) {
104+ no_address = true ;
105+ break ;
106+ }
107+
82108 const int ordinal=i-offset;
83109 fprintf (output, " #%-2d 0x" ,
84110 ordinal);
111+ const int padLen = [&]() {
112+ const char * const beginAddress = firstBracketAddress+3 ;
113+ const int addressLen = int (secondBracketAddress-beginAddress);
114+ return (ADDRESSDISPLAYLENGTH-addressLen);
115+ }();
85116 if (padLen>0 )
86117 fprintf (output, " %0*d" ,
87- padLen, 0 );
118+ padLen,
119+ 0 );
88120 if (realnameString) {
89121 fprintf (output, " %.*s in %s\n " ,
90- static_cast <int >(secondBracketAddress - firstBracketAddress - 3 ), firstBracketAddress+3 ,
122+ static_cast <int >(secondBracketAddress - firstBracketAddress - 3 ),
123+ firstBracketAddress+3 ,
91124 realnameString);
92125 } else {
93126 fprintf (output, " %.*s in %.*s\n " ,
94- static_cast <int >(secondBracketAddress - firstBracketAddress - 3 ), firstBracketAddress+3 ,
95- static_cast <int >(firstBracketAddress - symbolString), symbolString);
127+ static_cast <int >(secondBracketAddress - firstBracketAddress - 3 ),
128+ firstBracketAddress+3 ,
129+ static_cast <int >(firstBracketAddress - symbolString),
130+ symbolString);
96131 }
97132 }
98133 // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion) - code matches the documented usage
99134 free (symbolStringList);
100- #undef ADDRESSDISPLAYLENGTH
135+
136+ if (no_address) {
137+ fputs (" Callstack could not be obtained (no address)\n " , output);
138+ return ;
139+ }
101140}
102141
103142#endif // USE_UNIX_BACKTRACE_SUPPORT
0 commit comments