C/400

121. デバッグ・モードを検出するには ?

他のトピックでも現在、デバッグ・モードで実行中であるのか
それともリリース・モードで実行されているのかを検出する方法を紹介している。

なぜデバッグ・モードであるのかを検出したいのかと言うと
あるプログラムのデバッグに関して非常に重要なデバッグのテクニックを
忘れないようにするため、このプログラムが再びデバッグ・モードで
実行されたら自動的に警告メッセージやダンブ・リストの出力を
行いたいと思いついたからである。

そのためデバッグ・モードでそのプログラムが実行されたときには
メッセージなどを POPUP で表示したいと考えた。
それほどこのプログラムのデバッグ手法は重要だったのである。

さてデバッグ・モードであることを検出するためには
デバッグ・モードでは次のような検出可能な環境の変化が現れる。

  • 活動化グループ: QTEDBGAG が存在する。
  • デバッグ状況の属性を取得できる。

という二つの特性があることが判明している。
活動化グループ : QTEDBGAG を検出するために他のトピックでは

RCLACTGRP ACTGRP(QTEDBGAG)

を実行してみてその結果を MONITOR する手法を紹介した。
しかしここでは C言語を使うのであるから C/400 の API で
デバッグ中の属性を API で取得する方法を紹介しよう。
デバッグ属性を取得できれば、それは現在、デバッグ中であることを
示しているし、取得でなかった場合はリリース・モードであることを示している。

【サンプル・ソース: TESTDBG 】
0001.00 #include <stdio.h>                                                         
0002.00 #include <stdlib.h>                                                        
0003.00 #include <string.h>                                                        
0004.00 #include <QTEDBGS.h>                                                       
0005.00 #include <signal.h>                                                        
0006.00 #include <errno.h>                                                         
0007.00 #include <except.h>                                                        
0008.00 #include <qmhrcvpm.h>                                                      
0009.00 #include <micomput.h> /* triml */                                          
0010.00                                                                            
0011.00 #define TRUE         0                                                     
0012.00 #define FALSE       -1                                                     
0013.00 typedef struct {                                                           
0014.00    int  BYTESPRO;                                                          
0015.00    int  BYTESAVL;                                                          
0016.00    char MSGID[7];                                                          
0017.00    char RESRVD;                                                            
0018.00    char EXCPDATA[100];                                                     
0019.00 } ERRSTRUCTURE;     /* Define the error return structure            */     
0020.00 ERRSTRUCTURE  errcode;/* Error Code Structure for RCVMSG      */           
0021.00 _TE_ERROR_CODE_T errorCode;                                                
0022.00   volatile _INTRPT_Hndlr_Parms_T ca;                                       
0023.00 typedef struct {                                                           
0024.00    Qmh_Rcvpm_RCVM0300_t rcvm0300;                              
0025.00    char Msg[5000];                                             
0026.00 } RCVM0300;                                                    
0027.00 RCVM0300 rcvm0300;                                             
0028.00 typedef struct {                                               
0029.00    Qmh_Rcvpm_Sender_t sender;                                  
0030.00    char procinfo[1024];                                        
0031.00 } SENDER;                                                      
0032.00 SENDER sender;                                                 
0033.00 int IsDebugMode(void);                                         
0034.00                                                                
0035.00 void main(void){                                               
0036.00                                                                
0037.00     #pragma exception_handler(MONMSG, ca, 0, _C2_MH_ESCAPE, \  
0038.00                                        _CTLA_HANDLE)           
0039.00    printf("** TESTDBG : デバッグ・モードの検出 **\n");         
0040.00    getchar();                                                  
0041.00     if(IsDebugMode() == TRUE) printf("on Debug Mode\n");       
0042.00     else printf("Release Mode\n");                             
0043.00     getchar();                                                 
0044.00     exit(0);                                                   
0045.00                                                                
0046.00  MONMSG:                                                       
0047.00    #pragma disable_handler                                     
0048.00    return;                                                                  
0049.00                                                                             
0050.00 }                                                                           
0051.00 /********************/                                                      
0052.00 int IsDebugMode(void)                                                       
0053.00 /********************/                                                      
0054.00 {                                                                           
0055.00   char attr[10];                                                            
0056.00                                                                             
0057.00    errorCode.BytesProvided  = sizeof(errorCode);                            
0058.00    errorCode.BytesAvailable = 0;                                            
0059.00    QteRetrieveDebugAttribute("*DEBUGJOB ", attr, &errorCode);               
0060.00    if(errorCode.BytesAvailable != 0){/* APIERR */                           
0061.00      if(strncmp(errorCode.ExceptionID, "CPF9541", 7) == 0) return FALSE;    
0062.00     else return TRUE;                                                       
0063.00    }/* APIERR */                                                            
0064.00    else return TRUE;                                                        
0065.00 }                                                                           
【解説】

要は判定しているのは IsDebugMode 関数でありデバッグ中であれば
API : QteRetrieveDebugAttribute によってデバッグ属性の取得が成功するので
TRUE を返し、CPF9541 のエラーが発生すれば FALSE を戻している。

活動化グループ: QTEDBGAGRCLACTGRP
削除に行くという強引な方法ではなく
こちらのほうが自然でスマートな方法であると言える。