conformance_test/positive_tests added
[deliverable/titan.core.git] / core / Error.cc
CommitLineData
d44e3c4f 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
7 *
8 * Contributors:
9 * Balasko, Jeno
10 * Baranyi, Botond
11 * Beres, Szabolcs
12 * Delic, Adam
13 * Forstner, Matyas
14 * Herrlin, Thomas
15 * Raduly, Csaba
16 * Szabados, Kristof
17 * Szabo, Janos Zoltan – initial implementation
18 * Szalai, Gabor
19 *
20 ******************************************************************************/
970ed795
EL
21#include "Error.hh"
22#include "TitanLoggerApi.hh"
23
24#include <stdarg.h>
3abe9331 25#include <stdint.h>
970ed795
EL
26
27#include "../common/memory.h"
28#include "Logger.hh"
29#include "Runtime.hh"
30#include "Charstring.hh"
31
32#ifdef LINUX
33#include <ucontext.h>
34#include <dlfcn.h>
35#include <execinfo.h>
36
37#ifndef NO_CPP_DEMANGLE
38#include <cxxabi.h>
39using namespace __cxxabiv1;
40#endif
41
42#endif
43
44#ifdef LINUX
45
46const size_t MAX_DEPTH=100;
47
48void stacktrace(const ucontext_t& ctx)
49{
50 TTCN_Logger::log_event_str("\nStack trace:\n");
51
52 (void)ctx;
53 void *array[MAX_DEPTH];
54 size_t size;
55 char **strings;
56 size_t i;
57
58 size = backtrace (array, MAX_DEPTH);
59 strings = backtrace_symbols (array, size);
60
61 //printf ("Obtained %lu stack frames.\n", (unsigned long)size);
62
63 for (i = 0; i < size; i++) {
64 const char * symname = strings[i];
65
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) {
70 if (*j == '(')
71 begin = j+1;
72 else if (*j == '+')
73 end = j;
74 }
75
76 char *dem = 0;
77 if (begin && end) {
78 size_t len = end - begin;
79 char *mangled = (char*)malloc(len + 1);
80 memcpy(mangled, begin, len);
81 mangled[len] = '\0';
82
83 int status;
84 dem = __cxa_demangle(mangled, NULL, 0, &status);
85
86 if(status == 0 && dem)
87 symname = dem;
88 }
89
90 if (TTCN_Logger::is_logger_up()) {
91 TTCN_Logger::log_event ("%2lu: %s%s\n", (unsigned long)i, symname, (end ? end : ""));
92 }
93 else {
94 fprintf (stderr, "%2lu: %s%s\n", (unsigned long)i, symname, (end ? end : ""));
95 }
96
97 if (dem)
98 free(dem);
99 }
100
101 free (strings);
102}
103
104void where_am_i(TTCN_Logger::Severity sev = TTCN_Logger::USER_UNQUALIFIED)
105{
106 ucontext_t uc;
107 int er = getcontext(&uc);
108 if (!er) {
109 TTCN_Logger::begin_event(sev);
110 stacktrace(uc);
111 TTCN_Logger::end_event();
112 }
113 else {
114 perror("getcontext");
115 }
116}
117
118
119static 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);
127
128 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
129 stacktrace(*ucontext);
130 TTCN_Logger::end_event();
131
132 fprintf(stderr, "\nGoodbye, cruel world!\n");
133 exit(-1);
134}
135
136int 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) {
142 perror("sigaction");
143 return 0;
144 }
145 return 1;
146}
147
148static void __attribute((constructor)) init(void) {
149 setup_sigsegv();
150}
151
152#elif defined(SOLARIS) || defined(SOLARIS8)
153
154/*
155 walks up call stack, printing library:routine+offset for each routine
156 */
157
158#include <dlfcn.h>
159#include <setjmp.h>
160#include<sys/types.h>
161#include <sys/reg.h>
162#include <sys/frame.h>
163
164#if defined(sparc) || defined(__sparc)
165#define FLUSHWIN() asm("ta 3");
166#define FRAME_PTR_INDEX 1
167#define SKIP_FRAMES 0
168#endif
169
170#if defined(i386) || defined(__i386)
171#define FLUSHWIN()
172#define FRAME_PTR_INDEX 3
173#define SKIP_FRAMES 1
174#endif
175
176#if defined(ppc) || defined(__ppc)
177#define FLUSHWIN()
178#define FRAME_PTR_INDEX 0
179#define SKIP_FRAMES 2
180#endif
181
182#include <cxxabi.h>
183
184
185/*
186 this function walks up call stack, calling user-supplied
187 function once for each stack frame, passing the pc and the user-supplied
188 usrarg as the argument.
189 */
190
191int cs_operate(int (*func)(void *, void *), void * usrarg)
192{
193 struct frame *sp;
194 jmp_buf env;
195 int i;
196 int * iptr;
197
198 FLUSHWIN();
199
200 setjmp(env);
201 iptr = (int*) env;
202
203 sp = (struct frame *) iptr[FRAME_PTR_INDEX];
204
205 for(i=0;i<SKIP_FRAMES && sp;i++)
206 sp = (struct frame*) sp->fr_savfp;
207
208 i = 0;
209
210 while(sp && sp->fr_savpc && ++i && (*func)((void*)sp->fr_savpc, usrarg)) {
211 sp = (struct frame*) sp->fr_savfp;
212 }
213
214 return(i);
215}
216
217void print_my_stack()
218{
219 int print_address(void *, void *);
220 cs_operate(print_address, NULL);
221}
222
223int print_address(void *pc, void * usrarg)
224{
225 Dl_info info;
226 const char * func;
227 const char * lib;
228
229 if(dladdr(pc, & info) == 0) {
230 func = "??";
231 lib = "??";
232 }
233 else {
234 lib = info.dli_fname;
235 func = info.dli_sname;
236 }
237
238 size_t len = strlen(lib);
239 for (--len; len > 0; --len) {
240 if (lib[len] == '/') break;
241 }
242 if (len > 0) lib += ++len;
243
244 int status = 42;
245 char *demangled = abi::__cxa_demangle(func, NULL, 0, &status);
246 if (status == 0) func = demangled;
247
248 if (TTCN_Logger::is_logger_up()) {
3abe9331 249 TTCN_Logger::log_event("%s:%s+%p\n",
970ed795
EL
250 lib,
251 func,
3abe9331 252 (void *)((uintptr_t)pc - (uintptr_t)info.dli_saddr)
253 );
970ed795
EL
254 }
255 else {
3abe9331 256 fprintf(stderr, "%s:%s+%p\n",
970ed795
EL
257 lib,
258 func,
3abe9331 259 (void *)((uintptr_t)pc - (uintptr_t)info.dli_saddr)
260 );
970ed795
EL
261 }
262
263 if (status == 0) free(demangled);
264 return(1);
265}
266
267void where_am_i(TTCN_Logger::Severity sev = TTCN_Logger::USER_UNQUALIFIED)
268{
269 TTCN_Logger::begin_event(sev);
270 print_my_stack();
271 TTCN_Logger::end_event();
272}
273
274#else
275
276void where_am_i(TTCN_Logger::Severity /*sev*/ = TTCN_Logger::USER_UNQUALIFIED)
277{
278 // You are on your own
279}
280#endif // LINUX
281
282
283TTCN_Error::~TTCN_Error()
284{
285 Free(error_msg);
286}
287
288
289void TTCN_error(const char *err_msg, ...)
290{
291 if (TTCN_Runtime::is_in_ttcn_try_block()) {
292 // Add location data as if it were logged
293 char* error_str = TTCN_Location::print_location(
294 TTCN_Logger::SINFO_STACK == TTCN_Logger::get_source_info_format(),
295 TTCN_Logger::SINFO_NONE != TTCN_Logger::get_source_info_format(),
296 TTCN_Logger::get_log_entity_name());
297 if (error_str) {
298 error_str = mputstr(error_str, " ");
299 }
300 error_str = mputstr(error_str, "Dynamic test case error: ");
301 va_list p_var;
302 va_start(p_var, err_msg);
303 error_str = mputprintf_va_list(error_str, err_msg, p_var);
304 va_end(p_var);
305 throw TTCN_Error(error_str);
306 } else {
307 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
308 if (TTCN_Logger::SINFO_NONE == TTCN_Logger::get_source_info_format())
309 {
310 //Always print some location info in case of dynamic testcase error
311 char * loc = TTCN_Location::print_location(false, true, false);
312 if (loc) {
313 TTCN_Logger::log_event_str(loc);
314 TTCN_Logger::log_event_str(": ");
315 Free(loc);
316 }
317 }
318 TTCN_Logger::log_event_str("Dynamic test case error: ");
319 va_list p_var;
320 va_start(p_var, err_msg);
321 TTCN_Logger::log_event_va_list(err_msg, p_var);
322 va_end(p_var);
323 TTCN_Logger::OS_error();
324 TTCN_Logger::end_event();
325#ifndef NDEBUG
326// the current implementation of the stack trace printout is misleading and cause more
327// trouble and misunderstanding than it solves
328// So it disabled in production compilation
329// It remains active in debug compilation
330 where_am_i(TTCN_Logger::ERROR_UNQUALIFIED);
331#endif
332 TTCN_Runtime::set_error_verdict();
333 TTCN_Logger::log_executor_runtime(
334 TitanLoggerApi::ExecutorRuntime_reason::performing__error__recovery);
335 throw TC_Error();
336 }
337}
338
339void TTCN_error_begin(const char *err_msg, ...)
340{
341 if (TTCN_Runtime::is_in_ttcn_try_block()) {
342 TTCN_Logger::begin_event_log2str();
343 // Add location data as if it were logged
344 char* loc = TTCN_Location::print_location(
345 TTCN_Logger::SINFO_STACK == TTCN_Logger::get_source_info_format(),
346 TTCN_Logger::SINFO_NONE != TTCN_Logger::get_source_info_format(),
347 TTCN_Logger::get_log_entity_name());
348 if (loc) {
349 TTCN_Logger::log_event_str(loc);
350 TTCN_Logger::log_event_str(" ");
351 Free(loc);
352 }
353 TTCN_Logger::log_event_str("Dynamic test case error: ");
354 va_list p_var;
355 va_start(p_var, err_msg);
356 TTCN_Logger::log_event_va_list(err_msg, p_var);
357 va_end(p_var);
358 } else {
359 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
360 TTCN_Logger::log_event_str("Dynamic test case error: ");
361 va_list p_var;
362 va_start(p_var, err_msg);
363 TTCN_Logger::log_event_va_list(err_msg, p_var);
364 va_end(p_var);
365 }
366}
367
368void TTCN_error_end()
369{
370 if (TTCN_Runtime::is_in_ttcn_try_block()) {
371 CHARSTRING error_str = TTCN_Logger::end_event_log2str();
372 throw TTCN_Error(mcopystr((const char*)error_str));
373 } else {
374 TTCN_Logger::OS_error();
375 TTCN_Logger::end_event();
376 TTCN_Runtime::set_error_verdict();
377 TTCN_Logger::log_executor_runtime(
378 TitanLoggerApi::ExecutorRuntime_reason::performing__error__recovery);
379 throw TC_Error();
380 }
381}
382
383void TTCN_warning(const char *warning_msg, ...)
384{
385 TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED);
386 TTCN_Logger::log_event_str("Warning: ");
387 va_list p_var;
388 va_start(p_var, warning_msg);
389 TTCN_Logger::log_event_va_list(warning_msg, p_var);
390 va_end(p_var);
391 TTCN_Logger::end_event();
392}
393
394void TTCN_warning_begin(const char *warning_msg, ...)
395{
396 TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED);
397 TTCN_Logger::log_event_str("Warning: ");
398 va_list p_var;
399 va_start(p_var, warning_msg);
400 TTCN_Logger::log_event_va_list(warning_msg, p_var);
401 va_end(p_var);
402}
403
404void TTCN_warning_end()
405{
406 TTCN_Logger::end_event();
407}
408
409void TTCN_pattern_error(const char *error_msg, ...)
410{
411 va_list p_var;
412 va_start(p_var, error_msg);
413 char *error_str = mprintf_va_list(error_msg, p_var);
414 va_end(p_var);
415 try {
416 TTCN_error("Charstring pattern: %s", error_str);
417 } catch (...) {
418 Free(error_str);
419 throw;
420 }
421}
422
423void TTCN_pattern_warning(const char *warning_msg, ...)
424{
425 va_list p_var;
426 va_start(p_var, warning_msg);
427 char *warning_str = mprintf_va_list(warning_msg, p_var);
428 va_end(p_var);
429 TTCN_warning("Charstring pattern: %s", warning_str);
430 Free(warning_str);
431}
This page took 0.038106 seconds and 5 git commands to generate.