home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sherlock.zip / SOURCE.C < prev    next >
C/C++ Source or Header  |  1994-06-29  |  13KB  |  552 lines

  1. /*
  2. **  Sherlock - Copyright 1992, 1993, 1994
  3. **    Harfmann Software
  4. **    Compuserve: 73147,213
  5. **    All rights reserved
  6. */
  7. /*
  8. ** Find the requested source information based on certain information.
  9. */
  10. #include    <stdio.h>
  11. #include    <string.h>
  12. #include    <stdlib.h>
  13. #include    <sys\stat.h>
  14. #define     INCL_DOSFILEMGR
  15. #define     INCL_DOSMODULEMGR
  16. #define     INCL_DOSPROCESS
  17. #define     INCL_DOSSESMGR
  18. #include    <os2.h>
  19. #include    "debug.h"
  20.  
  21. typedef unsigned long DWORD;
  22. typedef unsigned short WORD;
  23. #include    "NewExe.h"
  24. #include    "Exe386.h"
  25. #include    "Debugger.h"
  26. #include    "SrcInter.h"
  27. #include    "Source.h"
  28.  
  29. DebugModule aModule;
  30. typedef struct _SupportList {
  31.     int (* _System isKnownModule)(DebugModule *module,
  32.          int (* _System DispatchCommand)(int command),
  33.          DebugBuffer *buffer);
  34.     HMODULE    handle;
  35.     struct _SupportList *next;
  36. } SupportList;
  37.  
  38. static SupportList *supportDllList = NULL;
  39.  
  40. static ULONG findProgramType(char *pszPgm)
  41. {
  42. FILE           *mod;
  43. struct exe_hdr    dosHdr;
  44. union    {
  45.     struct new_exe  os21x;
  46.     struct e32_exe  os22x;
  47. } header;
  48. unsigned char numChars;
  49. char          name[CCHMAXPATH];
  50.  
  51.     DosQueryAppType(pszPgm, &aModule.typeFlags);
  52.     if((aModule.typeFlags & 0x07) != FAPPTYP_NOTSPEC)
  53.     return aModule.typeFlags;
  54.  
  55.     /*
  56.     ** Open the file.
  57.     */
  58.     if((mod = fopen(pszPgm, "rb")) == NULL) {
  59.     fprintf(logFile, "Unable to open module %s.\n", pszPgm);
  60.     return 0;
  61.     }
  62.  
  63.     /*
  64.     ** Get the DOS exe header.
  65.     */
  66.     fread(&dosHdr, sizeof(struct exe_hdr), 1, mod);
  67.     fseek(mod, dosHdr.e_lfanew, SEEK_SET);
  68.  
  69.     /*
  70.     ** Read the os2 header.
  71.     */
  72.     fread(&header, sizeof(header), 1, mod);
  73.     if(header.os21x.ne_magic == NEMAGIC) {
  74.     WORD    i;
  75.  
  76.     fseek(mod, dosHdr.e_lfanew + header.os21x.ne_imptab, SEEK_SET);
  77.     for(i=0; i<header.os21x.ne_cmod; i++) {
  78.         fread(&numChars, 1, 1, mod);
  79.         fread(name, numChars, 1, mod);
  80.         name[numChars] = 0;
  81.         if(stricmp(name, "PMWIN") == 0) {
  82.         aModule.typeFlags |= FAPPTYP_WINDOWAPI;
  83.         fclose(mod);
  84.         return aModule.typeFlags;
  85.         }
  86.     }
  87.     } else {
  88.     DWORD    i;
  89.  
  90.     fseek(mod, dosHdr.e_lfanew + header.os22x.e32_impmod, SEEK_SET);
  91.     for(i=0; i<header.os22x.e32_impmodcnt; i++) {
  92.         fread(&numChars, 1, 1, mod);
  93.         fread(name, numChars, 1, mod);
  94.         name[numChars] = 0;
  95.         if(stricmp(name, "PMWIN") == 0) {
  96.         aModule.typeFlags |= FAPPTYP_WINDOWAPI;
  97.         fclose(mod);
  98.         return aModule.typeFlags;
  99.         }
  100.     }
  101.     }
  102.  
  103.     /*
  104.     ** Let the system decide.
  105.     */
  106.     fclose(mod);
  107.     return aModule.typeFlags;
  108. }
  109.  
  110. /*
  111. ** Start the program.
  112. */
  113. void StartProgram(int argc,         /* Argument count               */
  114.                   char *argv[],     /* Argument values              */
  115.                   int iarg)         /* Index to program name        */
  116. {
  117. ULONG    idErr;                /* Error code            */
  118. CHAR   *p1, *p2;
  119. CHAR    pszPgm[CCHMAXPATH];        /* Name of program to profile   */
  120. CHAR    szArgs[CCHMAXPATH];        /* Program arguments        */
  121. CHAR    szFail[CCHMAXPATH];        /* Program Failure            */
  122. CHAR    name[CCHMAXPATH];        /* Debugging session name        */
  123. STARTDATA stdata;            /* DosStartSession data        */
  124.  
  125.    /* Extract program name from arguments   */
  126.  
  127.     strcpy(pszPgm, argv[iarg]);
  128.     strupr(pszPgm);
  129.     if(strstr(pszPgm, ".EXE") == NULL)
  130.         strcat(pszPgm, ".EXE");
  131.  
  132.    /* Build argument string for program to be profiled  */
  133.  
  134.     szArgs[0] = 0;
  135.     for (iarg++; iarg < argc; iarg++) {
  136.         if ((strlen(szArgs) + strlen(argv[iarg]) + 1) >= sizeof(szArgs))
  137.             break;
  138.         strcat (szArgs, argv[iarg]);
  139.         strcat (szArgs, " ");
  140.     }
  141.  
  142.     /*
  143.     ** Start the session used by the debuggee.
  144.     */
  145.     stdata.Length = sizeof (stdata);
  146.     stdata.Related = SSF_RELATED_CHILD;
  147.     stdata.FgBg = SSF_FGBG_BACK;
  148.     stdata.TraceOpt = SSF_TRACEOPT_TRACE;
  149.     strcpy(name, "Debug session - ");
  150.     p1 = strrchr(pszPgm, '\\');
  151.     p2 = strrchr(pszPgm, '/');
  152.     if(p1 || p2)
  153.     strcat(name, p1 > p2 ? p1 : p2);
  154.     else
  155.         strcat(name, pszPgm);
  156.  
  157.     stdata.PgmTitle = name;
  158.     stdata.PgmName = pszPgm;
  159.     stdata.PgmInputs = szArgs;
  160.     stdata.TermQ = NULL;
  161.     stdata.Environment = NULL;
  162.     stdata.InheritOpt = SSF_INHERTOPT_PARENT;
  163.     aModule.typeFlags = findProgramType(pszPgm);
  164.     stdata.SessionType = aModule.typeFlags & 0x07;
  165.     stdata.IconFile = NULL;
  166.     stdata.PgmHandle = (ULONG) NULL;
  167.     stdata.PgmControl = SSF_CONTROL_VISIBLE;
  168.     stdata.InitXPos = stdata.InitYPos = 0;
  169.     stdata.InitXSize = stdata.InitYSize = 0;
  170.     stdata.ObjectBuffer = szFail;
  171.     if(idErr = DosStartSession(&stdata, &debugInfo.session, &debugInfo.pid)) {
  172.     fprintf(logFile, "\n%s could not be started\nError %u - %s)\n",
  173.            pszPgm, idErr, szFail);
  174.     exit(idErr);
  175.     }
  176.     return;
  177. }
  178.  
  179.  
  180. /*
  181. ** Find a debug module for a given MTE.
  182. */
  183. DebugModule *FindModule(ULONG MTE, DebugModule **prior)
  184. {
  185. DebugModule *ptr;
  186.  
  187.     if(prior)
  188.     prior[0] = &aModule;
  189.  
  190.     /*
  191.     ** See if the module is already in the module list.
  192.     */
  193.     for(ptr = &aModule; ptr->MTE != MTE;) {
  194.     if(prior)
  195.             prior[0] = ptr;
  196.  
  197.     ptr = ptr->nextModule;
  198.     if(ptr == NULL)
  199.         return NULL;
  200.     }
  201.  
  202.     /*
  203.     ** Make sure we save the data.
  204.     */
  205.     if(MTE != ptr->MTE) {
  206.     prior[0] = ptr;
  207.     return NULL;
  208.     }
  209.     return ptr;
  210. }
  211.  
  212. /*
  213. ** Return a pointer to the file name of the source if it is known
  214. ** for the given linear offset of the instruction pointer.
  215. */
  216. int FindSource(DebugModule *module, ULONG eipOffset,
  217.            char *funcName, char *sourceName, ULONG *lineNum)
  218. {
  219.     if(module)
  220.         if(module->FindSource)
  221.             return module->FindSource(module, eipOffset,
  222.                                       funcName, sourceName, lineNum);
  223.  
  224.     return 0;
  225. }
  226.  
  227. /*
  228. ** Find the offset for a given line number in a given file.
  229. */
  230. ULONG    FindSourceLine(DebugModule *module, int line, char *fileName)
  231. {
  232.     if(module)
  233.         if(module->FindSourceLine)
  234.             return module->FindSourceLine(module, line, fileName);
  235.  
  236.     return 0;
  237. }
  238.  
  239. /*
  240. ** Return the linear address of the object given the name of the
  241. **  variable to find and the linear address of the instruction
  242. **  pointer.
  243. */
  244. ULONG FindFuncAddr(DebugModule *module, char *name)
  245. {
  246. ULONG       addr;
  247.  
  248.     if(module == NULL) {
  249.     for(module = &aModule; module != NULL; module = module->nextModule) {
  250.         if(module->FindFuncAddr) {
  251.                 if(addr = module->FindFuncAddr(module, name)) {
  252.                     return addr;
  253.                 }
  254.         }
  255.     }
  256.     } else {
  257.         if(module->FindFuncAddr) {
  258.             if(addr = module->FindFuncAddr(module, name)) {
  259.                 return addr;
  260.             }
  261.         }
  262.     }
  263.     return 0;
  264. }
  265.  
  266. /*
  267. ** Return the linear address of the object given the name of the
  268. **  variable to find and the linear address of the instruction
  269. **  pointer.
  270. */
  271. int GetName(DebugModule *module, State *state, State *state2)
  272. {
  273. int rVal;
  274.  
  275.     if(module == NULL) {
  276.     debugBuffer.Addr = state->baseEIP;
  277.     DispatchCommand(DBG_C_AddrToObject);
  278.     module = FindModule(debugBuffer.MTE, NULL);
  279.     if(module) {
  280.         if(module->GetName(module, state, state2))
  281.         return 1;
  282.         for(module = &aModule; module != NULL;
  283.         module = module->nextModule) {
  284.         rVal = module->GetName(module, state, state2);
  285.         if(rVal == SUCCESS) {
  286.             return SUCCESS;
  287.         }
  288.         }
  289.     }
  290.     } else {
  291.     if(module->GetName) {
  292.         return module->GetName(module, state, state2);
  293.         }
  294.     }
  295.     return INVALID_NAME;
  296. }
  297.  
  298. /*
  299. ** Find the information about a member in a structure.
  300. */
  301. int GetArray(DebugModule *module, State *state, State *state2)
  302. {
  303.     if(module)
  304.     if(module->GetArray)
  305.         return module->GetArray(module, state, state2);
  306.  
  307.     return INVALID_INDEX;
  308. }
  309.  
  310. /*
  311. ** Get the number of members in a structure.
  312. */
  313. int GetNumMembers(DebugModule *module, State *state)
  314. {
  315.     if(module) {
  316.     if(module->GetNumMembers) {
  317.         return module->GetNumMembers(module, state);
  318.     }
  319.     }
  320.  
  321.     return 0;
  322. }
  323.  
  324. /*
  325. ** Get the name of the index'th member in a structure.
  326. */
  327. int GetMemberIndex(DebugModule *module, State *state, int MemberIndex, char *name)
  328. {
  329.     if(module) {
  330.     if(module->GetMemberIndex) {
  331.         return module->GetMemberIndex(module, state, MemberIndex, name);
  332.         }
  333.     }
  334.  
  335.     return INVALID_NAME;
  336. }
  337.  
  338. /*
  339. ** Find all of the DLLs in the Debuggers root dir and try to load them.
  340. */
  341. void loadSupportDlls(void)
  342. {
  343. HMODULE     mte;
  344. int        err;
  345. HDIR        hDir;
  346. ULONG        count;
  347. HMODULE     module;
  348. TIB           *tib;
  349. PIB           *pib;
  350. char           *ptr;
  351. SupportList    *list;
  352. int          (* _System proc)(DebugModule *module,
  353.             int (* _System DispatchCommand)(int command),
  354.             DebugBuffer *buff);
  355. int          (* _System priorityProc)();
  356. FILEFINDBUF3    findBuffer;
  357. char        debugName[CCHMAXPATH];
  358. char        errBuff[CCHMAXPATH];
  359.  
  360.     /*
  361.     ** Find the debugger's path.
  362.     */
  363.     DosGetInfoBlocks(&tib, &pib);
  364.     mte = pib->pib_hmte;
  365.     DosQueryModuleName(mte, sizeof(debugName), debugName);
  366.     ptr = strrchr(debugName, '\\');
  367.     *(ptr+1) = '\0';
  368.  
  369.     /*
  370.     ** Now use the base path as a search path.
  371.     */
  372.     count = 1;
  373.     hDir  = 1;
  374.     strcat(debugName, "*.dll");
  375.     err = DosFindFirst(debugName,        /* Search Path.        */
  376.                &hDir,            /* Handle to use.        */
  377.                0,            /* Normal files.        */
  378.                &findBuffer,        /* Find file buffer.    */
  379.                sizeof(findBuffer),  /* Find file buffer size.    */
  380.                &count,            /* Count of files found.    */
  381.                FIL_STANDARD);        /* Standard file find.    */
  382.     while(err == 0) {
  383.  
  384.     /*
  385.     ** Build the path to the name.
  386.     */
  387.     *(ptr+1) = '\0';
  388.     strcat(debugName, findBuffer.achName);
  389.  
  390.     /*
  391.     ** Try to load the module.
  392.     */
  393.     if(err = DosLoadModule(errBuff, sizeof(errBuff), debugName, &module)) {
  394.         fprintf(logFile, "Error loading '%s' %d\n",
  395.             findBuffer.achName, err);
  396.         goto getNext;
  397.     }
  398.  
  399.     /*
  400.     ** Load the known procedure function.
  401.     */
  402.     if(err = DosQueryProcAddr(module, 0, "isKnownModule", (PFN *) &proc)) {
  403.         fprintf(logFile, "Error loading procedure: %d\n", err);
  404.         proc = NULL;
  405.         DosFreeModule(module);
  406.         goto getNext;
  407.     }
  408.  
  409.     /*
  410.     ** Load the known procedure function.
  411.     */
  412.     if(err = DosQueryProcAddr(module, 0, "linkPriority", (PFN *) &priorityProc)) {
  413.         fprintf(logFile, "Error loading procedure: %d\n", err);
  414.         DosFreeModule(module);
  415.         goto getNext;
  416.     }
  417.  
  418.     /*
  419.     ** Build the link for the list.
  420.     */
  421.     list = calloc(sizeof(SupportList), 1);
  422.     list->next = NULL;
  423.     list->handle = module;
  424.     list->isKnownModule = proc;
  425.  
  426.     /*
  427.     ** If priority linkage, put at the front of the list.
  428.     ** else, put at the end of the list.
  429.     */
  430.     if(supportDllList == NULL) {
  431.         supportDllList = list;
  432.     } else {
  433.         if((*priorityProc)()) {
  434.         list->next = supportDllList;
  435.         supportDllList = list;
  436.         } else {
  437.         SupportList *t;
  438.         for(t=supportDllList;t->next;t=t->next)
  439.             ;
  440.         t->next = list;
  441.         }
  442.     }
  443.  
  444.     /*
  445.     ** Make sure to put link to list if necessary.
  446.     */
  447.  
  448.     /*
  449.     ** Get the next name of the DLL.
  450.     */
  451. getNext:err = DosFindNext(hDir, &findBuffer, sizeof(findBuffer), &count);
  452.  
  453.     }
  454.     DosFindClose(hDir);
  455. }
  456.  
  457. /*
  458. ** Load the module and find out if there is any debugging information.
  459. */
  460. void LoadDebuggeeModule(ULONG MTE)
  461. {
  462. DebugModule *prior, *ptr;
  463. SupportList *list;
  464. int        i;
  465. static char modName[CCHMAXPATH];
  466.  
  467.     /*
  468.     ** See if the module is already in the module list.
  469.     */
  470.     if(ptr = FindModule(MTE, &prior))
  471.         return;
  472.  
  473.     /*
  474.     ** If it is not listed, add it onto the end.
  475.     */
  476.     prior->nextModule = ptr = calloc(sizeof(DebugModule), 1);
  477.     ptr->MTE = MTE;
  478.  
  479.     /*
  480.     ** Get the module name.
  481.     */
  482.     DosQueryModuleName(MTE, sizeof(modName), modName);
  483.     ptr->name = malloc(strlen(modName) + 1);
  484.     strcpy(ptr->name, modName);
  485.  
  486.     /*
  487.     ** Determine the type of dll.
  488.     */
  489.     DosQueryAppType(modName, &ptr->typeFlags);
  490.  
  491.     /*
  492.     ** Load the support DLLs.
  493.     */
  494.     if(supportDllList == NULL)
  495.     loadSupportDlls();
  496.  
  497.     /*
  498.     ** Find out what system supports the source.
  499.     */
  500.     for(list = supportDllList; list; list=list->next) {
  501.     if(list->isKnownModule) {
  502.         if(list->isKnownModule(ptr, DispatchCommand, &debugBuffer)) {
  503.         return;
  504.         }
  505.     }
  506.     }
  507.  
  508.     /*
  509.     ** No one else wants it, use the default handler.
  510.     */
  511.     if(!DefConnectModule(ptr)) {
  512.     fprintf(logFile, "ERROR LOADING MODULE FOR DEBUGGING: '%s'.\n", modName);
  513.     }
  514.     return;
  515. }
  516.  
  517. /*
  518. ** Free the debuggee module from the list.
  519. */
  520. void FreeDebuggeeModule(ULONG MTE)
  521. {
  522. DebugModule *ptr;
  523.  
  524.     /*
  525.     ** See if the module is already in the module list.
  526.     */
  527.     ptr = FindModule(MTE, NULL);
  528.  
  529.     /*
  530.     ** If it is not listed, add it onto the end.
  531.     */
  532.     if(ptr == NULL) {
  533.     fprintf(logFile, "ERROR - Module not in our list!\n");
  534.     exit(1);
  535.     }
  536. }
  537.  
  538. /*
  539. ** Free all library information which has been loaded.
  540. */
  541. void FreeAllModules()
  542. {
  543. DebugModule *module;
  544.  
  545.     for(module = &aModule; module != NULL; module = module->nextModule) {
  546.         if(module->FreeModule) {
  547.             module->FreeModule(module);
  548.     }
  549.     }
  550.     return;
  551. }
  552.