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 char **backtrace = backtrace_symbols (e->bt, e->used);
429 /* parse the output and build a new backtrace */
430 e->bt_strings = xbt_new(char*,e->used);
433 for(i=0; i<e->used; i++)
435 e->bt_strings[i] = strdup(backtrace[i]);
443 /** @brief shows an exception content and the associated stack if available */
444 void xbt_ex_display(xbt_ex_t *e) {
448 thrower = bprintf(" on host %s(%d)",e->host,e->pid);
451 "** SimGrid: UNCAUGHT EXCEPTION received on %s(%d): category: %s; value: %d\n"
453 "** Thrown by %s()%s\n",
454 gras_os_myname(),(*xbt_getpid)(),
455 xbt_ex_catname(e->category), e->value, e->msg,
456 e->procname,thrower?thrower:" in this process");
457 CRITICAL1("%s",e->msg);
462 if (!e->remote && !e->bt_strings)
463 xbt_ex_setup_backtrace(e);
465 #if (defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)) || (defined(WIN32) && defined(_M_IX86))
466 /* We have everything to build neat backtraces */
470 fprintf(stderr,"\n");
471 for (i=0; i<e->used; i++)
472 fprintf(stderr,"%s\n",e->bt_strings[i]);
476 fprintf(stderr," at %s:%d:%s (no backtrace available on that arch)\n",
477 e->file,e->line,e->func);
483 /* default __ex_terminate callback function */
484 void __xbt_ex_terminate_default(xbt_ex_t *e) {
490 /* the externally visible API */
491 XBT_EXPORT_NO_IMPORT(ex_ctx_cb_t) __xbt_ex_ctx = &__xbt_ex_ctx_default;
492 XBT_EXPORT_NO_IMPORT(ex_term_cb_t) __xbt_ex_terminate = &__xbt_ex_terminate_default;
495 void xbt_ex_free(xbt_ex_t e) {
498 if (e.msg) free(e.msg);
507 for (i=0; i<e.used; i++)
508 free((char*)e.bt_strings[i]);
509 free((char **)e.bt_strings);
511 /* memset(e,0,sizeof(xbt_ex_t)); */
514 /** \brief returns a short name for the given exception category */
515 const char * xbt_ex_catname(xbt_errcat_t cat) {
517 case unknown_error: return "unknown_err";
518 case arg_error: return "invalid_arg";
519 case mismatch_error: return "mismatch";
520 case not_found_error: return "not found";
521 case system_error: return "system_err";
522 case network_error: return "network_err";
523 case timeout_error: return "timeout";
524 case thread_error: return "thread_err";
525 default: return "INVALID_ERR";
529 #ifndef HAVE_EXECINFO_H
530 # if (defined(WIN32) && defined(_M_IX86))
532 backtrace (void **buffer, int size)
535 STACKFRAME* stack_frame;
538 IMAGEHLP_SYMBOL * pSym;
539 unsigned long displacement = 0;
540 IMAGEHLP_LINE line_info = {0};
541 byte __buffer[(sizeof(SYMBOL_INFO) +MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
543 CONTEXT context = {CONTEXT_FULL};
544 GetThreadContext(GetCurrentThread(), &context);
546 /* ebp pointe sur la base de la pile */
547 /* esp pointe sur le stack pointer <=> sur le dernier élément déposé dans la pile (l'élément courant) */
550 _asm mov context.Eip, eax
552 _asm mov context.Esp, eax
553 _asm mov context.Ebp, ebp
555 dbg_hlp_init(GetCurrentProcess());
557 if((NULL == dbg_hlp) || (size <= 0) || (NULL == buffer))
563 for(pos = 0; pos < size; pos++)
568 pSym = (IMAGEHLP_SYMBOL*)__buffer;
570 pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
571 pSym->MaxNameLength = MAX_SYM_NAME;
574 line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE);
579 stack_frame = (void*)calloc(1,sizeof(STACKFRAME));
587 stack_frame->AddrPC.Offset = context.Eip;
588 stack_frame->AddrPC.Mode = AddrModeFlat;
590 stack_frame->AddrFrame.Offset = context.Ebp;
591 stack_frame->AddrFrame.Mode = AddrModeFlat;
593 stack_frame->AddrStack.Offset = context.Esp;
594 stack_frame->AddrStack.Mode = AddrModeFlat;
596 if((*(dbg_hlp->stack_walk))(
597 IMAGE_FILE_MACHINE_I386,
598 dbg_hlp->process_handle,
603 dbg_hlp->sym_function_table_access,
604 dbg_hlp->sym_get_module_base,
608 if(stack_frame->AddrReturn.Offset)
611 if((*(dbg_hlp->sym_get_sym_from_addr))(dbg_hlp->process_handle,stack_frame->AddrPC.Offset, &displacement,pSym))
613 if((*(dbg_hlp->sym_get_line_from_addr))(dbg_hlp->process_handle,stack_frame->AddrPC.Offset, &displacement,&line_info))
614 buffer[pos++] = (void*)stack_frame;
619 free(stack_frame); /* no symbol or no line info */
638 backtrace_symbols (void *const *buffer, int size)
643 STACKFRAME* stack_frame;
644 char str[MAX_SYM_NAME] = {0};
645 IMAGEHLP_SYMBOL * pSym;
646 unsigned long displacement = 0;
647 IMAGEHLP_LINE line_info = {0};
648 IMAGEHLP_MODULE module = {0};
649 byte __buffer[(sizeof(SYMBOL_INFO) +MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
651 if((NULL == dbg_hlp) || (size <= 0) || (NULL == buffer))
657 strings = (char**)calloc(size,sizeof(char*));
665 pSym = (IMAGEHLP_SYMBOL*)__buffer;
667 pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
668 pSym->MaxNameLength = MAX_SYM_NAME;
671 line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE);
672 module.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
674 for(pos = 0; pos < size; pos++)
676 stack_frame = (STACKFRAME*)(buffer[pos]);
678 if(NULL != stack_frame)
681 if((*(dbg_hlp->sym_get_sym_from_addr))(dbg_hlp->process_handle,stack_frame->AddrPC.Offset, &displacement,pSym))
683 if((*(dbg_hlp->sym_get_line_from_addr))(dbg_hlp->process_handle,stack_frame->AddrPC.Offset, &displacement,&line_info))
686 sprintf(str,"** In %s() at %s:%d", pSym->Name,line_info.FileName,line_info.LineNumber);
688 strings[pos] = strdup(str);
689 memset(str,0,MAX_SYM_NAME);
695 strings[pos] = strdup("<no line>");
700 strings[pos] = strdup("<no symbole>");
721 backtrace_symbols_fd(void *const *buffer, int size, int fd)
725 STACKFRAME* stack_frame;
726 char str[MAX_SYM_NAME] = {0};
727 IMAGEHLP_SYMBOL * pSym;
728 unsigned long displacement = 0;
729 IMAGEHLP_LINE line_info = {0};
730 IMAGEHLP_MODULE module = {0};
732 byte __buffer[(sizeof(SYMBOL_INFO) +MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
734 if((NULL == dbg_hlp) || (size <= 0) || (NULL == buffer) || (-1 == fd))
740 pSym = (IMAGEHLP_SYMBOL*)__buffer;
742 pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
743 pSym->MaxNameLength = MAX_SYM_NAME;
746 line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE);
747 module.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
749 for(pos = 0; pos < size; pos++)
751 stack_frame = (STACKFRAME*)(buffer[pos]);
753 if(NULL != stack_frame)
756 if((*(dbg_hlp->sym_get_sym_from_addr))(dbg_hlp->process_handle,stack_frame->AddrPC.Offset, &displacement,pSym))
758 if((*(dbg_hlp->sym_get_line_from_addr))(dbg_hlp->process_handle,stack_frame->AddrPC.Offset, &displacement,&line_info))
762 sprintf(str,"** In %s() at %s:%d\n", pSym->Name,line_info.FileName,line_info.LineNumber);
764 if(-1 == write(fd,str,strlen(str)))
767 memset(str,0,MAX_SYM_NAME);
784 dbg_hlp_init(HANDLE process_handle)
788 /* debug help is already loaded */
793 dbg_hlp = (xbt_debug_hlp_t)calloc(1,sizeof(s_xbt_debug_hlp_t));
798 /* load the library */
799 dbg_hlp->instance = LoadLibraryA("Dbghelp.dll");
801 if(!(dbg_hlp->instance))
805 return (int)GetLastError();
808 /* get the pointers to debug help library exported functions */
810 if(!((dbg_hlp->sym_initialize) = (xbt_pfn_sym_initialize_t)GetProcAddress(dbg_hlp->instance,"SymInitialize")))
812 FreeLibrary(dbg_hlp->instance);
815 return (int)GetLastError();
818 if(!((dbg_hlp->sym_cleanup) = (xbt_pfn_sym_cleanup_t)GetProcAddress(dbg_hlp->instance,"SymCleanup")))
820 FreeLibrary(dbg_hlp->instance);
823 return (int)GetLastError();
826 if(!((dbg_hlp->sym_function_table_access) = (xbt_pfn_sym_function_table_access_t)GetProcAddress(dbg_hlp->instance,"SymFunctionTableAccess")))
828 FreeLibrary(dbg_hlp->instance);
831 return (int)GetLastError();
834 if(!((dbg_hlp->sym_get_line_from_addr) = (xbt_pfn_sym_get_line_from_addr_t)GetProcAddress(dbg_hlp->instance,"SymGetLineFromAddr")))
836 FreeLibrary(dbg_hlp->instance);
839 return (int)GetLastError();
842 if(!((dbg_hlp->sym_get_module_base) = (xbt_pfn_sym_get_module_base_t)GetProcAddress(dbg_hlp->instance,"SymGetModuleBase")))
844 FreeLibrary(dbg_hlp->instance);
847 return (int)GetLastError();
850 if(!((dbg_hlp->sym_get_options) = (xbt_pfn_sym_get_options_t)GetProcAddress(dbg_hlp->instance,"SymGetOptions")))
852 FreeLibrary(dbg_hlp->instance);
855 return (int)GetLastError();
858 if(!((dbg_hlp->sym_get_sym_from_addr) = (xbt_pfn_sym_get_sym_from_addr_t)GetProcAddress(dbg_hlp->instance,"SymGetSymFromAddr")))
860 FreeLibrary(dbg_hlp->instance);
863 return (int)GetLastError();
866 if(!((dbg_hlp->sym_set_options) = (xbt_pfn_sym_set_options_t)GetProcAddress(dbg_hlp->instance,"SymSetOptions")))
868 FreeLibrary(dbg_hlp->instance);
871 return (int)GetLastError();
874 if(!((dbg_hlp->stack_walk) = (xbt_pfn_stack_walk_t)GetProcAddress(dbg_hlp->instance,"StackWalk")))
876 FreeLibrary(dbg_hlp->instance);
879 return (int)GetLastError();
882 dbg_hlp->process_handle = process_handle;
884 (*(dbg_hlp->sym_set_options))((*(dbg_hlp->sym_get_options))() | SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS);
886 if(!(*(dbg_hlp->sym_initialize))(dbg_hlp->process_handle,0,1))
888 FreeLibrary(dbg_hlp->instance);
891 return (int)GetLastError();
899 dbg_hlp_finalize(void)
904 if(!(*(dbg_hlp->sym_cleanup))(dbg_hlp->process_handle))
905 return (int)GetLastError();
907 if(!FreeLibrary(dbg_hlp->instance))
908 return (int)GetLastError();
917 /* dummy implementation. We won't use the result, but ex.h needs it to be defined */
918 int backtrace (void **__array, int __size) {
928 XBT_TEST_SUITE("xbt_ex","Exception Handling");
930 XBT_TEST_UNIT("controlflow",test_controlflow, "basic nested control flow") {
934 xbt_test_add0("basic nested control flow");
938 xbt_test_fail1("M1: n=%d (!= 1)", n);
942 xbt_test_fail1("M2: n=%d (!= 2)", n);
944 THROW0(unknown_error,0,"something");
947 xbt_test_fail1("M3: n=%d (!= 3)", n);
954 xbt_test_fail1("M2: n=%d (!= 5)", n);
956 THROW0(unknown_error,0,"something");
959 xbt_test_fail1("M3: n=%d (!= 6)", n);
964 xbt_test_fail1("MX: n=%d (shouldn't reach this point)", n);
968 xbt_test_fail1("M4: n=%d (!= 7)", n);
973 xbt_test_fail1("M5: n=%d (!= 8)", n);
976 XBT_TEST_UNIT("value",test_value,"exception value passing") {
980 THROW0(unknown_error, 2, "toto");
982 xbt_test_add0("exception value passing");
983 if (ex.category != unknown_error)
984 xbt_test_fail1("category=%d (!= 1)", ex.category);
986 xbt_test_fail1("value=%d (!= 2)", ex.value);
987 if (strcmp(ex.msg,"toto"))
988 xbt_test_fail1("message=%s (!= toto)", ex.msg);
993 XBT_TEST_UNIT("variables",test_variables,"variable value preservation") {
998 r1 = r2 = v1 = v2 = 1234;
1002 THROW0(unknown_error, 0, "toto");
1004 xbt_test_add0("variable preservation");
1006 xbt_test_fail1("r1=%d (!= 1234)", r1);
1008 xbt_test_fail1("v1=%d (!= 1234)", v1);
1009 /* r2 is allowed to be destroyed because not volatile */
1011 xbt_test_fail1("v2=%d (!= 5678)", v2);
1016 XBT_TEST_UNIT("cleanup",test_cleanup,"cleanup handling") {
1021 xbt_test_add0("cleanup handling");
1027 THROW0(1, 2, "blah");
1030 xbt_test_fail1("v1 = %d (!= 5678)", v1);
1034 xbt_test_fail1("v1 = %d (!= 5678)", v1);
1035 if (!(ex.category == 1 && ex.value == 2 && !strcmp(ex.msg,"blah")))
1036 xbt_test_fail0("unexpected exception contents");
1040 xbt_test_fail0("xbt_ex_free not executed");
1045 * The following is the example included in the documentation. It's a good
1046 * idea to check its syntax even if we don't try to run it.
1047 * And actually, it allows to put comments in the code despite doxygen.
1049 static char *mallocex(int size) {
1052 #define SMALLAMOUNT 10
1053 #define TOOBIG 100000000
1055 #if 0 /* this contains syntax errors, actually */
1056 static void bad_example(void) {
1057 struct {char*first;} *globalcontext;
1062 char *cp1, *cp2, *cp3;
1064 cp1 = mallocex(SMALLAMOUNT);
1065 globalcontext->first = cp1;
1066 cp2 = mallocex(TOOBIG);
1067 cp3 = mallocex(SMALLAMOUNT);
1071 if (cp3 != NULL) free(cp3);
1072 if (cp2 != NULL) free(cp2);
1073 if (cp1 != NULL) free(cp1);
1075 printf("cp3=%s", cp3);
1078 /* end_of_bad_example */
1081 typedef struct {char *first;} global_context_t;
1083 static void good_example(void) {
1084 global_context_t *global_context=malloc(sizeof(global_context_t));
1089 char * volatile /*03*/ cp1 = NULL /*02*/;
1090 char * volatile /*03*/ cp2 = NULL /*02*/;
1091 char * volatile /*03*/ cp3 = NULL /*02*/;
1093 cp1 = mallocex(SMALLAMOUNT);
1094 global_context->first = cp1;
1095 cp1 = NULL /*05 give away*/;
1096 cp2 = mallocex(TOOBIG);
1097 cp3 = mallocex(SMALLAMOUNT);
1101 printf("cp3=%s", cp3 == NULL /*02*/ ? "" : cp3);
1106 /*05 cp1 was given away */
1108 /*05 global context untouched */
1112 /* end_of_good_example */
1114 #endif /* SIMGRID_TEST */