source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/Debug.cpp @ 641

Last change on this file since 641 was 641, checked in by dai_9181, 15 years ago

・デバッグトレース時、グローバル領域の終端行でステップインまたはステップアウトしたときにデバッグ情報の取得に失敗して強制終了してしまう不具合を修正。
・グローバル領域のデバッグ実行ができなくなっている不具合を修正。

File size: 23.9 KB
Line 
1#include "stdafx.h"
2
3#include <Compiler.h>
4
5#include "../BasicCompiler_Common/common.h"
6#include "../BasicCompiler_Common/DebugSection.h"
7
8//デバッグ用
9#include "../BasicCompiler_Common/debug.h"
10
11char *OpBuffer;
12
13extern DWORD dwStepRun;
14
15HANDLE hDebugProcess;
16
17DWORD _DebugSys_dwThreadID[MAX_DEBUG_THREAD];
18HANDLE array_hDebugThread[MAX_DEBUG_THREAD];
19
20int StepCursorObpSchedule=-1;
21int StepCursor_BackupChar;
22
23int NextStepThreadNum;
24
25
26void Debugger_StepIn(void){
27    dwStepRun=1;
28}
29void Debugger_StepOver(void){
30    dwStepRun=2;
31}
32
33void Debugger_StepCursor(void){
34    char temporary[MAX_PATH];
35    GetTempPath(MAX_PATH,temporary);
36    if(temporary[lstrlen(temporary)-1]!='\\') lstrcat(temporary,"\\");
37    lstrcat(temporary,"ab_breakpoint.tmp");
38
39    char *buffer;
40    buffer=ReadBuffer_NonErrMsg(temporary);
41
42    int i=0;
43    char szFilePath[MAX_PATH];
44    i=GetOneParameter(buffer,i,szFilePath);
45    RemoveStringQuotes(szFilePath);
46
47    int iLineNum;
48    i=GetOneParameter(buffer,i,temporary);
49    iLineNum=atoi(temporary);
50
51
52
53    /////////////////////////////////////////////////////////
54    // デバッグ中プロセスのネイティブバッファ領域を更新
55    /////////////////////////////////////////////////////////
56
57    int FileNum;
58    const IncludedFilesRelation *pIncludedFilesRelation = NULL;
59    const BasicSource *pNowSource = NULL;
60    BOOST_FOREACH( const ObjectModule *pObjectModule, compiler.staticLibraries )
61    {
62        const BasicSource *pSource = &pObjectModule->GetSource();
63
64        pIncludedFilesRelation = &pSource->GetIncludedFilesRelation();
65
66        for(FileNum=0;FileNum<pIncludedFilesRelation->GetFileCounts();FileNum++)
67        {
68            if(lstrcmpi(pIncludedFilesRelation->GetFilePathFromFileNumber(FileNum).c_str(),szFilePath)==0)
69            {
70                pNowSource = pSource;
71                break;
72            }
73        }
74        if( FileNum == pIncludedFilesRelation->GetFileCounts() )
75        {
76            pIncludedFilesRelation = NULL;
77        }
78        else
79        {
80            break;
81        }
82    }
83
84    if( !pIncludedFilesRelation )
85    {
86        return;
87    }
88
89    for(i=0;;i++){
90        if( pIncludedFilesRelation->GetFileNumber( i ) == FileNum
91            || pIncludedFilesRelation->GetFileNumber( i ) == -1 )
92        {
93            break;
94        }
95    }
96    if( pIncludedFilesRelation->GetFileNumber( i ) == -1 )
97    {
98        return;
99    }
100
101    int FileBaseLine;
102    FileBaseLine=i;
103
104    int i2;
105    for(i2=0;;i++,i2++)
106    {
107        if( FileNum < pIncludedFilesRelation->GetFileNumber( i ) )
108        {
109            while( FileNum != pIncludedFilesRelation->GetFileNumber( i ) )
110            {
111                i++;
112            }
113        }
114
115        if(i2==iLineNum){
116            extern SourceLines oldSourceLines;
117
118loop:
119            int tempCp = GetSourceCodeIndexFromLine( pNowSource->GetBuffer(), FileBaseLine+i2 );
120
121            int i3;
122            for(i3=0;i3<(int)oldSourceLines.size()-1;i3++){
123                if(oldSourceLines[i3].GetSourceCodePosition().GetPos()==tempCp) break;
124            }
125            if(i3==oldSourceLines.size()-1){
126                i2--;
127                goto loop;
128            }
129
130            StepCursorObpSchedule=oldSourceLines[i3].GetNativeCodePos();
131            StepCursor_BackupChar=pobj_DBDebugSection->pobj_now->BreakStepCodeBuffer[StepCursorObpSchedule];
132
133            pobj_DBDebugSection->pobj_now->BreakStepCodeBuffer[StepCursorObpSchedule]=(char)0xCC;
134
135            break;
136        }
137    }
138
139    extern HWND hDebugWnd;
140    SendMessage(hDebugWnd,WM_DEBUG_CONTINUE,0,0);
141
142
143
144    HeapDefaultFree(buffer);
145}
146void Debugger_Stop(void){
147    //プロセスを終了
148    TerminateProcess(hDebugProcess,0);
149    hDebugProcess=0;
150
151    //デバッグダイアログを終了
152    extern HWND hDebugWnd;
153    if(hDebugWnd){
154        DestroyWindow(hDebugWnd);
155    }
156}
157void Debugger_Pause(void){
158    ///////////////////////////
159    // デバッグを一時中断
160    ///////////////////////////
161
162    //ターゲットプロセス内のスレッドを一時中断
163    int i;
164    for(i=0;i<MAX_DEBUG_THREAD;i++){
165        if(_DebugSys_dwThreadID[i])
166            SuspendThread(array_hDebugThread[i]);
167    }
168
169    //デバッグレジスタにフラグをセット
170    CONTEXT Context;
171    for(i=0;i<MAX_DEBUG_THREAD;i++){
172        if(_DebugSys_dwThreadID[i]){
173            Context.ContextFlags=CONTEXT_CONTROL|CONTEXT_DEBUG_REGISTERS;
174            GetThreadContext(array_hDebugThread[i],&Context);
175            Context.EFlags|=0x100;
176            SetThreadContext(array_hDebugThread[i],&Context);
177        }
178    }
179
180    //スレッドを再開
181    for(i=0;i<MAX_DEBUG_THREAD;i++){
182        if(_DebugSys_dwThreadID[i])
183            ResumeThread(array_hDebugThread[i]);
184    }
185}
186
187void ReleaseCPUSingleStep(void){
188    ////////////////////////////////////////
189    // CPU機構のシングルステップを解除
190    ////////////////////////////////////////
191
192    //ターゲットプロセス内のスレッドを一時中断
193    int i;
194    for(i=0;i<MAX_DEBUG_THREAD;i++){
195        if(_DebugSys_dwThreadID[i])
196            SuspendThread(array_hDebugThread[i]);
197    }
198
199    //デバッグレジスタにフラグをセット
200    CONTEXT Context;
201    for(i=0;i<MAX_DEBUG_THREAD;i++){
202        if(_DebugSys_dwThreadID[i]){
203            Context.ContextFlags=CONTEXT_CONTROL|CONTEXT_DEBUG_REGISTERS;
204            GetThreadContext(array_hDebugThread[i],&Context);
205            Context.EFlags&=~0x00000100;
206            SetThreadContext(array_hDebugThread[i],&Context);
207        }
208    }
209
210    //スレッドを再開
211    for(i=0;i<MAX_DEBUG_THREAD;i++){
212        if(_DebugSys_dwThreadID[i])
213            ResumeThread(array_hDebugThread[i]);
214    }
215}
216
217
218ULONG_PTR rva_to_real(DWORD p){
219    extern DWORD ImageBase;
220    extern int MemPos_CodeSection;
221    return p+ImageBase+MemPos_CodeSection;
222}
223
224void ShowVarList(DEBUG_EVENT *pde,BOOL bExit){
225    extern DWORD ImageBase;
226    extern int MemPos_RWSection;
227
228    //デバッグダイアログを表示
229    extern HINSTANCE hInst;
230    extern HWND hMainDlg;
231    extern HWND hDebugWnd;
232    dwStepRun=0;
233    if(!hDebugWnd) SendMessage(hMainDlg,WM_SHOWVARLIST,0,pde->dwThreadId);
234    else InitVarList(pde->dwThreadId);
235
236    if(bExit){
237        //"中断"
238        SetDlgItemText(hMainDlg,IDOK,STRING_CLOSE);
239
240        extern HWND hDebuggerToolbar;
241        SendMessage(hDebuggerToolbar,TB_SETSTATE,IDC_DEBUG_START,TBSTATE_INDETERMINATE);
242        SendMessage(hDebuggerToolbar,TB_SETSTATE,IDC_DEBUG_STEPOVER,TBSTATE_INDETERMINATE);
243        SendMessage(hDebuggerToolbar,TB_SETSTATE,IDC_DEBUG_STEPIN,TBSTATE_INDETERMINATE);
244    }
245    else{
246        //"継続"
247        SetDlgItemText(hDebugWnd,IDCANCEL,STRING_CONTINUE);
248    }
249    while(hDebugWnd&&dwStepRun==0) Sleep(1);
250}
251void DebugMessage(char *buffer){
252    extern HWND hMainDlg;
253    int pos;
254
255    if(!IsWindowEnabled(GetDlgItem(hMainDlg,IDC_DEBUGLIST))){
256        SetDlgItemText(hMainDlg,IDC_DEBUGLIST,"");
257        EnableWindow(GetDlgItem(hMainDlg,IDC_DEBUGLIST),1);
258    }
259
260    pos=GetWindowTextLength(GetDlgItem(hMainDlg,IDC_DEBUGLIST));
261    SendDlgItemMessage(hMainDlg,IDC_DEBUGLIST,EM_SETSEL,pos,pos);
262    SendDlgItemMessage(hMainDlg,IDC_DEBUGLIST,EM_REPLACESEL,0,(LPARAM)buffer);
263}
264UserProc *GetSubFromObp(ULONG_PTR pos)
265{
266    compiler.GetObjectModule().meta.GetUserProcs().Iterator_Reset();
267    while( compiler.GetObjectModule().meta.GetUserProcs().Iterator_HasNext() )
268    {
269        UserProc *pUserProc = compiler.GetObjectModule().meta.GetUserProcs().Iterator_GetNext();
270
271        if(rva_to_real(pUserProc->GetBeginOpAddress()) <= pos  &&
272            pos < rva_to_real(pUserProc->GetEndOpAddress()))
273        {
274            return pUserProc;
275        }
276    }
277    return NULL;
278}
279void ReleaseSingleStep(DWORD dwBeforeStepRun,HANDLE hThread,CONTEXT *pContext){
280    //以前にシングルステップ実行をした場合
281    extern DWORD ImageBase;
282    extern int MemPos_CodeSection;
283    extern int FileSize_CodeSection;
284    int i2;
285    ULONG_PTR lpAccBytes;
286
287    ///////////////////////////
288    // シングルステップOFF
289    ///////////////////////////
290
291    //ユーザー指定のブレークポイントをセット
292    WriteProcessMemory(hDebugProcess,
293        (void *)(ULONG_PTR)(ImageBase+MemPos_CodeSection),
294        pobj_DBDebugSection->pobj_now->BreakStepCodeBuffer,
295        FileSize_CodeSection,&lpAccBytes);
296
297    //次に実行すべき命令はユーザー指定によるブレークポイントをはずしておく
298    if(ImageBase+MemPos_CodeSection<=EIP_RIP(*pContext)&&EIP_RIP(*pContext)<ImageBase+MemPos_CodeSection+FileSize_CodeSection){
299        if(OpBuffer[EIP_RIP(*pContext)-ImageBase-MemPos_CodeSection-1]!=
300            pobj_DBDebugSection->pobj_now->BreakStepCodeBuffer[EIP_RIP(*pContext)-ImageBase-MemPos_CodeSection-1]){
301            //直前のブレークポイントがユーザー指定によるものだったとき
302
303            //eip/ripを1だけ減少
304            EIP_RIP(*pContext)--;
305            SetThreadContext(hThread,pContext);
306
307            //ブレークポイントを解除
308            WriteProcessMemory(hDebugProcess,(void *)EIP_RIP(*pContext),&OpBuffer[EIP_RIP(*pContext)-ImageBase-MemPos_CodeSection],1,&lpAccBytes);
309
310
311            extern int StepCursorObpSchedule;
312            if(StepCursorObpSchedule==(int)(EIP_RIP(*pContext)-ImageBase-MemPos_CodeSection)){
313                //カーソル行までのステップ実行の場合
314                pobj_DBDebugSection->pobj_now->BreakStepCodeBuffer[StepCursorObpSchedule]=StepCursor_BackupChar;
315                StepCursorObpSchedule=-1;
316            }
317
318            return;
319        }
320    }
321
322
323    if(dwBeforeStepRun){
324        //直前にシングルステップを行った場合
325        if(ImageBase+MemPos_CodeSection <= EIP_RIP(*pContext) &&
326            EIP_RIP(*pContext) < ImageBase+MemPos_CodeSection+FileSize_CodeSection){
327            //オリジナルコード内のみ、シングルステップ用の"int 3"を考慮
328            EIP_RIP(*pContext)--;
329            SetThreadContext(hThread,pContext);
330        }
331
332        //他のスレッドのサスペンドを解除
333        for(i2=0;i2<MAX_DEBUG_THREAD;i2++){
334            if(array_hDebugThread[i2] && hThread!=array_hDebugThread[i2])
335                ResumeThread(array_hDebugThread[i2]);
336        }
337    }
338}
339
340void Set_DebugSys_dwThreadID(){
341    int i;
342    for(i=0;i<pobj_DBDebugSection->num;i++){
343        ULONG_PTR lpAccBytes;
344        WriteProcessMemory(hDebugProcess,
345            (void *)(ULONG_PTR)(pobj_DBDebugSection->ppobj_ds[i]->dwImageBase + pobj_DBDebugSection->ppobj_ds[i]->dwRVA_RWSection),
346            _DebugSys_dwThreadID,
347            sizeof(DWORD)*MAX_DEBUG_THREAD,
348            &lpAccBytes
349        );
350    }
351}
352void AddThread(DWORD dwThreadId, HANDLE hThread){
353    int i;
354
355
356    for(i=0;i<MAX_DEBUG_THREAD;i++){
357        if(_DebugSys_dwThreadID[i]==0){
358            _DebugSys_dwThreadID[i]=dwThreadId;
359            array_hDebugThread[i]=hThread;
360            break;
361        }
362    }
363
364    Set_DebugSys_dwThreadID();
365}
366void DeleteThread(DWORD dwThreadId){
367    int i;
368
369    for(i=0;i<MAX_DEBUG_THREAD;i++){
370        if(_DebugSys_dwThreadID[i]==dwThreadId){
371            _DebugSys_dwThreadID[i]=0;
372            array_hDebugThread[i]=0;
373            break;
374        }
375    }
376
377    Set_DebugSys_dwThreadID();
378}
379
380void DebugProgram(void){
381    extern HWND hMainDlg;
382    extern DWORD ImageBase;
383    extern int MemPos_CodeSection;
384    extern int MemPos_RWSection;
385    extern int FileSize_CodeSection;
386    int i2,i3,i4;
387    char temporary[1024];
388
389    char ExeFilePathForDll[MAX_PATH];
390    if( compiler.IsDll() ){
391        //DLLをデバッグする場合
392        extern char szDebugExeForDll[1024];
393        if(szDebugExeForDll[0]){
394            //指定済み
395            lstrcpy(ExeFilePathForDll,szDebugExeForDll);
396        }
397        else{
398            //ユーザーに実行ファイルを選択させる
399            extern HWND hOwnerEditor;
400            extern LPSTR ExeFileFilter;
401            if(!GetFilePathDialog(hOwnerEditor,ExeFilePathForDll,ExeFileFilter,"デバッグ用の実行可能ファイルを指定してください。",1)) return;
402        }
403    }
404
405
406    //"中断"
407    SetDlgItemText(hMainDlg,IDOK,STRING_STOP);
408
409    SendMessage(hOwnerEditor,WM_SETDEBUGGERBASE,0,0);
410
411    //カレントディレクトリを設定
412    extern char BasicCurDir[MAX_PATH];
413    SetCurrentDirectory(BasicCurDir);
414
415    SendDlgItemMessage(hMainDlg,IDC_SHOWERROR,BM_SETCHECK,BST_UNCHECKED,0);
416    SendDlgItemMessage(hMainDlg,IDC_SHOWDEBUG,BM_SETCHECK,BST_CHECKED,0);
417    SendMessage(hMainDlg,WM_COMMAND,IDC_SHOWDEBUG,0);
418
419    //ブレークポイントを生成
420    pobj_DBBreakPoint=new CDBBreakPoint;
421
422
423    // デバッグをスタート
424    debugger.DebugStart();
425
426
427    if( program.IsAttach() )
428    {
429        //プロセスIDを元にハンドルを取得
430        HANDLE hProcess;
431        hProcess=OpenProcess(PROCESS_ALL_ACCESS,0, program.GetAttachProcessId() );
432        if(!hProcess) goto AttachError;
433
434        //そのプロセスにおける実行モジュールのインスタンスハンドルを取得
435        HINSTANCE hModule;
436        DWORD cbReturned;
437        if(!EnumProcessModules( hProcess, &hModule, sizeof(HINSTANCE), &cbReturned )) goto AttachError;
438
439        //実行ファイル名を取得
440        char tempOutputFileName[MAX_PATH];
441        GetModuleFileNameEx(hProcess,hModule,tempOutputFileName,MAX_PATH);
442        program.SetOutputFilePath( tempOutputFileName );
443
444        CloseHandle(hProcess);
445
446/*
447        //デバッグ用の拡張情報を取得
448        pobj_DebugSection->load(program.GetOutputFilePath().c_str());*/
449
450        if(!DebugActiveProcess( program.GetAttachProcessId() )){
451AttachError:
452            DebugMessage("アタッチに失敗しました。");
453            return;
454        }
455    }
456    else{
457        /*if(!pobj_DebugSection->load(program.GetOutputFilePath().c_str())){
458            extern BOOL bDebugCompile;
459            bDebugCompile=1;
460            Build();
461            pobj_DebugSection->load(program.GetOutputFilePath().c_str());
462        }*/
463
464        //スレッドを生成
465        extern char szDebugCmdLine[1024];
466        STARTUPINFO si;
467        PROCESS_INFORMATION pi;
468        memset(&si,0,sizeof(STARTUPINFO));
469        si.cb=sizeof(STARTUPINFO);
470        if( !compiler.IsDll() ){
471            //EXEファイルをデバッグ
472            CreateProcess(program.GetOutputFilePath().c_str(),szDebugCmdLine,NULL,NULL,0,NORMAL_PRIORITY_CLASS|DEBUG_ONLY_THIS_PROCESS|CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi);
473        }
474        else{
475            //DLLファイルをデバッグ
476            CreateProcess(ExeFilePathForDll,szDebugCmdLine,NULL,NULL,0,NORMAL_PRIORITY_CLASS|DEBUG_ONLY_THIS_PROCESS|CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi);
477        }
478
479        CloseHandle(pi.hProcess);
480        CloseHandle(pi.hThread);
481    }
482
483
484    //デバッグ情報データベースを生成
485    pobj_DBDebugSection=new CDBDebugSection();
486
487    //デバッグスレッド情報(プロシージャの階層構造を管理)を生成
488    pobj_dti=new CDebugThreadInfo();
489
490    UserProc *pUserProc;
491
492    extern DWORD dwStepRun;
493    BOOL bFirstBreak=1;
494    CONTEXT Context;
495    HANDLE hMainThread;
496    ULONG_PTR lpAccBytes;
497
498    DEBUG_EVENT de;
499    memset(&de,0,sizeof(DEBUG_EVENT));
500
501    while(WaitForDebugEvent(&de,INFINITE)){
502        if(de.dwDebugEventCode==LOAD_DLL_DEBUG_EVENT){
503            WCHAR wcBuf[MAX_PATH];
504            LONG_PTR lpData;
505
506            wcBuf[0]=0;
507            temporary[0]=0;
508
509            if(de.u.LoadDll.lpImageName){
510                if(!ReadProcessMemory(hDebugProcess,de.u.LoadDll.lpImageName,&lpData,sizeof(LONG_PTR),&lpAccBytes)){
511                    sprintf(temporary,"ロードされたDLLの名前取得(アドレス:&H%08x)に失敗しました。\r\n",(ULONG_PTR)de.u.LoadDll.lpImageName);
512                    DebugMessage(temporary);
513                    goto NextContinue;
514                }
515                if(!lpData) goto Attach_DllLoad;
516
517                if(!ReadProcessMemory(hDebugProcess,(void *)lpData,wcBuf,sizeof(WCHAR)*MAX_PATH,&lpAccBytes)){
518                    sprintf(temporary,"ロードされたDLLの名前取得(アドレス:&H%08x)に失敗しました。\r\n",lpData);
519                    DebugMessage(temporary);
520                    goto NextContinue;
521                }
522
523                if(de.dwThreadId,de.u.LoadDll.fUnicode)
524                    WideCharToMultiByte(CP_ACP,0,wcBuf,-1,temporary,255,NULL,NULL);
525                else lstrcpy(temporary,(char *)wcBuf);
526            }
527            else{
528Attach_DllLoad:
529                //アタッチした場合
530                GetModuleFileNameEx(hDebugProcess,(HINSTANCE)de.u.LoadDll.lpBaseOfDll,temporary,MAX_PATH);
531            }
532
533            char temp2[1024];
534            sprintf(temp2,"\"%s\" をロードしました。\r\n",temporary);
535            DebugMessage(temp2);
536
537
538            //可能であればデバッグ情報を読みとる
539            if(pobj_DBDebugSection->add((HMODULE)de.u.LoadDll.lpBaseOfDll)){
540                pobj_DBDebugSection->choice(0);
541                Set_DebugSys_dwThreadID();
542            }
543
544
545            /*if(lstrcmpi(temporary, program.GetOutputFilePath().c_str())==0){
546                ImageBase=(DWORD)de.u.LoadDll.lpBaseOfDll;
547
548                AddThread(de.dwThreadId,hMainThread);
549            }*/
550        }
551        else if(de.dwDebugEventCode==UNLOAD_DLL_DEBUG_EVENT){
552            //DLLのアンロード
553
554            pobj_DBDebugSection->del((HMODULE)de.u.UnloadDll.lpBaseOfDll);
555        }
556        else if(de.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT){
557            hDebugProcess=de.u.CreateProcessInfo.hProcess;
558            hMainThread=de.u.CreateProcessInfo.hThread;
559
560            if(pobj_DBDebugSection->add((HMODULE)de.u.CreateProcessInfo.lpBaseOfImage)){
561                pobj_DBDebugSection->choice(0);
562            }
563
564            AddThread(de.dwThreadId,de.u.CreateProcessInfo.hThread);
565        }
566        else if(de.dwDebugEventCode==CREATE_THREAD_DEBUG_EVENT){
567            AddThread(de.dwThreadId,de.u.CreateThread.hThread);
568        }
569        else if(de.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT){
570            //デバッグダイアログを終了
571            SendMessage(hMainDlg,WM_CLOSE_DEBUGGER,0,0);
572
573            DeleteThread(de.dwThreadId);
574
575            //"スレッド(&H%X)はコード &H%X で終了しました。\r\n"
576            sprintf(temporary,STRING_DEBUG_THREADFINISH,de.dwThreadId,de.u.ExitProcess.dwExitCode);
577            DebugMessage(temporary);
578
579            //"プログラムはコード &H%X で終了しました。\r\n"
580            sprintf(temporary,STRING_DEBUG_PROCESSFINISH,de.u.ExitProcess.dwExitCode);
581            DebugMessage(temporary);
582            break;
583        }
584        else if(de.dwDebugEventCode==EXIT_THREAD_DEBUG_EVENT){
585            //"スレッド(&H%X)はコード &H%X で終了しました。\r\n"
586            sprintf(temporary,STRING_DEBUG_THREADFINISH,de.dwThreadId,de.u.ExitThread.dwExitCode);
587            DebugMessage(temporary);
588
589            //以前にシングルステップ実行をした場合
590            //ステップ実行を解除
591            if(dwStepRun){
592                extern HWND hDebugWnd;
593                if(hDebugWnd) SendMessage(hDebugWnd,WM_VARLIST_CLOSE,0,0);
594
595                for(i4=0;i4<MAX_DEBUG_THREAD;i4++){
596                    if(de.dwThreadId==_DebugSys_dwThreadID[i4]) break;
597                }
598                Context.ContextFlags=CONTEXT_CONTROL;
599                GetThreadContext(array_hDebugThread[i4],&Context);
600
601                ReleaseSingleStep(dwStepRun,array_hDebugThread[i4],&Context);
602            }
603
604            DeleteThread(de.dwThreadId);
605        }
606        else if(de.dwDebugEventCode==OUTPUT_DEBUG_STRING_EVENT){
607            ReadProcessMemory(hDebugProcess,(void *)de.u.DebugString.lpDebugStringData,temporary,de.u.DebugString.nDebugStringLength,&lpAccBytes);
608            DebugMessage(temporary);
609        }
610        else if(de.dwDebugEventCode==EXCEPTION_DEBUG_EVENT){
611
612            //////////////////////////////////////
613            // モジュールを再確認
614            // ※DLLへのデバッグ分岐を可能にする
615            //////////////////////////////////////
616
617
618            //初回例外は無視
619            if(bFirstBreak){
620                bFirstBreak=0;
621                goto NextContinue;
622            }
623
624            for(i2=0;;i2++){
625                if(_DebugSys_dwThreadID[i2]==de.dwThreadId) break;
626            }
627
628            //スレッド情報をリフレッシュ
629            if(!pobj_dti->Reflesh(i2)){
630                MessageBox(hOwnerEditor,"デバッグ情報が壊れています。ターゲットファイルを再コンパイルしてください。","ActiveBasic",MB_OK|MB_ICONEXCLAMATION);
631
632                break;
633            }
634
635            if(de.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_ACCESS_VIOLATION){
636
637                //"スレッド(&H%X)でアクセス違反がありました(EIP=&H%08X)。\r\n"
638                sprintf(temporary,
639                    STRING_DEBUG_THREAD_ACCESSVIOLATION,
640                    de.dwThreadId,
641                    (ULONG_PTR)de.u.Exception.ExceptionRecord.ExceptionAddress,
642#ifdef _AMD64_
643                    (ULONG_PTR)Context.Rsp
644#else
645                    (ULONG_PTR)Context.Esp
646#endif
647                    );
648                DebugMessage(temporary);
649
650                MessageBeep(MB_ICONEXCLAMATION);
651                ShowVarList(&de,1);
652                break;
653            }
654            else if(de.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT||
655                de.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP){
656                /////////////////////////
657                // ブレークポイント
658                /////////////////////////
659
660                if(de.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP){
661                    //CPU機構のシングルステップによるブレークポイント
662                    //※シングルステップを解除
663                    ReleaseCPUSingleStep();
664                }
665
666                i3=dwStepRun;
667
668                for(i4=0;i4<MAX_DEBUG_THREAD;i4++){
669                    if(de.dwThreadId==_DebugSys_dwThreadID[i4]) break;
670                }
671                Context.ContextFlags=CONTEXT_CONTROL | CONTEXT_INTEGER;
672                GetThreadContext(array_hDebugThread[i4],&Context);
673
674                if(i3==0||
675                    i3&&(!(ImageBase+MemPos_CodeSection<=EIP_RIP(Context)&&EIP_RIP(Context)<ImageBase+MemPos_CodeSection+FileSize_CodeSection))
676                    ){
677                    //"スレッド(&H%X)のブレーク ポイント(EIP=&H%08X)。\r\n"
678                    sprintf(temporary,
679                        STRING_DEBUG_BREAKPOINT,
680                        de.dwThreadId,
681                        (ULONG_PTR)de.u.Exception.ExceptionRecord.ExceptionAddress,
682#ifdef _AMD64_
683                        (ULONG_PTR)Context.Rsp
684#else
685                        (ULONG_PTR)Context.Esp
686#endif
687                    );
688                    DebugMessage(temporary);
689                }
690
691                ShowVarList(&de,0);
692
693                //ステップ実行を解除
694                ReleaseSingleStep(i3,array_hDebugThread[i4],&Context);
695
696                if(dwStepRun){
697                    //新たにシングルステップを行う場合
698
699                    if(i4!=NextStepThreadNum){
700                        //次回のステップ対象が別スレッドの場合
701                        Context.ContextFlags=CONTEXT_CONTROL;
702                        GetThreadContext(array_hDebugThread[NextStepThreadNum],&Context);
703                    }
704
705                    if(ImageBase+MemPos_CodeSection <= EIP_RIP(Context) &&
706                        EIP_RIP(Context) < ImageBase+MemPos_CodeSection+FileSize_CodeSection){
707                        //Debug命令語が続く場合はシングルステップは不要になるので、無効にする
708                        //(オリジナルコード内のみ)
709                        if(OpBuffer[EIP_RIP(Context)-ImageBase-MemPos_CodeSection]==(char)0xCC)
710                            dwStepRun=0;
711                    }
712                    if(dwStepRun==1){
713                        //ステップイン
714StepIn:
715                        //シングルステップON
716                        WriteProcessMemory(hDebugProcess,(void *)(ULONG_PTR)(ImageBase+MemPos_CodeSection),
717                            pobj_DBDebugSection->pobj_now->SingleStepCodeBuffer,
718                            FileSize_CodeSection,&lpAccBytes);
719
720                        //次の命令語のブレーク命令は解除しておく(シングルステップ実行後のみ)
721                        //(オリジナルコード内のみ)
722                        if(i3&&ImageBase+MemPos_CodeSection<=EIP_RIP(Context)&&EIP_RIP(Context)<ImageBase+MemPos_CodeSection+FileSize_CodeSection)
723                            WriteProcessMemory(hDebugProcess,(void *)EIP_RIP(Context),&OpBuffer[EIP_RIP(Context)-ImageBase-MemPos_CodeSection],1,&lpAccBytes);
724
725                        //他のスレッドを一時中断
726                        for(i4=0;i4<MAX_DEBUG_THREAD;i4++){
727                            if(_DebugSys_dwThreadID[i4] && NextStepThreadNum!=i4)
728                                SuspendThread(array_hDebugThread[i4]);
729                        }
730                    }
731                    else if(dwStepRun==2){
732                        //ステップオーバー
733
734                        BOOL bRet;
735                        bRet=ReadProcessMemory(hDebugProcess,
736                            (void *)EIP_RIP(Context),
737                            temporary,
738                            5,
739                            &lpAccBytes);
740                        if(!bRet) MessageBox(hMainDlg,"プロセスメモリーの読み込みに失敗","error",MB_OK);
741
742                        extern const UserProc *pSub_DebugSys_EndProc;
743                        if((BYTE)temporary[0]==0xE8&&
744                            *((long *)(temporary+1))+5==(long)rva_to_real(pSub_DebugSys_EndProc->GetBeginOpAddress())-(long)EIP_RIP(Context)){
745                            //プロシージャの終端位置の場合はステップインを行う
746                            goto StepIn;
747                        }
748
749                        extern int GlobalOpBufferSize;
750                        if(ImageBase+MemPos_CodeSection<=pobj_dti->lplpObp[pobj_dti->iProcLevel]&&
751                            pobj_dti->lplpObp[pobj_dti->iProcLevel]<ImageBase+MemPos_CodeSection+GlobalOpBufferSize){
752                            //シングルステップON
753                            WriteProcessMemory(hDebugProcess,
754                                (void *)(ULONG_PTR)(ImageBase+MemPos_CodeSection),
755                                pobj_DBDebugSection->pobj_now->SingleStepCodeBuffer,
756                                GlobalOpBufferSize,
757                                &lpAccBytes);
758                        }
759                        else{
760                            //プロシージャを識別
761                            pUserProc=GetSubFromObp(pobj_dti->lplpObp[pobj_dti->iProcLevel]);
762
763                            //シングルステップON
764                            WriteProcessMemory(hDebugProcess,
765                                (void *)rva_to_real(pUserProc->GetBeginOpAddress()),
766                                pobj_DBDebugSection->pobj_now->SingleStepCodeBuffer+pUserProc->GetBeginOpAddress(),
767                                pUserProc->GetEndOpAddress()-pUserProc->GetBeginOpAddress(),
768                                &lpAccBytes);
769                        }
770
771                        //次の命令語のブレーク命令は解除しておく(シングルステップ実行後のみ)
772                        //(オリジナルコード内のみ)
773                        if(i3&&ImageBase+MemPos_CodeSection<=EIP_RIP(Context)&&EIP_RIP(Context)<ImageBase+MemPos_CodeSection+FileSize_CodeSection)
774                            WriteProcessMemory(hDebugProcess,(void *)EIP_RIP(Context),&OpBuffer[EIP_RIP(Context)-ImageBase-MemPos_CodeSection],1,&lpAccBytes);
775
776                        //他のスレッドを一時中断
777                        for(i4=0;i4<MAX_DEBUG_THREAD;i4++){
778                            if(_DebugSys_dwThreadID[i4] && NextStepThreadNum!=i4)
779                                SuspendThread(array_hDebugThread[i4]);
780                        }
781                    }
782                }
783            }
784            else if(de.u.Exception.ExceptionRecord.ExceptionCode==STATUS_INTEGER_DIVIDE_BY_ZERO){
785                //"0による除算が行われました。スレッド(&H%X) ブレーク ポイント(EIP=&H%08X)。\r\n"
786                sprintf(temporary,STRING_DEBUG_DIVIDE_BY_ZERO,de.dwThreadId,(ULONG_PTR)de.u.Exception.ExceptionRecord.ExceptionAddress);
787                DebugMessage(temporary);
788
789                ShowVarList(&de,1);
790                break;
791            }
792            else if(de.u.Exception.ExceptionRecord.ExceptionCode==STATUS_NO_MEMORY){
793                //"メモリ不足、またはヒープが壊れていることが原因で、メモリの割り当てに失敗しました。スレッド(&H%X) ブレーク ポイント(EIP=&H%08X)。\r\n"
794                sprintf(temporary,STRING_DEBUG_DIVIDE_NO_MEMORY,de.dwThreadId,(ULONG_PTR)de.u.Exception.ExceptionRecord.ExceptionAddress);
795                DebugMessage(temporary);
796
797                ShowVarList(&de,1);
798                break;
799            }
800            else{
801                //"例外処理\ncode:%X"
802                sprintf(temporary,STRING_DEBUG_ERROR,de.u.Exception.ExceptionRecord.ExceptionCode);
803                DebugMessage(temporary);
804            }
805        }
806NextContinue:
807        ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE);
808    }
809
810    extern HWND hDebugWnd;
811    if(hDebugWnd) SendMessage(hDebugWnd,WM_COMMAND,IDCANCEL,0);
812
813    //デバッグに利用した情報を解放
814    delete pobj_DBDebugSection;
815
816    //デバッグスレッド情報を解放
817    delete pobj_dti;
818
819    //ブレークポイントを解放
820    delete pobj_DBBreakPoint;
821
822    //"閉じる"
823    SetDlgItemText(hMainDlg,IDOK,STRING_CLOSE);
824
825    debugger.FinishDebug();
826
827    SendMessage(hOwnerEditor,WM_DESTROYDEBUGGERBASE,0,0);
828}
Note: See TracBrowser for help on using the repository browser.