3 /* ex - Exception Handling (modified to fit into SimGrid from OSSP version) */
5 /* Copyright (c) 2005, 2006, 2007 Martin Quinson */
6 /* Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com> */
7 /* Copyright (c) 2002-2004 The OSSP Project <http://www.ossp.org/> */
8 /* Copyright (c) 2002-2004 Cable & Wireless <http://www.cw.com/> */
9 /* All rights reserved. */
11 /* This program is free software; you can redistribute it and/or modify it
12 * under the terms of the license (GNU LGPL) which comes with this package. */
17 #include "portable.h" /* execinfo when available */
20 #include "xbt/module.h" /* xbt_binary_name */
21 #include "xbt/synchro.h" /* xbt_thread_self */
23 #include "gras/Virtu/virtu_interface.h" /* gras_os_myname */
24 #include "xbt/ex_interface.h"
26 #if (defined(WIN32) && defined(_M_IX86))
30 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ex,xbt,"Exception mecanism");
32 #if (defined(WIN32) && defined(_M_IX86))
35 * Win32 (x86) implementation backtrace, backtrace_symbols, backtrace_symbols_fd
36 * : support for application self-debugging.
39 /* Pointer function to SymInitialize() */
40 typedef BOOL (WINAPI *xbt_pfn_sym_initialize_t)(HANDLE, PSTR , BOOL);
42 /* Pointer function to SymCleanup() */
43 typedef BOOL (WINAPI *xbt_pfn_sym_cleanup_t)(HANDLE hProcess);
45 /* Pointer function to SymFunctionTableAccess() */
46 typedef PVOID (WINAPI *xbt_pfn_sym_function_table_access_t)(HANDLE, DWORD);
48 /* Pointer function to SymGetLineFromAddr() */
49 typedef BOOL (WINAPI *xbt_pfn_sym_get_line_from_addr_t)(HANDLE, DWORD, PDWORD , PIMAGEHLP_LINE);
51 /* Pointer function to SymGetModuleBase() */
52 typedef DWORD (WINAPI *xbt_pfn_sym_get_module_base_t)(HANDLE,DWORD);
54 /* Pointer function to SymGetOptions() */
55 typedef DWORD (WINAPI *xbt_pfn_sym_get_options_t)(VOID);
57 /* Pointer function to SymGetSymFromAddr() */
58 typedef BOOL (WINAPI *xbt_pfn_sym_get_sym_from_addr_t)(HANDLE, DWORD, PDWORD , OUT PIMAGEHLP_SYMBOL);
60 /* Pointer function to SymSetOptions() */
61 typedef DWORD (WINAPI *xbt_pfn_sym_set_options_t)(DWORD);
63 /* Pointer function to StackWalk() */
64 typedef BOOL (WINAPI *xbt_pfn_stack_walk_t)(DWORD, HANDLE, HANDLE ,LPSTACKFRAME, PVOID,PREAD_PROCESS_MEMORY_ROUTINE, PFUNCTION_TABLE_ACCESS_ROUTINE, PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE);
66 /* This structure representes the debug_help library used interface */
67 typedef struct s_xbt_debug_help
70 HANDLE process_handle;
71 xbt_pfn_sym_initialize_t sym_initialize;
72 xbt_pfn_sym_cleanup_t sym_cleanup;
73 xbt_pfn_sym_function_table_access_t sym_function_table_access;
74 xbt_pfn_sym_get_line_from_addr_t sym_get_line_from_addr;
75 xbt_pfn_sym_get_module_base_t sym_get_module_base;
76 xbt_pfn_sym_get_options_t sym_get_options;
77 xbt_pfn_sym_get_sym_from_addr_t sym_get_sym_from_addr;
78 xbt_pfn_sym_set_options_t sym_set_options;
79 xbt_pfn_stack_walk_t stack_walk;
80 }s_xbt_debug_hlp_t,* xbt_debug_hlp_t;
83 /* the address to the unique reference to the debug help library interface */
84 static xbt_debug_hlp_t
87 /* initialize the debug help library */
89 dbg_hlp_init(HANDLE process_handle);
91 /* finalize the debug help library */
93 dbg_hlp_finalize(void);
96 * backtrace() function.
98 * Returns a backtrace for the calling program, in the array
99 * pointed to by buffer. A backtrace is the series of currently active
100 * function calls for the program. Each item in the array pointed to by
101 * buffer is of type void *, and is the return address from the corre-
102 * sponding stack frame. The size argument specifies the maximum number
103 * of addresses that can be stored in buffer. If the backtrace is larger
104 * than size, then the addresses corresponding to the size most recent
105 * function calls are returned; to obtain the complete backtrace, make
106 * sure that buffer and size are large enough.
110 backtrace (void **buffer, int size);
113 * backtrace_symbols() function.
115 * Given the set of addresses returned by backtrace() in buffer, back-
116 * trace_symbols() translates the addresses into an array of strings containing
117 * the name, the source file and the line number or the las called functions.
120 backtrace_symbols (void *const *buffer, int size);
123 * backtrace_symbols_fd() function.
125 * Same as backtrace_symbols() function but, the the array of strings is wrotten
126 * in a file (fd is the file descriptor of this file)
129 backtrace_symbols_fd(void *const *buffer, int size, int fd);
132 /* default __ex_ctx callback function */
133 ex_ctx_t *__xbt_ex_ctx_default(void) {
134 /* Don't scream: this is a default which is never used (so, yes,
135 there is one setjump container by running entity).
137 This default gets overriden in xbt/xbt_os_thread.c so that it works in
138 real life and in simulation when using threads to implement the simulation
139 processes (ie, with pthreads and on windows).
141 It also gets overriden in xbt/context.c when using ucontextes (as well as
142 in Java for now, but after the java overhaul, it will get cleaned out)
144 static ex_ctx_t ctx = XBT_CTX_INITIALIZER;
149 /* Change raw libc symbols to file names and line numbers */
150 void xbt_ex_setup_backtrace(xbt_ex_t *e);
152 void xbt_backtrace_current(xbt_ex_t *e) {
153 #if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE) || (defined(WIN32) && defined(_M_IX86))
154 e->used = backtrace((void**)e->bt,XBT_BACKTRACE_SIZE);
155 e->bt_strings = NULL;
156 xbt_ex_setup_backtrace(e);
160 void xbt_backtrace_display(xbt_ex_t *e) {
161 #if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE) || (defined(WIN32) && defined(_M_IX86))
165 fprintf(stderr,"(backtrace not set)\n");
167 fprintf(stderr,"Backtrace (displayed in thread %p):\n",
168 (void*)xbt_thread_self());
169 for (i=1; i<e->used; i++) /* no need to display "xbt_display_backtrace" */
170 fprintf(stderr,"---> %s\n",e->bt_strings[i] +4);
173 /* don't fool xbt_ex_free with uninitialized msg field */
179 ERROR0("No backtrace on this arch");
183 /** \brief show the backtrace of the current point (lovely while debuging) */
184 void xbt_backtrace_display_current(void) {
186 xbt_backtrace_current(&e);
187 xbt_backtrace_display(&e);
191 extern char **environ; /* the environment, as specified by the opengroup */
194 void xbt_ex_setup_backtrace(xbt_ex_t *e) {
195 #if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
197 /* to get the backtrace from the libc */
198 char **backtrace = backtrace_symbols (e->bt, e->used);
200 /* To build the commandline of addr2line */
203 /* to extract the addresses from the backtrace */
204 char **addrs=xbt_new(char*,e->used);
207 /* To read the output of addr2line */
209 char line_func[1024],line_pos[1024];
211 /* size (in char) of pointers on this arch */
214 /* To search for the right executable path when not trivial */
215 struct stat stat_buf;
216 char *binary_name = NULL;
218 /* Some arches only have stubs of backtrace, no implementation (hppa comes to mind) */
222 /* build the commandline */
223 if (stat(xbt_binary_name,&stat_buf)) {
224 /* Damn. binary not in current dir. We'll have to dig the PATH to find it */
226 for (i=0; environ[i]; i++) {
227 if (!strncmp("PATH=",environ[i], 5)) {
228 xbt_dynar_t path=xbt_str_split(environ[i] + 5, ":");
231 xbt_dynar_foreach(path, cpt, data) {
234 binary_name = bprintf("%s/%s",data,xbt_binary_name);
235 if (!stat(binary_name,&stat_buf)) {
237 DEBUG1("Looked in the PATH for the binary. Found %s",binary_name);
238 xbt_dynar_free(&path);
242 if (stat(binary_name,&stat_buf)) {
245 e->bt_strings = xbt_new(char*,1);
246 e->bt_strings[0] = bprintf("(binary '%s' not found the path)",xbt_binary_name);
249 xbt_dynar_free(&path);
254 binary_name = xbt_strdup(xbt_binary_name);
256 cmd = curr = xbt_new(char,strlen(ADDR2LINE)+25+strlen(binary_name)+32*e->used);
258 curr += sprintf(curr,"%s -f -e %s ",ADDR2LINE,binary_name);
261 for (i=0; i<e->used;i++) {
262 /* retrieve this address */
263 DEBUG2("Retrieving address number %d from '%s'", i, backtrace[i]);
264 snprintf(buff,256,"%s",strchr(backtrace[i],'[')+1);
267 if (strcmp(buff,"(nil)"))
268 addrs[i]=bprintf("%s", buff);
270 addrs[i]=bprintf("0x0");
271 DEBUG3("Set up a new address: %d, '%s'(%p)", i, addrs[i], addrs[i]);
273 /* Add it to the command line args */
274 curr+=sprintf(curr,"%s ",addrs[i]);
276 addr_len = strlen(addrs[0]);
278 /* parse the output and build a new backtrace */
279 e->bt_strings = xbt_new(char*,e->used);
281 VERB1("Fire a first command: '%s'", cmd);
282 pipe = popen(cmd, "r");
284 CRITICAL0("Cannot fork addr2line to display the backtrace");
288 for (i=0; i<e->used; i++) {
289 DEBUG2("Looking for symbol %d, addr = '%s'", i, addrs[i]);
290 fgets(line_func,1024,pipe);
291 line_func[strlen(line_func)-1]='\0';
292 fgets(line_pos,1024,pipe);
293 line_pos[strlen(line_pos)-1]='\0';
295 if (strcmp("??",line_func)) {
296 DEBUG2("Found static symbol %s() at %s", line_func, line_pos);
297 e->bt_strings[i] = bprintf("** In %s() at %s", line_func,line_pos);
299 /* Damn. The symbol is in a dynamic library. Let's get wild */
304 long int addr,offset=0;
311 /* let's look for the offset of this library in our addressing space */
312 maps_name=bprintf("/proc/%d/maps",(int)getpid());
313 maps=fopen(maps_name,"r");
315 sscanf(addrs[i],"%lx",&addr);
316 sprintf(maps_buff,"%#lx",addr);
318 if (strcmp(addrs[i],maps_buff)) {
319 CRITICAL2("Cannot parse backtrace address '%s' (addr=%#lx)",
322 DEBUG2("addr=%s (as string) =%#lx (as number)",addrs[i],addr);
325 long int first, last;
326 if (fgets(maps_buff,512,maps) == NULL)
329 maps_buff[strlen(maps_buff) -1]='\0';
330 DEBUG1("map line: %s", maps_buff);
332 sscanf(maps_buff,"%lx",&first);
333 p=strchr(maps_buff,'-')+1;
334 sscanf(p,"%lx",&last);
335 if (first < addr && addr < last) {
340 DEBUG3("%#lx in [%#lx-%#lx]", addr, first,last);
341 DEBUG0("Symbol found, map lines not further displayed (even if looking for next ones)");
348 VERB0("Problem while reading the maps file. Following backtrace will be mangled.");
349 DEBUG1("No dynamic. Static symbol: %s", backtrace[i]);
350 e->bt_strings[i] = bprintf("** In ?? (%s)", backtrace[i]);
354 /* Ok, Found the offset of the maps line containing the searched symbol.
355 We now need to substract this from the address we got from backtrace.
359 addrs[i] = bprintf("0x%0*lx",addr_len-2,addr-offset);
360 DEBUG2("offset=%#lx new addr=%s",offset,addrs[i]);
362 /* Got it. We have our new address. Let's get the library path and we
364 p = xbt_strdup(backtrace[i]);
366 /* library path not displayed in the map file either... */
368 sprintf(line_func,"??");
375 /* Here we go, fire an addr2line up */
376 subcmd = bprintf("%s -f -e %s %s",ADDR2LINE,p, addrs[i]);
378 VERB1("Fire a new command: '%s'",subcmd);
379 subpipe = popen(subcmd,"r");
381 CRITICAL0("Cannot fork addr2line to display the backtrace");
384 fgets(line_func,1024,subpipe);
385 line_func[strlen(line_func)-1]='\0';
386 fgets(line_pos,1024,subpipe);
387 line_pos[strlen(line_pos)-1]='\0';
392 /* check whether the trick worked */
393 if (strcmp("??",line_func)) {
394 DEBUG2("Found dynamic symbol %s() at %s", line_func, line_pos);
395 e->bt_strings[i] = bprintf("** In %s() at %s", line_func,line_pos);
397 /* damn, nothing to do here. Let's print the raw address */
398 DEBUG1("Dynamic symbol not found. Raw address = %s", backtrace[i]);
399 e->bt_strings[i] = bprintf("** In ?? at %s", backtrace[i]);
405 /* Mask the bottom of the stack */
406 if (!strncmp("main",line_func,strlen("main")) ||
407 !strncmp("xbt_thread_context_wrapper",line_func,strlen("xbt_thread_context_wrapper"))) {
409 for (j=i+1; j<e->used; j++)
413 if (!strncmp("xbt_thread_context_wrapper",line_func,strlen("xbt_thread_context_wrapper"))) {
415 e->bt_strings[i] = bprintf("** (in a separate thread)");
425 #elif (defined(WIN32) && defined (_M_IX86))
427 /* to get the backtrace from the libc */
428 char **backtrace = backtrace_symbols (e->bt, e->used);
430 /* parse the output and build a new backtrace */
431 e->bt_strings = xbt_new(char*,e->used);
434 for(i=0; i<e->used; i++)
436 e->bt_strings[i] = strdup(backtrace[i]);
444 /** @brief shows an exception content and the associated stack if available */
445 void xbt_ex_display(xbt_ex_t *e) {
449 thrower = bprintf(" on host %s(%d)",e->host,e->pid);
452 "** SimGrid: UNCAUGHT EXCEPTION received on %s(%d): category: %s; value: %d\n"
454 "** Thrown by %s()%s\n",
455 gras_os_myname(),(*xbt_getpid)(),
456 xbt_ex_catname(e->category), e->value, e->msg,
457 e->procname,thrower?thrower:" in this process");
458 CRITICAL1("%s",e->msg);
463 if (!e->remote && !e->bt_strings)
464 xbt_ex_setup_backtrace(e);
466 #if (defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)) || (defined(WIN32) && defined(_M_IX86))
467 /* We have everything to build neat backtraces */
471 fprintf(stderr,"\n");
472 for (i=0; i<e->used; i++)
473 fprintf(stderr,"%s\n",e->bt_strings[i]);
477 fprintf(stderr," at %s:%d:%s (no backtrace available on that arch)\n",
478 e->file,e->line,e->func);
484 /* default __ex_terminate callback function */
485 void __xbt_ex_terminate_default(xbt_ex_t *e) {
491 /* the externally visible API */
492 XBT_EXPORT_NO_IMPORT(ex_ctx_cb_t) __xbt_ex_ctx = &__xbt_ex_ctx_default;
493 XBT_EXPORT_NO_IMPORT(ex_term_cb_t) __xbt_ex_terminate = &__xbt_ex_terminate_default;
496 void xbt_ex_free(xbt_ex_t e) {
499 if (e.msg) free(e.msg);
508 for (i=0; i<e.used; i++)
509 free((char*)e.bt_strings[i]);
510 free((char **)e.bt_strings);
512 /* memset(e,0,sizeof(xbt_ex_t)); */
515 /** \brief returns a short name for the given exception category */
516 const char * xbt_ex_catname(xbt_errcat_t cat) {
518 case unknown_error: return "unknown_err";
519 case arg_error: return "invalid_arg";
520 case mismatch_error: return "mismatch";
521 case not_found_error: return "not found";
522 case system_error: return "system_err";
523 case network_error: return "network_err";
524 case timeout_error: return "timeout";
525 case thread_error: return "thread_err";
526 default: return "INVALID_ERR";
530 #ifndef HAVE_EXECINFO_H
531 # if (defined(WIN32) && defined(_M_IX86))
533 backtrace (void **buffer, int size)
536 STACKFRAME* stack_frame;
539 CONTEXT context = {CONTEXT_FULL};
540 GetThreadContext(GetCurrentThread(), &context);
542 /* ebp pointe sur la base de la pile */
543 /* esp pointe sur le stack pointer <=> sur le dernier élément déposé dans la pile (l'élément courant) */
546 _asm mov context.Eip, eax
548 _asm mov context.Esp, eax
549 _asm mov context.Ebp, ebp
551 dbg_hlp_init(GetCurrentProcess());
553 if((NULL == dbg_hlp) || (size <= 0) || (NULL == buffer))
559 for(pos = 0; pos < size; pos++)
566 stack_frame = (void*)calloc(1,sizeof(STACKFRAME));
574 stack_frame->AddrPC.Offset = context.Eip;
575 stack_frame->AddrPC.Mode = AddrModeFlat;
577 stack_frame->AddrFrame.Offset = context.Ebp;
578 stack_frame->AddrFrame.Mode = AddrModeFlat;
580 stack_frame->AddrStack.Offset = context.Esp;
581 stack_frame->AddrStack.Mode = AddrModeFlat;
583 if((*(dbg_hlp->stack_walk))(
584 IMAGE_FILE_MACHINE_I386,
585 dbg_hlp->process_handle,
590 dbg_hlp->sym_function_table_access,
591 dbg_hlp->sym_get_module_base,
595 if(stack_frame->AddrReturn.Offset)
596 buffer[pos++] = (void*)stack_frame;
599 free(stack_frame); /* no symbol */
618 backtrace_symbols (void *const *buffer, int size)
623 STACKFRAME* stack_frame;
624 char str[MAX_SYM_NAME] = {0};
625 IMAGEHLP_SYMBOL * pSym;
626 unsigned long displacement = 0;
627 IMAGEHLP_LINE line_info = {0};
628 IMAGEHLP_MODULE module = {0};
629 byte __buffer[(sizeof(SYMBOL_INFO) +MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
631 if((NULL == dbg_hlp) || (size <= 0) || (NULL == buffer))
637 strings = (char**)calloc(size,sizeof(char*));
645 pSym = (IMAGEHLP_SYMBOL*)__buffer;
647 pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
648 pSym->MaxNameLength = MAX_SYM_NAME;
651 line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE);
652 module.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
654 for(pos = 0; pos < size; pos++)
656 stack_frame = (STACKFRAME*)(buffer[pos]);
658 if(NULL != stack_frame)
661 if((*(dbg_hlp->sym_get_sym_from_addr))(dbg_hlp->process_handle,stack_frame->AddrPC.Offset, &displacement,pSym))
663 if((*(dbg_hlp->sym_get_line_from_addr))(dbg_hlp->process_handle,stack_frame->AddrPC.Offset, &displacement,&line_info))
666 sprintf(str,"** In %s() at %s:%d", pSym->Name,line_info.FileName,line_info.LineNumber);
668 strings[pos] = strdup(str);
669 memset(str,0,MAX_SYM_NAME);
693 backtrace_symbols_fd(void *const *buffer, int size, int fd)
697 STACKFRAME* stack_frame;
698 char str[MAX_SYM_NAME] = {0};
699 IMAGEHLP_SYMBOL * pSym;
700 unsigned long displacement = 0;
701 IMAGEHLP_LINE line_info = {0};
702 IMAGEHLP_MODULE module = {0};
704 byte __buffer[(sizeof(SYMBOL_INFO) +MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
706 if((NULL == dbg_hlp) || (size <= 0) || (NULL == buffer) || (-1 == fd))
712 pSym = (IMAGEHLP_SYMBOL*)__buffer;
714 pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
715 pSym->MaxNameLength = MAX_SYM_NAME;
718 line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE);
719 module.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
721 for(pos = 0; pos < size; pos++)
723 stack_frame = (STACKFRAME*)(buffer[pos]);
725 if(NULL != stack_frame)
728 if((*(dbg_hlp->sym_get_sym_from_addr))(dbg_hlp->process_handle,stack_frame->AddrPC.Offset, &displacement,pSym))
730 if((*(dbg_hlp->sym_get_line_from_addr))(dbg_hlp->process_handle,stack_frame->AddrPC.Offset, &displacement,&line_info))
734 sprintf(str,"** In %s() at %s:%d\n", pSym->Name,line_info.FileName,line_info.LineNumber);
736 if(-1 == write(fd,str,strlen(str)))
739 memset(str,0,MAX_SYM_NAME);
756 dbg_hlp_init(HANDLE process_handle)
760 /* debug help is already loaded */
765 dbg_hlp = (xbt_debug_hlp_t)calloc(1,sizeof(s_xbt_debug_hlp_t));
770 /* load the library */
771 dbg_hlp->instance = LoadLibraryA("Dbghelp.dll");
773 if(!(dbg_hlp->instance))
777 return (int)GetLastError();
780 /* get the pointers to debug help library exported functions */
782 if(!((dbg_hlp->sym_initialize) = (xbt_pfn_sym_initialize_t)GetProcAddress(dbg_hlp->instance,"SymInitialize")))
784 FreeLibrary(dbg_hlp->instance);
787 return (int)GetLastError();
790 if(!((dbg_hlp->sym_cleanup) = (xbt_pfn_sym_cleanup_t)GetProcAddress(dbg_hlp->instance,"SymCleanup")))
792 FreeLibrary(dbg_hlp->instance);
795 return (int)GetLastError();
798 if(!((dbg_hlp->sym_function_table_access) = (xbt_pfn_sym_function_table_access_t)GetProcAddress(dbg_hlp->instance,"SymFunctionTableAccess")))
800 FreeLibrary(dbg_hlp->instance);
803 return (int)GetLastError();
806 if(!((dbg_hlp->sym_get_line_from_addr) = (xbt_pfn_sym_get_line_from_addr_t)GetProcAddress(dbg_hlp->instance,"SymGetLineFromAddr")))
808 FreeLibrary(dbg_hlp->instance);
811 return (int)GetLastError();
814 if(!((dbg_hlp->sym_get_module_base) = (xbt_pfn_sym_get_module_base_t)GetProcAddress(dbg_hlp->instance,"SymGetModuleBase")))
816 FreeLibrary(dbg_hlp->instance);
819 return (int)GetLastError();
822 if(!((dbg_hlp->sym_get_options) = (xbt_pfn_sym_get_options_t)GetProcAddress(dbg_hlp->instance,"SymGetOptions")))
824 FreeLibrary(dbg_hlp->instance);
827 return (int)GetLastError();
830 if(!((dbg_hlp->sym_get_sym_from_addr) = (xbt_pfn_sym_get_sym_from_addr_t)GetProcAddress(dbg_hlp->instance,"SymGetSymFromAddr")))
832 FreeLibrary(dbg_hlp->instance);
835 return (int)GetLastError();
838 if(!((dbg_hlp->sym_set_options) = (xbt_pfn_sym_set_options_t)GetProcAddress(dbg_hlp->instance,"SymSetOptions")))
840 FreeLibrary(dbg_hlp->instance);
843 return (int)GetLastError();
846 if(!((dbg_hlp->stack_walk) = (xbt_pfn_stack_walk_t)GetProcAddress(dbg_hlp->instance,"StackWalk")))
848 FreeLibrary(dbg_hlp->instance);
851 return (int)GetLastError();
854 dbg_hlp->process_handle = process_handle;
856 (*(dbg_hlp->sym_set_options))((*(dbg_hlp->sym_get_options))() | SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS);
858 if(!(*(dbg_hlp->sym_initialize))(dbg_hlp->process_handle,0,1))
860 FreeLibrary(dbg_hlp->instance);
863 return (int)GetLastError();
871 dbg_hlp_finalize(void)
876 if(!(*(dbg_hlp->sym_cleanup))(dbg_hlp->process_handle))
877 return (int)GetLastError();
879 if(!FreeLibrary(dbg_hlp->instance))
880 return (int)GetLastError();
889 /* dummy implementation. We won't use the result, but ex.h needs it to be defined */
890 int backtrace (void **__array, int __size) {
900 XBT_TEST_SUITE("xbt_ex","Exception Handling");
902 XBT_TEST_UNIT("controlflow",test_controlflow, "basic nested control flow") {
906 xbt_test_add0("basic nested control flow");
910 xbt_test_fail1("M1: n=%d (!= 1)", n);
914 xbt_test_fail1("M2: n=%d (!= 2)", n);
916 THROW0(unknown_error,0,"something");
919 xbt_test_fail1("M3: n=%d (!= 3)", n);
926 xbt_test_fail1("M2: n=%d (!= 5)", n);
928 THROW0(unknown_error,0,"something");
931 xbt_test_fail1("M3: n=%d (!= 6)", n);
936 xbt_test_fail1("MX: n=%d (shouldn't reach this point)", n);
940 xbt_test_fail1("M4: n=%d (!= 7)", n);
945 xbt_test_fail1("M5: n=%d (!= 8)", n);
948 XBT_TEST_UNIT("value",test_value,"exception value passing") {
952 THROW0(unknown_error, 2, "toto");
954 xbt_test_add0("exception value passing");
955 if (ex.category != unknown_error)
956 xbt_test_fail1("category=%d (!= 1)", ex.category);
958 xbt_test_fail1("value=%d (!= 2)", ex.value);
959 if (strcmp(ex.msg,"toto"))
960 xbt_test_fail1("message=%s (!= toto)", ex.msg);
965 XBT_TEST_UNIT("variables",test_variables,"variable value preservation") {
970 r1 = r2 = v1 = v2 = 1234;
974 THROW0(unknown_error, 0, "toto");
976 xbt_test_add0("variable preservation");
978 xbt_test_fail1("r1=%d (!= 1234)", r1);
980 xbt_test_fail1("v1=%d (!= 1234)", v1);
981 /* r2 is allowed to be destroyed because not volatile */
983 xbt_test_fail1("v2=%d (!= 5678)", v2);
988 XBT_TEST_UNIT("cleanup",test_cleanup,"cleanup handling") {
993 xbt_test_add0("cleanup handling");
999 THROW0(1, 2, "blah");
1002 xbt_test_fail1("v1 = %d (!= 5678)", v1);
1006 xbt_test_fail1("v1 = %d (!= 5678)", v1);
1007 if (!(ex.category == 1 && ex.value == 2 && !strcmp(ex.msg,"blah")))
1008 xbt_test_fail0("unexpected exception contents");
1012 xbt_test_fail0("xbt_ex_free not executed");
1017 * The following is the example included in the documentation. It's a good
1018 * idea to check its syntax even if we don't try to run it.
1019 * And actually, it allows to put comments in the code despite doxygen.
1021 static char *mallocex(int size) {
1024 #define SMALLAMOUNT 10
1025 #define TOOBIG 100000000
1027 #if 0 /* this contains syntax errors, actually */
1028 static void bad_example(void) {
1029 struct {char*first;} *globalcontext;
1034 char *cp1, *cp2, *cp3;
1036 cp1 = mallocex(SMALLAMOUNT);
1037 globalcontext->first = cp1;
1038 cp2 = mallocex(TOOBIG);
1039 cp3 = mallocex(SMALLAMOUNT);
1043 if (cp3 != NULL) free(cp3);
1044 if (cp2 != NULL) free(cp2);
1045 if (cp1 != NULL) free(cp1);
1047 printf("cp3=%s", cp3);
1050 /* end_of_bad_example */
1053 typedef struct {char *first;} global_context_t;
1055 static void good_example(void) {
1056 global_context_t *global_context=malloc(sizeof(global_context_t));
1061 char * volatile /*03*/ cp1 = NULL /*02*/;
1062 char * volatile /*03*/ cp2 = NULL /*02*/;
1063 char * volatile /*03*/ cp3 = NULL /*02*/;
1065 cp1 = mallocex(SMALLAMOUNT);
1066 global_context->first = cp1;
1067 cp1 = NULL /*05 give away*/;
1068 cp2 = mallocex(TOOBIG);
1069 cp3 = mallocex(SMALLAMOUNT);
1073 printf("cp3=%s", cp3 == NULL /*02*/ ? "" : cp3);
1078 /*05 cp1 was given away */
1080 /*05 global context untouched */
1084 /* end_of_good_example */
1086 #endif /* SIMGRID_TEST */