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