home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / image / symcvt / symtocv.c < prev   
Encoding:
C/C++ Source or Header  |  1997-10-05  |  12.2 KB  |  484 lines

  1. /*++
  2.  
  3.  
  4. Copyright 1996 - 1997 Microsoft Corporation
  5.  
  6. Module Name:
  7.  
  8.     symtocv.c
  9.  
  10. Abstract:
  11.  
  12.     This module handles the conversion activities requires for converting
  13.     C7/C8 SYM files to CODEVIEW debug data.
  14.  
  15. Author:
  16.  
  17.     Wesley A. Witt (wesw) 13-April-1993
  18.  
  19. Environment:
  20.  
  21.     Win32, User Mode
  22.  
  23. --*/
  24.  
  25. #include <windows.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29.  
  30. #include "cv.h"
  31. #define _SYMCVT_SOURCE_
  32. #include "symcvt.h"
  33. #include "cvcommon.h"
  34.  
  35. typedef struct tagSYMNAME {
  36.     BYTE        length;
  37.     char        name[1];
  38. } SYMNAME, *PSYMNAME;
  39.  
  40. typedef struct tagSYMSYMBOL {
  41.     WORD        offset;
  42.     SYMNAME     symName;
  43. } SYMSYMBOL, *PSYMSYMBOL;
  44.  
  45. typedef struct tagSYMFILEHEADER {
  46.     DWORD       fileSize;
  47.     WORD        reserved1;
  48.     WORD        numSyms;
  49.     DWORD       reserved2;
  50.     WORD        nextOffset;
  51.     BYTE        reserved3;
  52.     SYMNAME     symName;
  53. } SYMFILEHEADER, *PSYMFILEHEADER;
  54.  
  55. typedef struct tagSYMHEADER {
  56.     WORD        nextOffset;
  57.     WORD        numSyms;
  58.     WORD        reserved1;
  59.     WORD        segment;
  60.     BYTE        reserved2[12];
  61.     SYMNAME     symName;
  62. } SYMHEADER, *PSYMHEADER;
  63.  
  64. #define SIZEOFSYMFILEHEADER   16
  65. #define SIZEOFSYMHEADER       21
  66. #define SIZEOFSYMBOL           3
  67.  
  68. #define SYM_SEGMENT_NAME       0
  69. #define SYM_SYMBOL_NAME        1
  70. #define SYM_SEGMENT_ABS        2
  71. #define SYM_SYMBOL_ABS         3
  72.  
  73. typedef struct tagENUMINFO {
  74.     DATASYM16           *dataSym;
  75.     DATASYM16           *dataSym2;
  76.     DWORD               numsyms;
  77.     SGI                 *sgi;
  78. } ENUMINFO, *PENUMINFO;
  79.  
  80. typedef BOOL (CALLBACK* SYMBOLENUMPROC)(PSYMNAME pSymName, int symType,
  81.                                         SEGMENT segment, UOFF16 offset,
  82.                                         PENUMINFO pEnumInfo);
  83.  
  84.  
  85. static VOID   GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable,
  86.                           char * s );
  87. DWORD  CreateModulesFromSyms( PPOINTERS p );
  88. DWORD  CreatePublicsFromSyms( PPOINTERS p );
  89. DWORD  CreateSegMapFromSyms( PPOINTERS p );
  90. static BOOL   EnumSymbols( PPOINTERS p, SYMBOLENUMPROC lpEnumProc,
  91.                            PENUMINFO pEnumInfo  );
  92.  
  93. int             CSymSegs;
  94.  
  95. BOOL CALLBACK
  96. SymbolCount(PSYMNAME pSymName, int symType, SEGMENT segment,
  97.             UOFF16 offset, PENUMINFO pEnumInfo )
  98. {
  99.     if ((symType == SYM_SEGMENT_NAME) && (segment > 0)) {
  100.         CSymSegs += 1;
  101.     }
  102.     pEnumInfo->numsyms++;
  103.     return TRUE;
  104. }
  105.  
  106. BOOL
  107. ConvertSymToCv( PPOINTERS p )
  108.  
  109. /*++
  110.  
  111. Routine Description:
  112.  
  113.     This is the control function for the conversion of COFF to CODEVIEW
  114.     debug data.  It calls individual functions for the conversion of
  115.     specific types of debug data.
  116.  
  117.  
  118. Arguments:
  119.  
  120.     p        - pointer to a POINTERS structure (see symcvt.h)
  121.  
  122.  
  123. Return Value:
  124.  
  125.     TRUE     - conversion succeded
  126.     FALSE    - conversion failed
  127.  
  128. --*/
  129.  
  130. {
  131.     ENUMINFO            enumInfo;
  132.     DWORD               dwSize;
  133.  
  134.     CSymSegs = 0;
  135.     enumInfo.numsyms = 0;
  136.     EnumSymbols( p, SymbolCount, &enumInfo );
  137.     dwSize = (enumInfo.numsyms * (sizeof(DATASYM16) + 10)) + 256000;
  138.     p->pCvCurr = p->pCvStart.ptr = malloc( dwSize );
  139.     if (p->pCvStart.ptr == NULL) {
  140.         return FALSE;
  141.     }
  142.     memset( p->pCvStart.ptr, 0, dwSize );
  143.  
  144.     try {
  145.  
  146.         CreateSignature( p );
  147.         CreatePublicsFromSyms( p );
  148.         CreateSymbolHashTable( p );
  149.         CreateAddressSortTable( p );
  150.         CreateSegMapFromSyms( p );
  151.         CreateModulesFromSyms( p );
  152.         CreateDirectories( p );
  153.         p->pCvStart.ptr = realloc( p->pCvStart.ptr, p->pCvStart.size );
  154.         return TRUE;
  155.  
  156.     } except (EXCEPTION_EXECUTE_HANDLER) {
  157.  
  158.         free( p->pCvStart.ptr );
  159.         p->pCvStart.ptr = NULL;
  160.         return FALSE;
  161.  
  162.     }
  163. }
  164.  
  165.  
  166. DWORD
  167. CreateModulesFromSyms( PPOINTERS p )
  168.  
  169. /*++
  170.  
  171. Routine Description:
  172.  
  173.     Creates the individual CV module records.  There is one CV module
  174.     record for each .FILE record in the COFF debug data.  This is true
  175.     even if the COFF size is zero.
  176.  
  177.  
  178. Arguments:
  179.  
  180.     p        - pointer to a POINTERS structure (see symcvt.h)
  181.  
  182.  
  183. Return Value:
  184.  
  185.     The number of modules that were created.
  186.  
  187. --*/
  188.  
  189. {
  190.     char                szDrive    [_MAX_DRIVE];
  191.     char                szDir      [_MAX_DIR];
  192.     char                szFname    [_MAX_FNAME];
  193.     char                szExt      [_MAX_EXT];
  194.     OMFModule           *m;
  195.     int                 i;
  196.     char *              pb;
  197.  
  198.     _splitpath( p->iptrs.szName, szDrive, szDir, szFname, szExt );
  199.  
  200.     m = (OMFModule *) p->pCvCurr;
  201.  
  202.     m->ovlNumber        = 0;
  203.     m->iLib             = 0;
  204.     m->cSeg             = CSymSegs;
  205.     m->Style[0]         = 'C';
  206.     m->Style[1]         = 'V';
  207.     for (i=0; i<CSymSegs; i++) {
  208.         m->SegInfo[i].Seg   = i+1;
  209.         m->SegInfo[i].pad   = 0;
  210.         m->SegInfo[i].Off   = 0;
  211.         m->SegInfo[i].cbSeg = 0xffff;
  212.     }
  213.     pb = (char *) &m->SegInfo[CSymSegs];
  214.     sprintf( &pb[1], "%s.c", szFname );
  215.     pb[0] = strlen( &pb[1] );
  216.  
  217.     pb = (char *) NextMod(m);
  218.  
  219.     UpdatePtrs( p, &p->pCvModules, (LPVOID)pb, 1 );
  220.  
  221.     return 1;
  222. }
  223.  
  224. BOOL CALLBACK
  225. ConvertASymtoPublic(PSYMNAME pSymName, int symType, SEGMENT segment,
  226.                     UOFF16 offset, PENUMINFO pEnumInfo )
  227. {
  228.     if (symType != SYM_SYMBOL_NAME) {
  229.         return TRUE;
  230.     }
  231.  
  232.     pEnumInfo->dataSym->rectyp     = S_PUB16;
  233.     pEnumInfo->dataSym->seg        = segment;
  234.     pEnumInfo->dataSym->off        = offset;
  235.     pEnumInfo->dataSym->typind     = 0;
  236.     pEnumInfo->dataSym->name[0]    = pSymName->length;
  237.     strncpy( &pEnumInfo->dataSym->name[1], pSymName->name, pSymName->length );
  238.     pEnumInfo->dataSym2 = NextSym16( pEnumInfo->dataSym );
  239.     pEnumInfo->dataSym->reclen = (USHORT) ((DWORD)pEnumInfo->dataSym2 -
  240.                                   (DWORD)pEnumInfo->dataSym) - 2;
  241.     pEnumInfo->dataSym = pEnumInfo->dataSym2;
  242.     pEnumInfo->numsyms++;
  243.  
  244.     return TRUE;
  245. }
  246.  
  247. DWORD
  248. CreatePublicsFromSyms( PPOINTERS p )
  249.  
  250. /*++
  251.  
  252. Routine Description:
  253.  
  254.     Creates the individual CV public symbol records.  There is one CV
  255.     public record created for each COFF symbol that is marked as EXTERNAL
  256.     and has a section number greater than zero.  The resulting CV publics
  257.     are sorted by section and offset.
  258.  
  259.  
  260. Arguments:
  261.  
  262.     p        - pointer to a POINTERS structure (see symcvt.h)
  263.  
  264.  
  265. Return Value:
  266.  
  267.     The number of publics created.
  268.  
  269. --*/
  270.  
  271. {
  272.     OMFSymHash          *omfSymHash;
  273.     ENUMINFO            enumInfo;
  274.  
  275.  
  276.     enumInfo.dataSym = (DATASYM16 *)
  277.                  (PUCHAR)((DWORD)p->pCvCurr + sizeof(OMFSymHash));
  278.     enumInfo.numsyms = 0;
  279.  
  280.     EnumSymbols( p, ConvertASymtoPublic, &enumInfo );
  281.  
  282.     omfSymHash = (OMFSymHash *) p->pCvCurr;
  283.     UpdatePtrs(p, &p->pCvPublics, (LPVOID)enumInfo.dataSym,
  284.                enumInfo.numsyms );
  285.  
  286.     omfSymHash->cbSymbol = p->pCvPublics.size - sizeof(OMFSymHash);
  287.     omfSymHash->symhash  = 0;
  288.     omfSymHash->addrhash = 0;
  289.     omfSymHash->cbHSym   = 0;
  290.     omfSymHash->cbHAddr  = 0;
  291.  
  292.     return enumInfo.numsyms;
  293. }
  294.  
  295.  
  296. BOOL CALLBACK
  297. ConvertASegment( PSYMNAME pSymName, int symType, SEGMENT segment,
  298.             UOFF16 offset, PENUMINFO pEnumInfo )
  299. {
  300.     if (symType != SYM_SEGMENT_NAME) {
  301.         return TRUE;
  302.     }
  303.  
  304.     if (segment == 0) {
  305.         return TRUE;
  306.     }
  307.  
  308.     pEnumInfo->numsyms++;
  309.  
  310.     pEnumInfo->sgi->sgf.fRead        = TRUE;
  311.     pEnumInfo->sgi->sgf.fWrite       = TRUE;
  312.     pEnumInfo->sgi->sgf.fExecute     = TRUE;
  313.     pEnumInfo->sgi->sgf.f32Bit       = 0;
  314.     pEnumInfo->sgi->sgf.fSel         = 0;
  315.     pEnumInfo->sgi->sgf.fAbs         = 0;
  316.     pEnumInfo->sgi->sgf.fGroup       = 1;
  317.     pEnumInfo->sgi->iovl             = 0;
  318.     pEnumInfo->sgi->igr              = 0;
  319.     pEnumInfo->sgi->isgPhy           = (USHORT) pEnumInfo->numsyms;
  320.     pEnumInfo->sgi->isegName         = 0;
  321.     pEnumInfo->sgi->iclassName       = 0;
  322.     pEnumInfo->sgi->doffseg          = offset;
  323.     pEnumInfo->sgi->cbSeg            = 0xFFFF;
  324.     pEnumInfo->sgi++;
  325.  
  326.     return TRUE;
  327. }
  328.  
  329.  
  330. DWORD
  331. CreateSegMapFromSyms( PPOINTERS p )
  332.  
  333. /*++
  334.  
  335. Routine Description:
  336.  
  337.     Creates the CV segment map.  The segment map is used by debuggers
  338.     to aid in address lookups.  One segment is created for each COFF
  339.     section in the image.
  340.  
  341. Arguments:
  342.  
  343.     p        - pointer to a POINTERS structure (see symcvt.h)
  344.  
  345.  
  346. Return Value:
  347.  
  348.     The number of segments in the map.
  349.  
  350. --*/
  351.  
  352. {
  353.     SGM          *sgm;
  354.     ENUMINFO     enumInfo;
  355.  
  356.  
  357.     sgm = (SGM *) p->pCvCurr;
  358.     enumInfo.sgi = (SGI *) ((DWORD)p->pCvCurr + sizeof(SGM));
  359.     enumInfo.numsyms = 0;
  360.  
  361.     EnumSymbols( p, ConvertASegment, &enumInfo );
  362.  
  363.     sgm->cSeg = (USHORT)enumInfo.numsyms;
  364.     sgm->cSegLog = (USHORT)enumInfo.numsyms;
  365.  
  366.     UpdatePtrs( p, &p->pCvSegMap, (LPVOID)enumInfo.sgi, enumInfo.numsyms );
  367.  
  368.     return enumInfo.numsyms;
  369. }
  370.  
  371. BOOL
  372. EnumSymbols( PPOINTERS p, SYMBOLENUMPROC lpEnumProc, PENUMINFO pEnumInfo )
  373.  
  374. /*++
  375.  
  376. Routine Description:
  377.  
  378.     This function enumerates all symbols ine the mapped SYM file
  379.  
  380.  
  381. Arguments:
  382.  
  383.     p             -  pointer to a POINTERS structure
  384.     lpEnumProc    -  function to be called once for each function
  385.     pEnumInfo     -  data to be passed between the caller and the enum func
  386.  
  387. Return Value:
  388.  
  389.     TRUE     - success
  390.     FALSE    - failure
  391.  
  392. --*/
  393.  
  394. {
  395.     PSYMFILEHEADER      pSymFileHead;
  396.     PSYMHEADER          pSymHead;
  397.     PSYMHEADER          pSymHead2;
  398.     PSYMSYMBOL          pSymSymbol;
  399.     DWORD               i;
  400.     DWORD               startPosition;
  401.     DWORD               position;
  402.     BOOL                fV86Mode;
  403.     WORD                Segment;
  404.     UOFF16              Offset;
  405.  
  406.  
  407.     pSymFileHead = (PSYMFILEHEADER) p->iptrs.fptr;
  408.     pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymFileHead + SIZEOFSYMFILEHEADER +
  409.                                pSymFileHead->symName.length + 1);
  410.  
  411.     if (!lpEnumProc(&pSymFileHead->symName, SYM_SEGMENT_ABS,
  412.                     0, 0, pEnumInfo )) {
  413.         return FALSE;
  414.     }
  415.  
  416.     for (i=0; i<pSymFileHead->numSyms; i++) {
  417.         if (!lpEnumProc(&pSymSymbol->symName, SYM_SYMBOL_ABS,
  418.                         0, pSymSymbol->offset, pEnumInfo )) {
  419.             return FALSE;
  420.         }
  421.         pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymSymbol + SIZEOFSYMBOL +
  422.                                    pSymSymbol->symName.length);
  423.     }
  424.  
  425.     position = startPosition = ((LONG)pSymFileHead->nextOffset) << 4;
  426.  
  427.     //
  428.     //  Determine if this is a V86Mode sym file.
  429.     //
  430.     //  We'll read the first two headers. If their segment numbers are
  431.     //  not 1 and 2, then we assume V86Mode.
  432.     //
  433.     pSymHead  = (PSYMHEADER) ((DWORD)p->iptrs.fptr + position);
  434.     position  = ((LONG)pSymHead->nextOffset) << 4;
  435.     if ( position != startPosition && position != 0 ) {
  436.         pSymHead2 = (PSYMHEADER) ((DWORD)p->iptrs.fptr + position);
  437.     } else {
  438.         pSymHead2 = NULL;
  439.     }
  440.  
  441.     if ( pSymHead->segment == 1 &&
  442.          (!pSymHead2 || pSymHead2->segment == 2)) {
  443.         fV86Mode = FALSE;
  444.     } else {
  445.         fV86Mode = TRUE;
  446.         Segment  = 0;
  447.     }
  448.  
  449.     position = startPosition;
  450.  
  451.     do {
  452.         pSymHead = (PSYMHEADER) ((DWORD)p->iptrs.fptr + position);
  453.         pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymHead + SIZEOFSYMHEADER +
  454.                                    pSymHead->symName.length);
  455.  
  456.         if ( fV86Mode ) {
  457.             Segment++;
  458.             Offset  = pSymHead->segment;
  459.         } else {
  460.             Segment = pSymHead->segment;
  461.             Offset  = 0;
  462.         }
  463.  
  464.         position = ((LONG)pSymHead->nextOffset) << 4;
  465.  
  466.         if (!lpEnumProc( &pSymHead->symName, SYM_SEGMENT_NAME,
  467.                         Segment, Offset, pEnumInfo )) {
  468.             return FALSE;
  469.         }
  470.  
  471.         for (i=0; i<pSymHead->numSyms; i++) {
  472.             if (!lpEnumProc(&pSymSymbol->symName, SYM_SYMBOL_NAME,
  473.                             Segment, pSymSymbol->offset,
  474.                             pEnumInfo )) {
  475.                 return FALSE;
  476.             }
  477.             pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymSymbol + SIZEOFSYMBOL +
  478.                                        pSymSymbol->symName.length);
  479.         }
  480.     } while ( position != startPosition && position != 0 );
  481.  
  482.     return 0;
  483. }
  484.