home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sherlock.zip / SHERLOCK (.txt) < prev    next >
IBM Works for OS/2  |  1997-04-02  |  33KB  |  241 lines

  1. IBM Works OS/2
  2. Users Manual For Sherlock
  3. Copyright (C) Footprint Software Inc. 1993-1994
  4. HP DeskJet 540
  5. HPDeskJe
  6. Sherlock - A Programmers helper.
  7. Introduction
  8. Trying to debug an application is usually a mystery.  Most  of the time, the debugging is at the developers computer  where source code is available and source level debuggers  are able to quickly and easily locate problems. At this  point it is easy to find problems and correct them.  At this  point, there is little challenge to the mystery.
  9. Unfortunately, after a program has gone out the door, it is  inevitable that a problem occurs at the end user's site.   Although we programmers might be able to reproduce the  problem if an exact description is given, sometimes we  cannot due to one reason or another.  If a trace of what the  program is currently doing at the customers site was  available, then the developer would have a better idea of  what went wrong and how to fix the problem.  Giving the user  access to the original source may not be desirable, and  while reporting the linear address in OS/2 2.0 may make the  end user feel good, it is useless to the developer since the  machine configurations may be different and therefore will  have different addresses.  This is were programmers have a  real mystery.   Unfortunately, usually with too many the  number of pieces missing to allow the mystery to be solved.
  10. This introduces a need into the developers market.  This  need is to allow any end user with minimal instructions to  provide the type of debugging information that the developer  really needs.  Sherlock is a program to aid fellow  programmers in this remote diagnosis of program problems.   This is done through an interfaceless debugger.  This  debugger will load the desired executable for debugging,  start the program and then continue until an exception  occurs.  When an exception occurs, the entire program state  is dumped.  Each thread will have the current register  thread dumped and then attempt to trace the stack back to  the root node of the thread.
  11. Installation
  12. Sherlock may be installed into any directory that is in you  PATH statement.  It is suggested that you create a new  directory to store the files and add this directory to your  PATH statement in CONFIG.SYS.  If you have debugging DLLs,  they MUST be installed in the same directory as Sherlock.   Sherlock will search for the debugging DLLs only in the  directory where Sherlock is stored.  For example:
  13. C:    Make Drive C current.
  14. MKDIR C:\SHERLOCK    Create the Sherlock  directory.
  15. CHDIR C:\SHERLOCK    Change to the Sherlock  directory.
  16. COPY A:*.EXE *.EXE    Copy the executable.
  17. COPY A:*.DLL *.DLL    Copy the debugging  DLLs.
  18. E CONFIG.SYS    Add C:\SHERLOCK to the PATH 
  19.             statement.
  20. Usage
  21. Usage of SHERLOCK is simple, even for most end users.  The  target program is started as it would normally be started  with the addition of listing Sherlock ahead of the target  application.  For example, if you wish to test the program  xyz.exe with the parameters a b.
  22.        Normal:
  23.        xyz a b
  24.        With Sherlock:
  25.        Sherlock xyz a b
  26. Sherlock supports only one command line argument -L which  will specify the name of a new output file.  The name of the  output file is specified immediately after the L.  For  example:
  27. Sherlock -LCatch.log Catch.exe
  28. What will I get out of Sherlock?
  29. What Sherlock will generate is a log file of what the  operator of a debugger would see.  Sherlock will try to load  debugging information for each module which is loaded.   Sherlock's ability to decode debugging information is based  upon loading a DLL to support each different debugging  information format.  Sherlock is capable of supporting many  different debugging formats at the same time. Each module  which is loaded by the target program will be sent to the  support DLLs to ask whether it supports the debugging format  of the module.  If it says yes, no other support DLLs will  be ask whether they support the debugging format of the  module.
  30. Currently, only the following formats are supported:
  31.     SYM files created by mapsym.
  32.     Microsoft C V6.0 debugging format
  33.     IBM C-Set/2 Version 1.0 and 2.x
  34. VisualAge is not supported currently.
  35. Sample Output
  36. Sherlock will produce a log file with all of the output from  Sherlock.  The log file is named SHERLOCK.LOG or whatever  you specify on Sherlock's command line.  This file is placed  into the current directory.  Each execution of Sherlock will  overwrite any existing log file.  The output will be as  described below.
  37. Sherlock will log all exceptions that occur within the  application to the log file.  Note that there are many types  of exceptions.  Some are normal or diagnostic such as guard  page exceptions.  Other exceptions are fatal, but can be  recovered from.  Access Violations while usually fatal can  be recovered from.  For example, C-Set/2 (Copyright IBM) can  insert an exception handler which if not overridden will  print a register state dump.  If overridden, it is possible  to recover from the exception and continue program  execution.  
  38. Sherlock will log ALL exceptions to the log file until the  program has terminated. Each exception will be dumped as a  set of blocks of the format: 
  39. Exception block
  40. Register block
  41. Traceback from current function to first function.  
  42. Code dump
  43. For the descriptions of the different blocks below, the  following program will be used:
  44. ** Main entrance routine.
  45. #define INCL_DOSDATETIME
  46. #include <os2.h>
  47. int main(int argc, char **argv);
  48. int main(int argc, char **argv)
  49.     DosOpen((PSZ)    0,         /* pszFileName */
  50.         (PHFILE) 0,     /* pHf       */
  51.         (PULONG) 0,     /* pulAction   */
  52.              0,         /* cbFile       */
  53.              0,         /* ulAttribute */
  54.              0,         /* fsOpenFlags */
  55.              0,         /* fsOpenMode  */
  56.         (PEAOP2) 0);    /* peaop2       */
  57.     return 0;
  58. This program will cause a GP fault somewhere within OS/2  since a number of NULL pointers is being passed in.  Note  that the program will compile correctly without a complaint  from the compiler.
  59. Exception Block
  60. The "Exception type" block will list the type of problem  that was hit and where. (e.g. - Except #: c0000005 Access  Violation).  Some of the information in this block is  gibberish if you have not worked with OS/2's exception  mechanism.  Some of the information is gibberish even if you  do work with OS/2's exception mechanism.  (Please refer to  the BSEXCPT.H file from the OS/2 Toolkit for details as to  what the Except # parameters mean.)  The text printed to the  right of the 'Except #" is the description as defined by  IBM.  Note that you and others might define other exception  numbers.  These might be used as signals to your application  to signal some event.
  61. For this exception number, an access violation occurred.  The  exception address is the location where the error was  detected.  This is usually the INSTRUCTION POINTER when the  exception occurred.  For this exception type, there are two  exception parameters.  The first for access violation is the  address that caused the problem.  Zero would be a NULL  pointer.  How that pointer was obtained cannot be found from  this block.  It could have been a direct memory reference,  or an indirect reference through one of the index registers  in the CPU.  The module name while useful, is also  misleading  It is NOT the name of the module that actually  had the fault, but the name of the program that was  executing.  Note that in this case, there is no debugging  information available where the exception actually occurred,  so there is no function information available.
  62. Exception type 1 at 1a050179
  63.   Except #: c0000005  Access violation
  64.   Flags:    00000000
  65.   Next Rec: 00000000
  66.   Except Addr: 1a050179
  67.   Num Parms: 2
  68.   Except 0: 00000000
  69.   Except 1: ffffffff
  70.   Module:   D:\SHERLOCK\CATCH\CATCH.EXE
  71.   Size:     18778
  72.   Timestamp:Mon Dec  6 21:27:20 1993
  73.   Lo Function: UNKNOWN
  74.   Hi Function: UNKNOWN
  75. Exception in thread: 1        
  76. ID of the thread where  the exception occurred.
  77. Register block
  78. Each thread of execution within the executing program will  have its register set dumped.  The entire register set is  dumped.  If you have the assembler source code for the  section of code where the exception occurs, then you can  relate the registers to what the program was trying to  accomplish.  Additionally, the segment register information  is dumped.  These registers may be useful if you examine the  limits.  For example, if a reference using the 'FS' register  is made at offset of 0x32, then an exception will occur.   By checking FSLim, then you would see that you have indexed  too far into that segment.  
  79. For the test case given above, you can use the information  from the Exception Block to possibly gather additional  information.  For example, we know from above that the  address 0 was causing a problem.  IF it was from a register  index, then it would have to be from either the EBX, ESI or  EDI registers.  Without more information, you are still  stuck.  You do not know which register is causing the  problem, or if a register is causing a problem.
  80. Pid: 000000f0  Tid:    00000001
  81. Cmd:        0  Value:  00716668
  82. Addr: 0002294c  Buffer: 00037fd4
  83. Len:  00000024  Index:  00000000
  84. MTE:  0000030c
  85. EAX: 00172a80  EBX: 00000000  ECX: 00060010  EDX:  00060007
  86. ESP: 0002291c  EBP: 00022ae4  ESI: 00000000  EDI:  00000000
  87. EIP: 0000c0a0  EFLAGS: 00002206
  88. Carry Parity Aux Zero Sign Trap IntE Dir Flow IOPL Nested  Resume
  89.   NC    PE      0  NE    0    0    1   DN  NO    2    0       0
  90. CSLim 1c000000  CSBase: 00000000  CSAcc: df  CSAttr: d0   CS:005b
  91. DSLim 1c000000  DSBase: 00000000  DSAcc: f3  DSAttr: d0   DS:0053
  92. ESLim 1c000000  ESBase: 00000000  ESAcc: f3  ESAttr: d0   ES:0053
  93. FSLim 00000031  FSBase: 00050030  FSAcc: f3  FSAttr: 00   FS:150b
  94. GSLim 00000000  GSBase: 00000000  GSAcc: 00  GSAttr: 00   GS:0000
  95. SSLim 1c000000  SSBase: 00000000  SSAcc: f3  SSAttr: d0   SS:0053
  96. Traceback from current function to first function  invoked 
  97. The traceback is the block that answers the question of how  you got to where the problem was detected.  Sherlock takes  the EBP, EIP of the current thread given by the register  dump and tracks through the stack to where the program  starts.  At each EBP location found, Sherlock will dump any  location information that is available.  Sherlock assumes  that EBP is used to save the Stack Frame base on every  function call.  If this is not the case, then Sherlock may  skip over functions in its trace.  Sherlock also assumes  that EBP is pushed onto the stack immediately after the  function has been called.  If this is not the case, then  Sherlock may become confused and give erratic results.   Sherlock will follow the EBP back to the beginning of the  program.
  98. Each block contains the EBP/EIP.  These are the Stack Frame  pointer and the EIP of the routine.  The EIP is then  translated by Sherlock into the Base Offset/ Relative  Offset/ Object length/ Object/ Module.  These can be used to  translate into source locations if a map file of the module  is known.  The Object is the Object or Segment in the  linker's map file.  The Relative Offset is the offset within  the Object.  By checking function addresses or line number  information within the map file you can translate the  Relative Offset into a function.
  99. For unsupported debugging modules, a Hi and Lo function  marker are also given.  These may be helpful or may not  since these are based upon the exported functions of a  module.  If a module only contains only a few functions  exported, then the function markers will most likely be  useless.
  100. EBP:    00022ae4    EIP:    1a02c0a0
  101.   Base:    1a020000    Rel:    0000c0a0    Len:    00010000
  102.   Object: 00000002
  103.   Module:   C:\OS2\DLL\DOSCALL1.DLL
  104.   Lo Function: DOSREAD
  105.   Hi Function: DOSCOPY
  106. EBP:    00022b14    EIP:    1a02a958
  107.   Base:    1a020000    Rel:    0000a958    Len:    00010000
  108.   Object: 00000002
  109.   Module:   C:\OS2\DLL\DOSCALL1.DLL
  110.   Lo Function: DOSREAD
  111.   Hi Function: DOSCOPY
  112. The Function/ Source/ Line are the location where the  program was trying to execute for the first block.  In later  blocks, this is the location of where the prior function  (earlier in the listing) was called from.  This entry shows  the result of using one of the debugging support DLLs.  The  function, source module and line number are therefore  accessible and dumped.
  113. EBP:    00022b3c    EIP:    00010023
  114.   Base:    00010000    Rel:    00000023    Len:    00010000
  115.   Object: 00000001
  116.   Module:   C:\WORK\DEBUG\CATCH.EXE
  117.   Function: main
  118.   Source:   CATCH.C
  119.   Line:     9
  120. This entry shows the same module as the above entry, but the  area where the stack traced back to does not have debugging  information, so the bounding functions are supplied as  markers.  If the source code can be found, the source code  will be listed after these blocks.  If there is no debugging  information available, then a disassembly of the code will  occur.  This disassembly will be where ever the EIP for the  block is located.
  121. EBP:    00022b58    EIP:    00010596
  122.   Base:    00010000    Rel:    00000596    Len:    00010000
  123.   Object: 00000001
  124.   Module:   C:\WORK\DEBUG\CATCH.EXE
  125.   Lo Function: _RunExitList
  126.   Hi Function: UNKNOWN
  127. EIP: 1a02c834, DLL: C:\OS2\DLL\DOSCALL1.DLL Func:  DOS32R3EXCEPTIONDISPATCHER
  128. 1a02c834  PUSH    EBP
  129. 1a02c835  MOV    EBP,ESP
  130. 1a02c837  SUB    ESP,0x00000100
  131. 1a02c83d  PUSH    EDI
  132. 1a02c83e  PUSH    ESI
  133. 1a02c83f  MOV    EAX,DWORD PTR [EBP 0xc]
  134. 1a02c842  CMP    DWORD PTR [EAX],0xc0010002
  135. 1a02c848  JE    $ 0x08
  136. 1a02c84a  CMP    DWORD PTR [EAX],0xc0010003
  137. 1a02c850  JNE    $ 0x0c
  138. 1a02c852  MOV    DWORD PTR [EBP 0],0x00000000
  139. Current Limitations
  140. The current release has the current limitations:
  141. 1)    Only the program started will be monitored.  Any  subprocesses started by the program will not be  monitored.
  142. 2)    The distributed version does not have the debugging  DLLs.
  143. 3)    The first release has an annoying flashing effect.  I  am still working to find why this is happening.   Hopefully the next version will have this fixed.
  144. 4)    Crossing 16-32 bit function calls is not currently  supported for the stack trace.
  145. 5)    Tracing of 16 bit stacks is difficult and may be  incorrect for code with near calls in the trace.
  146. Copyright and Legal Information
  147. Sherlock is Copyrighted (c) 1992 - 1995 by Harfmann  Software.
  148. Adding new Interfaces
  149. Sherlock is designed to look in the startup directory where  Sherlock has been installed to find support DLLs.  Any file  with a DLL extension is loaded and examined for two  functions to be exported by name called:
  150.     isKnownModule
  151.     linkPriority
  152. Link Priority
  153. Link priority is used to determine the order used to try and  resolve symbolic information.  When Sherlock first starts,  it tries to load every DLL in the Sherlock directory  assuming that it is a support DLL for Sherlock.  It will  then invoke the linkPriority function to build an internal  linked list of support DLLs.  
  154. ** Answer the linkage priority.
  155. ** Return 1 for insert in front of list
  156. **    (first crack  at linking)
  157. ** Return 0 for add to end of list.
  158. **    (last crack  at linking)
  159. int _System linkPriority(void)
  160.     return 1;
  161. When Sherlock tries to load a module, it iterates through  each support DLL in the linked list to try and determine  whether the debugging format of the module is known to that  support DLL.  For example, the SYM file support is given 0  priority and HLL (C Set++) is given 1 priority to allow the  HLL format to take precedence over the SYM format.
  162. Supporting a Debugging Format
  163. When a module is loaded, Sherlock iterates through all of  the support DLLs to determine if any of them can find the  debugging information for the module.  If the module does  understand the format, it returns true, otherwise it returns  false.  This is done with the isKnownModule function shown  below:
  164. ** Answer whether the module named is a HLL module.
  165. ** If so, set the function pointers and return true.
  166. int _System isKnownModule(DebugModule *module,
  167.                int (* _System DispatchCommand)
  168.                     (int  command),
  169.                      DebugBuffer *buffer)
  170. Where:
  171. module - Pointer to a structure that will be used to  reference the module for as long as the module is  loaded.  All elements except AuxData and the  function pointers should be considered static and  should not be changed.  AuxData and the function  pointers should be filled in if the module  understands the debugging format of the module.
  172. DispatchCommand - Function pointer to be used by the  support DLL if it needs to use the DosDebug API.
  173. buffer - Pointer to the buffer used by DosDebug().
  174. typedef struct _DebugModule {
  175.     void   *nextModule;    // Internal - DO NOT MODIFY
  176.     char   *name;        // Name of file as returned by  DosQueryModuleName
  177.     void   *AuxData;        // Spare pointer for support  DLL usage
  178.     void   *ViewData;        // Internal - DO NOT MODIFY
  179.     time_t  fTimestamp;    // Time stamp of the module
  180.     ULONG   fileSize;        // File size of the module
  181.     ULONG   MTE;        // Module handle
  182.     ULONG   typeFlags;    // Module flags return by  DosQueryAppType
  183.     /*
  184.     ** Module cleanup.    Free any support structures.
  185.     */
  186.     void    (* _System FreeModule)(
  187.                struct _DebugModule *module);    /* Module  handle */
  188.     /*
  189.     ** Source functions.
  190.     */
  191.     int     (* _System FindSource)(        /* 1 found / 0  - not found     */
  192.             struct _DebugModule *module,    /* Module  handle */
  193.             ULONG eipOffset,    /* EIP for function to  find  */
  194.             char *funcName,    /* Buffer for function  name  */
  195.             char *sourceName,    /* Buffer for source  code     */
  196.             ULONG *lineNum);    /* Pointer to line  number     */
  197.     ULONG   (* _System FindSourceLine)(    /* Return offset of  file/line*/
  198.             struct _DebugModule *module,    /* Module  handle */
  199.             int line,        /* Line to find         */
  200.             char *fileName);    /* File name         */
  201.     ULONG   (* _System FindFuncAddr) (    /* Return offset of  function */
  202.             struct _DebugModule *module,    /* Module  handle */
  203.             char *name);            /* Function name.          */
  204.     /*
  205.     ** Variable functions.
  206.     */
  207.     int     (* _System GetName)(            /* State return  value from above    */
  208.             struct _DebugModule *module,    /* Module  handle */
  209.             State *state,        /* State information to  retrieve.
  210.                         ** Contains name of variable.  */
  211.             State *state2);        /* If !NULL: state2  is element of
  212.                         ** structure given in state.  */
  213.     int     (* _System GetArray)(        /* State return  value from above */
  214.             struct _DebugModule *module,    /* Module  handle */
  215.             State *state,        /* Name of array         */
  216.             State *state2);        /* Index of element  to retrieve */
  217.     int     (* _System GetNumMembers)(    /* Return # of  elements 0 if not a structure */
  218.             struct _DebugModule *module,    /* Module  handle */
  219.             State *state);        /* Variable to query and  program state */
  220.     /*
  221.     ** Get the name of the index'th structure element
  222.     */
  223.     int     (* _System GetMemberIndex)(     /* State return  value from above */
  224.             struct _DebugModule *module,    /* Module  handle */
  225.             State *state,        /* Program state          */
  226.             int MemberIndex,    /* Index of element to  retrieve  */
  227.             char *name);        /* Buffer to return name  into     */
  228. } DebugModule;
  229. The FreeModule and FindSource function pointers must be  filled in to support the current functionality of Sherlock.   The other function pointers may be used in future versions.
  230. Page - 
  231. Copyright Harfmann Software
  232. Times New Roman
  233. Times New Roman
  234. Times New Roman
  235. Courier
  236. Times New Roman Bold Italic
  237. Helvetica Bold
  238. Times New Roman Bold
  239. Helvetica
  240. Helvetica
  241.