Go to the documentation of this file.00001
00002 #include "vul_debug.h"
00003
00004
00005
00006
00007 #include <vcl_iostream.h>
00008 #include <vxl_config.h>
00009 #include <vcl_new.h>
00010 #include <vcl_cstdlib.h>
00011
00012 #ifdef _WIN32
00013
00014 #if VXL_HAS_DBGHELP_H
00015
00016 #define NOATOM
00017 #define NOGDI
00018 #define NOGDICAPMASKS
00019 #define NOMETAFILE
00020 #define NOMINMAX
00021 #define NOMSG
00022 #define NOOPENFILE
00023 #define NORASTEROPS
00024 #define NOSCROLL
00025 #define NOSOUND
00026 #define NOSYSMETRICS
00027 #define NOTEXTMETRIC
00028 #define NOWH
00029 #define NOCOMM
00030 #define NOKANJI
00031 #define NOCRYPT
00032 #define NOMCX
00033 #include <windows.h>
00034 #include <DbgHelp.h>
00035 #include <vcl_cstdio.h>
00036 #pragma comment (lib, "dbghelp")
00037
00038 static bool vul_debug_core_dump_in_windows_seh(const char * filename,
00039 EXCEPTION_POINTERS* pep)
00040 {
00041 static char buffer[2048];
00042 static int count = 0;
00043 vcl_snprintf(buffer, sizeof(buffer), filename, count++);
00044 buffer[sizeof(buffer)-1]=0;
00045
00046 HANDLE hFile = CreateFile( buffer, GENERIC_READ | GENERIC_WRITE,
00047 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
00048
00049 if ( ( hFile == NULL ) || ( hFile == INVALID_HANDLE_VALUE ) )
00050 {
00051 vcl_cerr << "WARNING: vul_debug_core_dump: Unable to create core dump file: " << filename << vcl_endl;
00052 return false;
00053 }
00054
00055 MINIDUMP_EXCEPTION_INFORMATION mdei;
00056 mdei.ThreadId = GetCurrentThreadId();
00057 mdei.ExceptionPointers = pep;
00058 mdei.ClientPointers = FALSE;
00059
00060 if (! MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
00061 hFile, MiniDumpWithFullMemory, (pep != 0) ? &mdei : 0, 0, 0 ))
00062 vcl_cerr << "WARNING: vul_debug_core_dump: Unable to dump core: " << filename << vcl_endl;
00063
00064 CloseHandle( hFile );
00065 return true;
00066 }
00067
00068 bool vul_debug_core_dump_in_windows_seh(const char * filename,
00069 void* pep)
00070 {
00071 return vul_debug_core_dump_in_windows_seh(filename, (EXCEPTION_POINTERS*)pep);
00072 }
00073
00074
00075
00076 #pragma warning (disable: 4535)
00077
00078
00079 bool vul_debug_core_dump(const char * filename)
00080 {
00081 _se_translator_function current = _set_se_translator(0);
00082
00083 __try
00084 {
00085 RaiseException(0xe0000000,0,0,0);
00086 }
00087 __except(vul_debug_core_dump_in_windows_seh(filename, GetExceptionInformation()),1)
00088 {}
00089 _set_se_translator(current);
00090 return true;
00091 }
00092
00093 #if VCL_HAS_EXCEPTIONS
00094
00095 unsigned vul_debug_windows_structured_exception::code() const
00096 {
00097 return static_cast<EXCEPTION_POINTERS*>(ex_ptr_)->ExceptionRecord->ExceptionCode;
00098 }
00099
00100
00101 void *vul_debug_windows_structured_exception::address() const
00102 {
00103 return static_cast<EXCEPTION_POINTERS*>(ex_ptr_)->ExceptionRecord->ExceptionAddress;
00104 }
00105
00106 const char *vul_debug_windows_structured_exception::what() const throw()
00107 {
00108 static char buf[100];
00109 vcl_sprintf(buf, "Caught Windows Structured Exception. Code %lx. Address %lx", code(), address());
00110 return buf;
00111 }
00112 #endif
00113
00114 static const char* se_coredump_filename = 0;
00115
00116 void vul_debug_set_coredump_and_throw_on_windows_se_handler(
00117 unsigned code, EXCEPTION_POINTERS * ex_ptr)
00118 {
00119 vul_debug_core_dump_in_windows_seh(se_coredump_filename, ex_ptr);
00120 #if VCL_HAS_EXCEPTIONS
00121 throw vul_debug_windows_structured_exception(ex_ptr);
00122 #else
00123 vcl_cerr << static_cast<char*>(ex_ptr) << '\n';
00124 vcl_abort();
00125 #endif
00126 }
00127
00128
00129
00130
00131 void vul_debug_set_coredump_and_throw_on_windows_se(const char * filename)
00132 {
00133 se_coredump_filename = filename;
00134 _set_se_translator(vul_debug_set_coredump_and_throw_on_windows_se_handler);
00135 }
00136
00137
00138 # else //VXL_HAS_DBGHELP_H
00139
00140 bool vul_debug_core_dump_in_windows_seh(const char *, void*)
00141 {
00142 vcl_cerr << "WARNING: vul_debug_core_dump_in_windows_seh: Unable to core dump\n";
00143 return false;
00144 }
00145
00146 bool vul_debug_core_dump(const char *)
00147 {
00148 vcl_cerr << "WARNING: vul_debug_core_dump: Unable to core dump\n";
00149 return false;
00150 }
00151
00152
00153 unsigned vul_debug_windows_structured_exception::code() const
00154 {
00155 return 0;
00156 }
00157
00158
00159 void *vul_debug_windows_structured_exception::address() const
00160 {
00161 return 0;
00162 }
00163
00164 const char *vul_debug_windows_structured_exception::what() const throw()
00165 {
00166 return "Caught Windows Exception on machine with old or no version of DbgHelp.";
00167 }
00168
00169
00170
00171
00172 void vul_debug_set_coredump_and_throw_on_windows_se(const char * )
00173 {
00174 vcl_cerr << "WARNING: No DbgHelp.h on this platform - can't set SE Handler.\n";
00175 }
00176
00177 # endif // VXL_HAS_DBGHELP_H
00178
00179
00180 #else // _WIN32
00181
00182 #include <vcl_string.h>
00183 #ifdef VXL_UNISTD_HAS_GETPID
00184 # include <unistd.h>
00185 #endif
00186 #include <vul/vul_sprintf.h>
00187
00188 bool vul_debug_core_dump(const char * filename)
00189 {
00190 static int count = 0;
00191 #ifdef VXL_UNISTD_HAS_GETPID
00192 vcl_string syscall = "gcore -o ";
00193 syscall += vul_sprintf(filename, count++);
00194 syscall += vul_sprintf(" %d", getpid());
00195 if (system(syscall.c_str())==0) return true;
00196 syscall = "gcore -s -c ";
00197 syscall += filename;
00198 syscall += vul_sprintf(" %d", getpid());
00199 if (system(syscall.c_str())==0) return true;
00200 #endif
00201 vcl_cerr << "WARNING: vul_debug_core_dump: Unable to core dump\n";
00202 return false;
00203 }
00204
00205
00206
00207
00208
00209 void vul_debug_set_coredump_and_throw_on_windows_se(const char * )
00210 {
00211
00212 }
00213
00214 #endif // _WIN32
00215
00216
00217 static const char* out_of_memory_coredump_filename = 0;
00218
00219 void
00220 #ifdef _WIN32
00221 __cdecl
00222 #endif
00223 vul_debug_set_coredump_and_throw_on_out_of_memory_handler()
00224 {
00225 vul_debug_core_dump(out_of_memory_coredump_filename);
00226 #if VCL_HAS_EXCEPTIONS
00227 throw vcl_bad_alloc();
00228 #else
00229 vcl_cerr << "Out of Memory.\n";
00230 vcl_abort();
00231 #endif
00232 }
00233
00234
00235
00236 void vul_debug_set_coredump_and_throw_on_out_of_memory(const char * filename)
00237 {
00238 out_of_memory_coredump_filename = filename;
00239 vcl_set_new_handler(vul_debug_set_coredump_and_throw_on_out_of_memory_handler);
00240 }