1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
17 * Szabo, Janos Zoltan – initial implementation
20 ******************************************************************************/
22 #include "TitanLoggerApi.hh"
27 #include "../common/memory.h"
30 #include "Charstring.hh"
37 #ifndef NO_CPP_DEMANGLE
39 using namespace __cxxabiv1
;
46 const size_t MAX_DEPTH
=100;
48 void stacktrace(const ucontext_t
& ctx
)
50 TTCN_Logger::log_event_str("\nStack trace:\n");
53 void *array
[MAX_DEPTH
];
58 size
= backtrace (array
, MAX_DEPTH
);
59 strings
= backtrace_symbols (array
, size
);
61 //printf ("Obtained %lu stack frames.\n", (unsigned long)size);
63 for (i
= 0; i
< size
; i
++) {
64 const char * symname
= strings
[i
];
66 const char *begin
= 0, *end
= 0;
67 // The format is: /path/to/exe(_Z11mangledname+0xBAAD) [0x...]
68 // Mangled name starts here ---^ ends here--^
69 for (const char *j
= symname
; *j
; ++j
) {
78 size_t len
= end
- begin
;
79 char *mangled
= (char*)malloc(len
+ 1);
80 memcpy(mangled
, begin
, len
);
84 dem
= __cxa_demangle(mangled
, NULL
, 0, &status
);
86 if(status
== 0 && dem
)
90 if (TTCN_Logger::is_logger_up()) {
91 TTCN_Logger::log_event ("%2lu: %s%s\n", (unsigned long)i
, symname
, (end
? end
: ""));
94 fprintf (stderr
, "%2lu: %s%s\n", (unsigned long)i
, symname
, (end
? end
: ""));
104 void where_am_i(TTCN_Logger::Severity sev
= TTCN_Logger::USER_UNQUALIFIED
)
107 int er
= getcontext(&uc
);
109 TTCN_Logger::begin_event(sev
);
111 TTCN_Logger::end_event();
114 perror("getcontext");
119 static void signal_segv(int signum
, siginfo_t
* info
, void*ptr
) {
120 static const char *si_codes
[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"};
121 ucontext_t
*ucontext
= (ucontext_t
*)ptr
;
122 fprintf(stderr
, "\n\n!!! Segmentation Fault !!!\n\n");
123 fprintf(stderr
, "info.si_signo = %d\n", signum
);
124 fprintf(stderr
, "info.si_errno = %d\n", info
->si_errno
);
125 fprintf(stderr
, "info.si_code = %d (%s)\n", info
->si_code
, si_codes
[info
->si_code
]);
126 fprintf(stderr
, "info.si_addr = %p\n", info
->si_addr
);
128 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
129 stacktrace(*ucontext
);
130 TTCN_Logger::end_event();
132 fprintf(stderr
, "\nGoodbye, cruel world!\n");
136 int setup_sigsegv() {
137 struct sigaction action
;
138 memset(&action
, 0, sizeof(action
));
139 action
.sa_sigaction
= signal_segv
;
140 action
.sa_flags
= SA_SIGINFO
;
141 if(sigaction(SIGSEGV
, &action
, NULL
) < 0) {
148 static void __attribute((constructor
)) init(void) {
152 #elif defined(SOLARIS) || defined(SOLARIS8)
155 walks up call stack, printing library:routine+offset for each routine
160 #include<sys/types.h>
162 #include <sys/frame.h>
164 #if defined(sparc) || defined(__sparc)
165 #define FLUSHWIN() asm("ta 3");
166 #define FRAME_PTR_INDEX 1
167 #define SKIP_FRAMES 0
170 #if defined(i386) || defined(__i386)
172 #define FRAME_PTR_INDEX 3
173 #define SKIP_FRAMES 1
176 // TODO: Values for __x86_64 are only guesses, not tested.
177 #if defined(__x86_64)
179 #define FRAME_PTR_INDEX 7
180 #define SKIP_FRAMES 1
183 #if defined(ppc) || defined(__ppc)
185 #define FRAME_PTR_INDEX 0
186 #define SKIP_FRAMES 2
193 this function walks up call stack, calling user-supplied
194 function once for each stack frame, passing the pc and the user-supplied
195 usrarg as the argument.
198 int cs_operate(int (*func
)(void *, void *), void * usrarg
)
210 sp
= (struct frame
*) iptr
[FRAME_PTR_INDEX
];
212 for(i
=0;i
<SKIP_FRAMES
&& sp
;i
++)
213 sp
= (struct frame
*) sp
->fr_savfp
;
217 while(sp
&& sp
->fr_savpc
&& ++i
&& (*func
)((void*)sp
->fr_savpc
, usrarg
)) {
218 sp
= (struct frame
*) sp
->fr_savfp
;
224 void print_my_stack()
226 int print_address(void *, void *);
227 cs_operate(print_address
, NULL
);
230 int print_address(void *pc
, void * usrarg
)
236 if(dladdr(pc
, & info
) == 0) {
241 lib
= info
.dli_fname
;
242 func
= info
.dli_sname
;
245 size_t len
= strlen(lib
);
246 for (--len
; len
> 0; --len
) {
247 if (lib
[len
] == '/') break;
249 if (len
> 0) lib
+= ++len
;
252 char *demangled
= abi::__cxa_demangle(func
, NULL
, 0, &status
);
253 if (status
== 0) func
= demangled
;
255 if (TTCN_Logger::is_logger_up()) {
256 TTCN_Logger::log_event("%s:%s+%p\n",
259 (void *)((uintptr_t)pc
- (uintptr_t)info
.dli_saddr
)
263 fprintf(stderr
, "%s:%s+%p\n",
266 (void *)((uintptr_t)pc
- (uintptr_t)info
.dli_saddr
)
270 if (status
== 0) free(demangled
);
274 void where_am_i(TTCN_Logger::Severity sev
= TTCN_Logger::USER_UNQUALIFIED
)
276 TTCN_Logger::begin_event(sev
);
278 TTCN_Logger::end_event();
283 void where_am_i(TTCN_Logger::Severity
/*sev*/ = TTCN_Logger::USER_UNQUALIFIED
)
285 // You are on your own
290 TTCN_Error::~TTCN_Error()
296 void TTCN_error(const char *err_msg
, ...)
298 if (TTCN_Runtime::is_in_ttcn_try_block()) {
299 // Add location data as if it were logged
300 char* error_str
= TTCN_Location::print_location(
301 TTCN_Logger::SINFO_STACK
== TTCN_Logger::get_source_info_format(),
302 TTCN_Logger::SINFO_NONE
!= TTCN_Logger::get_source_info_format(),
303 TTCN_Logger::get_log_entity_name());
305 error_str
= mputstr(error_str
, " ");
307 error_str
= mputstr(error_str
, "Dynamic test case error: ");
309 va_start(p_var
, err_msg
);
310 error_str
= mputprintf_va_list(error_str
, err_msg
, p_var
);
312 throw TTCN_Error(error_str
);
314 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
315 if (TTCN_Logger::SINFO_NONE
== TTCN_Logger::get_source_info_format())
317 //Always print some location info in case of dynamic testcase error
318 char * loc
= TTCN_Location::print_location(false, true, false);
320 TTCN_Logger::log_event_str(loc
);
321 TTCN_Logger::log_event_str(": ");
325 TTCN_Logger::log_event_str("Dynamic test case error: ");
327 va_start(p_var
, err_msg
);
328 TTCN_Logger::log_event_va_list(err_msg
, p_var
);
330 TTCN_Logger::OS_error();
331 TTCN_Logger::end_event();
333 // the current implementation of the stack trace printout is misleading and cause more
334 // trouble and misunderstanding than it solves
335 // So it disabled in production compilation
336 // It remains active in debug compilation
337 where_am_i(TTCN_Logger::ERROR_UNQUALIFIED
);
339 TTCN_Runtime::set_error_verdict();
340 TTCN_Logger::log_executor_runtime(
341 TitanLoggerApi::ExecutorRuntime_reason::performing__error__recovery
);
346 void TTCN_error_begin(const char *err_msg
, ...)
348 if (TTCN_Runtime::is_in_ttcn_try_block()) {
349 TTCN_Logger::begin_event_log2str();
350 // Add location data as if it were logged
351 char* loc
= TTCN_Location::print_location(
352 TTCN_Logger::SINFO_STACK
== TTCN_Logger::get_source_info_format(),
353 TTCN_Logger::SINFO_NONE
!= TTCN_Logger::get_source_info_format(),
354 TTCN_Logger::get_log_entity_name());
356 TTCN_Logger::log_event_str(loc
);
357 TTCN_Logger::log_event_str(" ");
360 TTCN_Logger::log_event_str("Dynamic test case error: ");
362 va_start(p_var
, err_msg
);
363 TTCN_Logger::log_event_va_list(err_msg
, p_var
);
366 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
367 TTCN_Logger::log_event_str("Dynamic test case error: ");
369 va_start(p_var
, err_msg
);
370 TTCN_Logger::log_event_va_list(err_msg
, p_var
);
375 void TTCN_error_end()
377 if (TTCN_Runtime::is_in_ttcn_try_block()) {
378 CHARSTRING error_str
= TTCN_Logger::end_event_log2str();
379 throw TTCN_Error(mcopystr((const char*)error_str
));
381 TTCN_Logger::OS_error();
382 TTCN_Logger::end_event();
383 TTCN_Runtime::set_error_verdict();
384 TTCN_Logger::log_executor_runtime(
385 TitanLoggerApi::ExecutorRuntime_reason::performing__error__recovery
);
390 void TTCN_warning(const char *warning_msg
, ...)
392 TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED
);
393 TTCN_Logger::log_event_str("Warning: ");
395 va_start(p_var
, warning_msg
);
396 TTCN_Logger::log_event_va_list(warning_msg
, p_var
);
398 TTCN_Logger::end_event();
401 void TTCN_warning_begin(const char *warning_msg
, ...)
403 TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED
);
404 TTCN_Logger::log_event_str("Warning: ");
406 va_start(p_var
, warning_msg
);
407 TTCN_Logger::log_event_va_list(warning_msg
, p_var
);
411 void TTCN_warning_end()
413 TTCN_Logger::end_event();
416 void TTCN_pattern_error(const char *error_msg
, ...)
419 va_start(p_var
, error_msg
);
420 char *error_str
= mprintf_va_list(error_msg
, p_var
);
423 TTCN_error("Charstring pattern: %s", error_str
);
430 void TTCN_pattern_warning(const char *warning_msg
, ...)
433 va_start(p_var
, warning_msg
);
434 char *warning_str
= mprintf_va_list(warning_msg
, p_var
);
436 TTCN_warning("Charstring pattern: %s", warning_str
);