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
00093 unsigned vul_debug_windows_structured_exception::code() const
00094 {
00095 return static_cast<EXCEPTION_POINTERS*>(ex_ptr_)->ExceptionRecord->ExceptionCode;
00096 }
00097
00098
00099 void *vul_debug_windows_structured_exception::address() const
00100 {
00101 return static_cast<EXCEPTION_POINTERS*>(ex_ptr_)->ExceptionRecord->ExceptionAddress;
00102 }
00103
00104 const char *vul_debug_windows_structured_exception::what() const throw()
00105 {
00106 static char buf[100];
00107 vcl_sprintf(buf, "Caught Windows Structured Exception. Code %lx. Address %lx", code(), address());
00108 return buf;
00109 }
00110
00111 static const char* se_coredump_filename = 0;
00112
00113 void vul_debug_set_coredump_and_throw_on_windows_se_handler(
00114 unsigned code, EXCEPTION_POINTERS * ex_ptr)
00115 {
00116 vul_debug_core_dump_in_windows_seh(se_coredump_filename, ex_ptr);
00117 #ifdef VCL_HAS_EXCEPTIONS
00118 throw vul_debug_windows_structured_exception(ex_ptr);
00119 #else
00120 vcl_cerr << vul_debug_windows_structured_exception(ex_ptr).what();
00121 vcl_abort();
00122 #endif
00123 }
00124
00125
00126
00127
00128 void vul_debug_set_coredump_and_throw_on_windows_se(const char * filename)
00129 {
00130 se_coredump_filename = filename;
00131 _set_se_translator(vul_debug_set_coredump_and_throw_on_windows_se_handler);
00132 }
00133
00134
00135 # else //VXL_HAS_DBGHELP_H
00136
00137 void vul_debug_core_dump_in_windows_seh(const char *, void*)
00138 {
00139 vcl_cerr << "WARNING: vul_debug_core_dump_in_windows_seh: Unable to core dump\n";
00140 }
00141
00142 void vul_debug_core_dump(const char *)
00143 {
00144 vcl_cerr << "WARNING: vul_debug_core_dump: Unable to core dump\n";
00145 }
00146
00147
00148 unsigned vul_debug_windows_structured_exception::code() const
00149 {
00150 return 0;
00151 }
00152
00153
00154 void *vul_debug_windows_structured_exception::address() const
00155 {
00156 return 0;
00157 }
00158
00159 const char *vul_debug_windows_structured_exception::what() const throw()
00160 {
00161 return "Caught Windows Exception on machine with old or no version of DbgHelp.";
00162 }
00163
00164
00165
00166
00167 void vul_debug_set_coredump_and_throw_on_windows_se(const char * )
00168 {
00169 vcl_cerr << "WARNING: No DbgHelp.h on this platform - can't set SE Handler.\n";
00170 }
00171
00172 # endif // VXL_HAS_DBGHELP_H
00173
00174
00175 #else // _WIN32
00176
00177 #include <vcl_string.h>
00178 #ifdef VXL_UNISTD_HAS_GETPID
00179 # include <unistd.h>
00180 #endif
00181 #include <vul/vul_sprintf.h>
00182
00183 void vul_debug_core_dump(const char * filename)
00184 {
00185 static int count = 0;
00186 #ifdef VXL_UNISTD_HAS_GETPID
00187 vcl_string syscall = "gcore -o ";
00188 syscall += vul_sprintf(filename, count++);
00189 syscall += vul_sprintf(" %d", getpid());
00190 if (system(syscall.c_str())==0) return;
00191 syscall = "gcore -s -c ";
00192 syscall += filename;
00193 syscall += vul_sprintf(" %d", getpid());
00194 if (system(syscall.c_str())==0) return;
00195 #endif
00196 vcl_cerr << "WARNING: vul_debug_core_dump: Unable to core dump\n";
00197 }
00198
00199
00200
00201
00202
00203 void vul_debug_set_coredump_and_throw_on_windows_se(const char * filename)
00204 {
00205
00206 }
00207
00208 #endif // _WIN32
00209
00210
00211 static const char* out_out_memory_coredump_filename = 0;
00212
00213 void
00214 #ifdef _WIN32
00215 __cdecl
00216 #endif
00217 vul_debug_set_coredump_and_throw_on_out_of_memory_handler()
00218 {
00219 vul_debug_core_dump(out_out_memory_coredump_filename);
00220 #if VCL_HAS_EXCEPTIONS
00221 throw vcl_bad_alloc();
00222 #else
00223 vcl_cerr << "Out of Memory.\n";
00224 vcl_abort();
00225 #endif
00226 }
00227
00228
00229
00230 void vul_debug_set_coredump_and_throw_on_out_of_memory(const char * filename)
00231 {
00232 out_out_memory_coredump_filename = filename;
00233 vcl_set_new_handler(vul_debug_set_coredump_and_throw_on_out_of_memory_handler);
00234 }