Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/teraterm/teraterm/ttdebug.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10171 - (show annotations) (download) (as text)
Thu Aug 18 14:43:36 2022 UTC (21 months, 1 week ago) by zmatsuo
File MIME type: text/x-c++src
File size: 10671 byte(s)
テスト用クラッシュ関数のクラッシュ方法を変更

- __debugbreak() を使用するようにした
- 以前はNULLポインタへの書き込みだった
- MinGW の時は __builtin_trap() を使用していた (r10167)
1 /*
2 * (C) 2020- TeraTerm Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <windows.h>
30 #include <stdio.h>
31 #include <imagehlp.h>
32 #include <shlobj.h> // for SHGetSpecialFolderPathW()
33 #include <intrin.h> // for __debugbreak()
34
35 #include "compat_win.h"
36 #include "asprintf.h"
37 #include "svnversion.h" // for SVNVERSION
38
39 #include "ttdebug.h"
40 #include "ttlib.h"
41
42 /**
43 * �R���\�[���E�B���h�E���\�������f�o�O�p
44 * �f�o�O�p������������printf()�n���\����������������������������
45 *
46 * @retval �R���\�[����Window Handle
47 */
48 HWND DebugConsoleOpen(void)
49 {
50 FILE *fp;
51 HWND hWnd = pGetConsoleWindow();
52 if (hWnd != NULL) {
53 return hWnd;
54 }
55 AllocConsole();
56 freopen_s(&fp, "CONOUT$", "w", stdout);
57 freopen_s(&fp, "CONOUT$", "w", stderr);
58
59 // �������{�^����������
60 hWnd = pGetConsoleWindow();
61 HMENU hmenu = GetSystemMenu(hWnd, FALSE);
62 RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
63
64 return hWnd;
65 }
66
67 //
68 // ���O�n���h�����t�b�N�i�X�^�b�N�g���[�X���_���v�j
69 //
70 // cf. http://svn.collab.net/repos/svn/trunk/subversion/libsvn_subr/win32_crashrpt.c
71 // (2007.9.30 yutaka)
72 //
73 // ���O�R�[�h������������������
74 #if !defined(_M_X64)
75 static const char *GetExceptionString(DWORD exception)
76 {
77 #define EXCEPTION(x) case EXCEPTION_##x: return (#x);
78 static char buf[16];
79
80 switch (exception)
81 {
82 EXCEPTION(ACCESS_VIOLATION)
83 EXCEPTION(DATATYPE_MISALIGNMENT)
84 EXCEPTION(BREAKPOINT)
85 EXCEPTION(SINGLE_STEP)
86 EXCEPTION(ARRAY_BOUNDS_EXCEEDED)
87 EXCEPTION(FLT_DENORMAL_OPERAND)
88 EXCEPTION(FLT_DIVIDE_BY_ZERO)
89 EXCEPTION(FLT_INEXACT_RESULT)
90 EXCEPTION(FLT_INVALID_OPERATION)
91 EXCEPTION(FLT_OVERFLOW)
92 EXCEPTION(FLT_STACK_CHECK)
93 EXCEPTION(FLT_UNDERFLOW)
94 EXCEPTION(INT_DIVIDE_BY_ZERO)
95 EXCEPTION(INT_OVERFLOW)
96 EXCEPTION(PRIV_INSTRUCTION)
97 EXCEPTION(IN_PAGE_ERROR)
98 EXCEPTION(ILLEGAL_INSTRUCTION)
99 EXCEPTION(NONCONTINUABLE_EXCEPTION)
100 EXCEPTION(STACK_OVERFLOW)
101 EXCEPTION(INVALID_DISPOSITION)
102 EXCEPTION(GUARD_PAGE)
103 EXCEPTION(INVALID_HANDLE)
104
105 default:
106 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "0x%x", exception);
107 return buf;
108 //return "UNKNOWN_ERROR";
109 }
110 #undef EXCEPTION
111 }
112
113 /* ���O�������������������o���������\�������A���O�t�B���^���� */
114 static void CALLBACK ApplicationFaultHandler(EXCEPTION_POINTERS *ExInfo)
115 {
116 HGLOBAL gptr;
117 STACKFRAME sf;
118 BOOL bResult;
119 PIMAGEHLP_SYMBOL pSym;
120 DWORD Disp;
121 HANDLE hProcess = GetCurrentProcess();
122 HANDLE hThread = GetCurrentThread();
123 IMAGEHLP_MODULE ih_module;
124 IMAGEHLP_LINE ih_line;
125 int frame;
126 char msg[3072], buf[256];
127
128 if (pSymGetLineFromAddr == NULL) {
129 goto error;
130 }
131
132 /* �V���{�������i�[�p�o�b�t�@�������� */
133 gptr = GlobalAlloc(GMEM_FIXED, 10000);
134 if (gptr == NULL) {
135 goto error;
136 }
137 pSym = (PIMAGEHLP_SYMBOL)GlobalLock(gptr);
138 ZeroMemory(pSym, sizeof(IMAGEHLP_SYMBOL));
139 pSym->SizeOfStruct = 10000;
140 pSym->MaxNameLength = 10000 - sizeof(IMAGEHLP_SYMBOL);
141
142 /* �X�^�b�N�t���[���������� */
143 ZeroMemory(&sf, sizeof(sf));
144 sf.AddrPC.Offset = ExInfo->ContextRecord->Eip;
145 sf.AddrStack.Offset = ExInfo->ContextRecord->Esp;
146 sf.AddrFrame.Offset = ExInfo->ContextRecord->Ebp;
147 sf.AddrPC.Mode = AddrModeFlat;
148 sf.AddrStack.Mode = AddrModeFlat;
149 sf.AddrFrame.Mode = AddrModeFlat;
150
151 /* �V���{���n���h���������� */
152 SymInitialize(hProcess, NULL, TRUE);
153
154 // ���W�X�^�_���v
155 msg[0] = '\0';
156 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "eax=%08X ebx=%08X ecx=%08X edx=%08X esi=%08X edi=%08X\r\n"
157 "ebp=%08X esp=%08X eip=%08X efl=%08X\r\n"
158 "cs=%04X ss=%04X ds=%04X es=%04X fs=%04X gs=%04X\r\n",
159 ExInfo->ContextRecord->Eax,
160 ExInfo->ContextRecord->Ebx,
161 ExInfo->ContextRecord->Ecx,
162 ExInfo->ContextRecord->Edx,
163 ExInfo->ContextRecord->Esi,
164 ExInfo->ContextRecord->Edi,
165 ExInfo->ContextRecord->Ebp,
166 ExInfo->ContextRecord->Esp,
167 ExInfo->ContextRecord->Eip,
168 ExInfo->ContextRecord->EFlags,
169 ExInfo->ContextRecord->SegCs,
170 ExInfo->ContextRecord->SegSs,
171 ExInfo->ContextRecord->SegDs,
172 ExInfo->ContextRecord->SegEs,
173 ExInfo->ContextRecord->SegFs,
174 ExInfo->ContextRecord->SegGs
175 );
176 strncat_s(msg, sizeof(msg), buf, _TRUNCATE);
177
178 if (ExInfo->ExceptionRecord != NULL) {
179 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "Exception: %s\r\n", GetExceptionString(ExInfo->ExceptionRecord->ExceptionCode));
180 strncat_s(msg, sizeof(msg), buf, _TRUNCATE);
181 }
182
183 /* �X�^�b�N�t���[���������\���������� */
184 frame = 0;
185 for (;;) {
186 /* �����X�^�b�N�t���[�������� */
187 bResult = StackWalk(
188 IMAGE_FILE_MACHINE_I386,
189 hProcess,
190 hThread,
191 &sf,
192 NULL,
193 NULL,
194 SymFunctionTableAccess,
195 SymGetModuleBase,
196 NULL);
197
198 /* ���s�������A���[�v�������� */
199 if (!bResult || sf.AddrFrame.Offset == 0)
200 break;
201
202 frame++;
203
204 /* �v���O�����J�E���^�i���z�A�h���X�j�������������I�t�Z�b�g������ */
205 bResult = SymGetSymFromAddr(hProcess, sf.AddrPC.Offset, &Disp, pSym);
206
207 /* �����������\�� */
208 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "#%d 0x%08x in ", frame, sf.AddrPC.Offset);
209 strncat_s(msg, sizeof(msg), buf, _TRUNCATE);
210 if (bResult) {
211 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "%s() + 0x%x ", pSym->Name, Disp);
212 strncat_s(msg, sizeof(msg), buf, _TRUNCATE);
213 } else {
214 _snprintf_s(buf, sizeof(buf), _TRUNCATE, " --- ");
215 strncat_s(msg, sizeof(msg), buf, _TRUNCATE);
216 }
217
218 // ���s�t�@�C����������
219 ZeroMemory( &(ih_module), sizeof(ih_module) );
220 ih_module.SizeOfStruct = sizeof(ih_module);
221 bResult = SymGetModuleInfo( hProcess, sf.AddrPC.Offset, &(ih_module) );
222 strncat_s(msg, sizeof(msg), "at ", _TRUNCATE);
223 if (bResult) {
224 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "%s ", ih_module.ImageName );
225 strncat_s(msg, sizeof(msg), buf, _TRUNCATE);
226 } else {
227 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "%s ", "<Unknown Module>" );
228 strncat_s(msg, sizeof(msg), buf, _TRUNCATE);
229 }
230
231 // �t�@�C�������s����������
232 ZeroMemory( &(ih_line), sizeof(ih_line) );
233 ih_line.SizeOfStruct = sizeof(ih_line);
234 bResult = pSymGetLineFromAddr( hProcess, sf.AddrPC.Offset, &Disp, &ih_line );
235 if (bResult)
236 {
237 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "%s:%lu", ih_line.FileName, ih_line.LineNumber );
238 strncat_s(msg, sizeof(msg), buf, _TRUNCATE);
239 }
240
241 strncat_s(msg, sizeof(msg), "\n", _TRUNCATE);
242 }
243
244 /* ������ */
245 SymCleanup(hProcess);
246 GlobalUnlock(pSym);
247 GlobalFree(pSym);
248
249 // ���O�������������AAPI�����������o��
250 ::MessageBoxA(NULL, msg, "Tera Term: Application fault", MB_OK | MB_ICONEXCLAMATION);
251
252 error:
253 ;
254 }
255 #endif // !defined(_M_X64 )
256
257 static wchar_t *CreateDumpFilename()
258 {
259 SYSTEMTIME local_time;
260 GetLocalTime(&local_time);
261
262 #if defined(SVNVERSION)
263 char *version;
264 asprintf(&version, "r%04d", SVNVERSION);
265 #else
266 char *version = _strdup("unknown");
267 #endif
268 wchar_t *dump_file;
269 aswprintf(&dump_file, L"teraterm_%hs_%04u%02u%02u-%02u%02u%02u.dmp",
270 version,
271 local_time.wYear, local_time.wMonth, local_time.wDay,
272 local_time.wHour, local_time.wMinute, local_time.wSecond);
273 free(version);
274 return dump_file;
275 }
276
277 static void DumpMiniDump(const wchar_t *filename, struct _EXCEPTION_POINTERS* pExceptionPointers)
278 {
279 wchar_t *logdir = NULL;
280 wchar_t *dumpfile = NULL;
281
282 if (pMiniDumpWriteDump == NULL) {
283 // MiniDumpWriteDump() ���T�|�[�g�������������BXP�����O
284 return;
285 }
286
287 logdir = GetLogDirW(NULL);
288 awcscats(&dumpfile, logdir, L"\\", filename, NULL);
289 HANDLE file = CreateFileW(dumpfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
290 free(dumpfile);
291 if (file == INVALID_HANDLE_VALUE) {
292 return;
293 }
294
295 MINIDUMP_EXCEPTION_INFORMATION mdei;
296 mdei.ThreadId = GetCurrentThreadId();
297 mdei.ExceptionPointers = pExceptionPointers;
298 mdei.ClientPointers = TRUE;
299
300 pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), file,
301 (MINIDUMP_TYPE)(MiniDumpNormal|MiniDumpWithHandleData), &mdei, NULL, NULL);
302
303 CloseHandle(file);
304 }
305
306 static BOOL DumpFile = TRUE;
307
308 static LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS* pExceptionPointers)
309 {
310 if (DumpFile) {
311 wchar_t *fname = CreateDumpFilename();
312 if (fname != NULL) {
313 DumpMiniDump(fname, pExceptionPointers);
314 MessageBoxW(NULL, fname, L"Tera Term", MB_OK);
315 free(fname);
316 }
317 else {
318 DumpMiniDump(L"teraterm.dmp", pExceptionPointers);
319 MessageBoxW(NULL, L"dump teraterm.dmp", L"Tera Term", MB_OK);
320 }
321 }
322
323 #if !defined(_M_X64)
324 ApplicationFaultHandler(pExceptionPointers);
325 #endif
326
327 // return EXCEPTION_EXECUTE_HANDLER; /* ���������v���Z�X���I�������� */
328 return EXCEPTION_CONTINUE_SEARCH; /* ���������m�A�v���P�[�V�����G���[�n�|�b�v�A�b�v���b�Z�[�W�{�b�N�X�������o�� */
329 }
330
331 void DebugTestCrash(void)
332 {
333 __debugbreak();
334 }
335
336 static void InvalidParameterHandler(const wchar_t* /*expression*/,
337 const wchar_t* /*function*/,
338 const wchar_t* /*file*/,
339 unsigned int /*line*/,
340 uintptr_t /*pReserved*/)
341 {
342 DebugTestCrash();
343 }
344
345 /**
346 * ���O�n���h�����t�b�N
347 */
348 void DebugSetException(void)
349 {
350 SetUnhandledExceptionFilter(ExceptionFilter);
351
352 // C�����^�C���������p�����[�^�G���[�n���h��
353 _set_invalid_parameter_handler(InvalidParameterHandler);
354 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26