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 / cvcommon.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  20KB  |  830 lines

  1. /*++
  2.  
  3. Copyright 1996 - 1997 Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     cvcommon.c
  8.  
  9. Abstract:
  10.  
  11.     This file contians a set of common routines which are used in
  12.     doing symbol conversions from one type of symbols to CodeView
  13.     symbols.
  14.  
  15. Author:
  16.  
  17.     Wesley A. Witt (wesw) 19-April-1993
  18.     Jim Schaad (jimsch) 22 May 1993
  19.  
  20. --*/
  21.  
  22. #include        <windows.h>
  23. #include        <stdlib.h>
  24. #include        "cv.h"
  25. #include        "symcvt.h"
  26. #include        "cvcommon.h"
  27.  
  28. typedef struct tagSYMHASH {
  29.     DWORD       dwHashVal;         // hash value for the symbol
  30.     DWORD       dwHashBucket;      // hash bucket number
  31.     DATASYM16 * dataSym;           // pointer to the symbol info
  32. } SYMHASH;
  33.  
  34. typedef struct tagOFFSETSORT {
  35.     DWORD       dwOffset;          // offset for the symbol
  36.     DWORD       dwSection;         // section number of the symbol
  37.     DATASYM16 * dataSym;           // pointer to the symbol info
  38. } OFFSETSORT;
  39.  
  40.  
  41. int _CRTAPI1 SymHashCompare( const void *arg1, const void *arg2 );
  42. int _CRTAPI1 OffsetSortCompare( const void *arg1, const void *arg2 );
  43.  
  44.  
  45. DWORD
  46. CreateSignature( PPOINTERS p )
  47.  
  48. /*++
  49.  
  50. Routine Description:
  51.  
  52.     Creates the CODEVIEW signature record.  Currently this converter only
  53.     generates NB09 data (MS C/C++ 8.0).
  54.  
  55.  
  56. Arguments:
  57.  
  58.     p        - pointer to a POINTERS structure (see symcvt.h)
  59.  
  60.  
  61. Return Value:
  62.  
  63.     number of records generates, this is always 1.
  64.  
  65. --*/
  66.  
  67. {
  68.     OMFSignature        *omfSig;
  69.  
  70.     omfSig = (OMFSignature *) p->pCvCurr;
  71.     strcpy( omfSig->Signature, "NB09" );
  72.     omfSig->filepos = 0;
  73.     p->pCvStart.size += sizeof(OMFSignature);
  74.     p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFSignature);
  75.     return 1;
  76. }                               /* CreateSignature() */
  77.  
  78.  
  79. DWORD
  80. CreateDirectories( PPOINTERS p )
  81.  
  82. /*++
  83.  
  84. Routine Description:
  85.  
  86.     This is the control function for the generation of the CV directories.
  87.     It calls individual functions for the generation of specific types of
  88.     debug directories.
  89.  
  90.  
  91. Arguments:
  92.  
  93.     p        - pointer to a POINTERS structure (see symcvt.h)
  94.  
  95.  
  96. Return Value:
  97.  
  98.     the number of directories created.
  99.  
  100. --*/
  101.  
  102. {
  103.     OMFDirHeader        *omfDir = (OMFDirHeader *)p->pCvCurr;
  104.     OMFSignature        *omfSig = (OMFSignature *)p->pCvStart.ptr;
  105.     OMFDirEntry         *omfDirEntry = NULL;
  106.  
  107.     omfSig->filepos = (DWORD)p->pCvCurr - (DWORD)p->pCvStart.ptr;
  108.  
  109.     omfDir->cbDirHeader = sizeof(OMFDirHeader);
  110.     omfDir->cbDirEntry  = sizeof(OMFDirEntry);
  111.     omfDir->cDir        = 0;
  112.     omfDir->lfoNextDir  = 0;
  113.     omfDir->flags       = 0;
  114.  
  115.     p->pCvStart.size += sizeof(OMFDirHeader);
  116.     p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirHeader);
  117.  
  118.     omfDir->cDir += CreateModuleDirectoryEntries( p );
  119.     omfDir->cDir += CreatePublicDirectoryEntries( p );
  120.     omfDir->cDir += CreateSegMapDirectoryEntries( p );
  121.     omfDir->cDir += CreateSrcModulesDirectoryEntries( p );
  122.  
  123.     strcpy(p->pCvCurr, "NB090000");
  124.     p->pCvStart.size += 8;
  125.     p->pCvCurr += 8;
  126.     *((DWORD *) (p->pCvCurr-4)) = p->pCvStart.size;
  127.  
  128.     return omfDir->cDir;
  129. }                               /* CreateDirectories() */
  130.  
  131.  
  132. DWORD
  133. CreateModuleDirectoryEntries( PPOINTERS p )
  134.  
  135. /*++
  136.  
  137. Routine Description:
  138.  
  139.     Creates directory entries for each module in the image.
  140.  
  141.  
  142. Arguments:
  143.  
  144.     p        - pointer to a POINTERS structure (see symcvt.h)
  145.  
  146.  
  147. Return Value:
  148.  
  149.     the number of directory entries created.
  150.  
  151. --*/
  152.  
  153. {
  154.     OMFDirEntry   *omfDirEntry = NULL;
  155.     OMFModule     *m = NULL;
  156.     OMFModule     *mNext = NULL;
  157.     DWORD         i = 0;
  158.     DWORD         mSize = 0;
  159.     DWORD         lfo = (DWORD)p->pCvModules.ptr - (DWORD)p->pCvStart.ptr;
  160.  
  161.     m = (OMFModule *) p->pCvModules.ptr;
  162.     for (i=0; i<p->pCvModules.count; i++) {
  163.         mNext = NextMod(m);
  164.  
  165.         omfDirEntry = (OMFDirEntry *) p->pCvCurr;
  166.  
  167.         mSize = (DWORD)mNext - (DWORD)m;
  168.         omfDirEntry->SubSection = sstModule;
  169.         omfDirEntry->iMod       = (USHORT) i + 1;
  170.         omfDirEntry->lfo        = lfo;
  171.         omfDirEntry->cb         = mSize;
  172.  
  173.         lfo += mSize;
  174.  
  175.         p->pCvStart.size += sizeof(OMFDirEntry);
  176.         p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
  177.  
  178.         m = mNext;
  179.     }
  180.  
  181.     return p->pCvModules.count;
  182. }                               /* CreateModuleDirectoryEntries() */
  183.  
  184.  
  185. DWORD
  186. CreatePublicDirectoryEntries( PPOINTERS p )
  187.  
  188. /*++
  189.  
  190. Routine Description:
  191.  
  192.     Creates the directory entry for the global publics.
  193.  
  194. Arguments:
  195.  
  196.     p        - pointer to a POINTERS structure (see symcvt.h)
  197.  
  198.  
  199. Return Value:
  200.  
  201.     the number of directory entries created, always 1.
  202.  
  203. --*/
  204.  
  205. {
  206.     OMFDirEntry   *omfDirEntry = (OMFDirEntry *) p->pCvCurr;
  207.  
  208.     omfDirEntry->SubSection = sstGlobalPub;
  209.     omfDirEntry->iMod       = 0xffff;
  210.     omfDirEntry->lfo        = (DWORD)p->pCvPublics.ptr - (DWORD)p->pCvStart.ptr;
  211.     omfDirEntry->cb         = p->pCvPublics.size;
  212.  
  213.     p->pCvStart.size += sizeof(OMFDirEntry);
  214.     p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
  215.  
  216.     return 1;
  217. }                               /* CreatePublicDirectoryEntries() */
  218.  
  219.  
  220. DWORD
  221. CreateSegMapDirectoryEntries( PPOINTERS p )
  222.  
  223. /*++
  224.  
  225. Routine Description:
  226.  
  227.     Creates the directory entry for the segment map.
  228.  
  229.  
  230. Arguments:
  231.  
  232.     p        - pointer to a POINTERS structure (see symcvt.h)
  233.  
  234.  
  235. Return Value:
  236.  
  237.     the number of directory entries created, always 1.
  238.  
  239. --*/
  240.  
  241. {
  242.     OMFDirEntry   *omfDirEntry = (OMFDirEntry *) p->pCvCurr;
  243.  
  244.     omfDirEntry->SubSection = sstSegMap;
  245.     omfDirEntry->iMod       = 0xffff;
  246.     omfDirEntry->lfo        = (DWORD)p->pCvSegMap.ptr - (DWORD)p->pCvStart.ptr;
  247.     omfDirEntry->cb         = p->pCvSegMap.size;
  248.  
  249.     p->pCvStart.size += sizeof(OMFDirEntry);
  250.     p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
  251.  
  252.     return 1;
  253. }                               /* CreateSegMapDirectoryEntries() */
  254.  
  255.  
  256. DWORD
  257. CreateSrcModulesDirectoryEntries( PPOINTERS p )
  258.  
  259. /*++
  260.  
  261. Routine Description:
  262.  
  263.     Creates directory entries for each source module in the image.
  264.  
  265.  
  266. Arguments:
  267.  
  268.     p        - pointer to a POINTERS structure (see symcvt.h)
  269.  
  270.  
  271. Return Value:
  272.  
  273.     the number of directory entries created.
  274.  
  275. --*/
  276.  
  277. {
  278.     OMFDirEntry         *omfDirEntry = NULL;
  279.     DWORD               i;
  280.     DWORD               lfo = (DWORD)p->pCvSrcModules.ptr - (DWORD)p->pCvStart.ptr;
  281.     DWORD               j = lfo;
  282.     OMFSourceModule     *m;
  283.  
  284.  
  285.     //
  286.     // if there were no linenumber conversions then bail out
  287.     //
  288.     if (!p->pCvSrcModules.count) {
  289.         return 0;
  290.     }
  291.  
  292.     for (i=0; i<p->pCvSrcModules.count; i++) {
  293.  
  294.         if (!p->pMi[i].SrcModule) {
  295.             continue;
  296.         }
  297.  
  298.         omfDirEntry = (OMFDirEntry *) p->pCvCurr;
  299.  
  300.         omfDirEntry->SubSection = sstSrcModule;
  301.         omfDirEntry->iMod = (USHORT) p->pMi[i].iMod;
  302.         omfDirEntry->lfo = lfo;
  303.         omfDirEntry->cb = p->pMi[i].cb;
  304.  
  305.         m = (OMFSourceModule*) p->pMi[i].SrcModule;
  306.  
  307.         lfo += omfDirEntry->cb;
  308.  
  309.         p->pCvStart.size += sizeof(OMFDirEntry);
  310.         p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
  311.     }
  312.  
  313.     free( p->pMi );
  314.  
  315.     return p->pCvSrcModules.count;
  316. }                               /* CreateSrcModulesDirectoryEntries() */
  317.  
  318.  
  319.  
  320. #define byt_toupper(b)      (b & 0xDF)
  321. #define dwrd_toupper(dw)    (dw & 0xDFDFDFDF)
  322.  
  323. DWORD
  324. DWordXorLrl( char *szSym )
  325.  
  326. /*++
  327.  
  328. Routine Description:
  329.  
  330.     This function will take an ascii character string and generate
  331.     a hash for that string.  The hash algorithm is the CV NB09 hash
  332.     algorithm.
  333.  
  334.  
  335. Arguments:
  336.  
  337.     szSym    - a character pointer, the first char is the string length
  338.  
  339.  
  340. Return Value:
  341.  
  342.     The generated hash value.
  343.  
  344. --*/
  345.  
  346. {
  347.     char                *pName = szSym+1;
  348.     int                 cb =  *szSym;
  349.     char                *pch;
  350.     char                c;
  351.     DWORD               hash = 0, ulEnd = 0;
  352.     DWORD UNALIGNED     *pul;
  353.  
  354.     // Replace all "::" with "__" for hashing purposes
  355.  
  356.     c = *(pName+cb);
  357.     *(pName+cb) = '\0';
  358.     pch = strstr( pName, "::" );
  359.     if ( pch ) {
  360.         *pch++ = '_';
  361.         *pch   = '_';
  362.     }
  363.     *(pName+cb) = c;
  364.  
  365.     // If we're standard call, skip the trailing @999
  366.  
  367.     pch = pName + cb - 1;
  368.     while (isdigit(*pch)) {
  369.         pch--;
  370.     }
  371.  
  372.     if (*pch == '@') {
  373.         cb = pch - pName;
  374.     }
  375.  
  376.     // If we're fastcall, skip the leading '@'
  377.  
  378.     if (*pName == '@') {
  379.         pName++;
  380.         cb--;
  381.     }
  382.  
  383.     // Calculate the odd byte hash.
  384.  
  385.     while (cb & 3) {
  386.         ulEnd |= byt_toupper (pName[cb-1]);
  387.         ulEnd <<=8;
  388.         cb--;
  389.     }
  390.  
  391.     pul = (DWORD UNALIGNED *)pName;
  392.  
  393.     // calculate the dword hash for the remaining
  394.  
  395.     while (cb) {
  396.         hash ^= dwrd_toupper(*pul);
  397.         hash = _lrotl (hash, 4);
  398.         pul++;
  399.         cb -=4;
  400.     }
  401.  
  402.     // or in the remainder
  403.  
  404.     hash ^= ulEnd;
  405.  
  406.     return hash;
  407. }                               /* DWordXorLrl() */
  408.  
  409.  
  410.  
  411. OMFModule *
  412. NextMod(
  413.         OMFModule *             pMod
  414.         )
  415. /*++
  416.  
  417. Routine Description:
  418.  
  419.     description-of-function.
  420.  
  421. Arguments:
  422.  
  423.     argument-name - Supplies | Returns description of argument.
  424.     .
  425.     .
  426.  
  427. Return Value:
  428.  
  429.     return-value - Description of conditions needed to return value. - or -
  430.     None.
  431.  
  432. --*/
  433.  
  434. {
  435.     char *      pb;
  436.  
  437.     pb = (char *) &(pMod->SegInfo[pMod->cSeg]);
  438.     pb += *pb + 1;
  439.     pb = (char *) (((unsigned long) pb + 3) & ~3);
  440.  
  441.     return (OMFModule *) pb;
  442. }                               /* NextMod() */
  443.  
  444.  
  445.  
  446. int
  447. _CRTAPI1
  448. SymHashCompare(
  449.                const void *     arg1,
  450.                const void *     arg2
  451.                )
  452. /*++
  453.  
  454. Routine Description:
  455.  
  456.     Sort compare function for sorting SYMHASH records by hashed
  457.     bucket number.
  458.  
  459.  
  460. Arguments:
  461.  
  462.     arg1     - record #1
  463.     arg2     - record #2
  464.  
  465.  
  466. Return Value:
  467.  
  468.    -1        - record #1 is < record #2
  469.     0        - records are equal
  470.     1        - record #1 is > record #2
  471.  
  472. --*/
  473.  
  474. {
  475.     if (((SYMHASH*)arg1)->dwHashBucket < ((SYMHASH*)arg2)->dwHashBucket) {
  476.         return -1;
  477.     }
  478.     if (((SYMHASH*)arg1)->dwHashBucket > ((SYMHASH*)arg2)->dwHashBucket) {
  479.         return 1;
  480.     }
  481.  
  482.     // BUGBUG: Should we second sort on the hash value?
  483.  
  484.     return 0;
  485. }                               /* SymHashCompare() */
  486.  
  487.  
  488. // Symbol Offset/Hash structure
  489.  
  490. typedef struct _SOH {
  491.     DWORD uoff;
  492.     DWORD ulHash;
  493. } SOH;
  494.  
  495. #define MINHASH     6           // Don't create a hash with fewer than 6 slots
  496.  
  497. DWORD
  498. CreateSymbolHashTable(
  499.     PPOINTERS p
  500.     )
  501. /*++
  502.  
  503. Routine Description:
  504.  
  505.     Creates the CV symbol hash table.  This hash table is used
  506.     primarily by debuggers to access symbols in a quick manner.
  507.  
  508. Arguments:
  509.  
  510.     p        - pointer to a POINTERS structure (see symcvt.h)
  511.  
  512. Return Value:
  513.  
  514.     The number of buckets is the hash table.
  515.  
  516. --*/
  517. {
  518.     DWORD           i;
  519.     DWORD           j;
  520.     int             k;
  521.     DWORD           numsyms;
  522.     DWORD           numbuckets;
  523.     OMFSymHash      *omfSymHash;
  524.     DATASYM16       *dataSymStart;
  525.     DATASYM16       *dataSym;
  526.     LPVOID          pHashData;
  527.     USHORT          *pCHash;
  528.     DWORD           *pHashTable;
  529.     DWORD           *pBucketCounts;
  530.     DWORD           *pChainTable;
  531.     SYMHASH         *symHashStart;
  532.     SYMHASH         *symHash;
  533. //    DWORD           dwHashVal;
  534.     char *          sz;
  535.  
  536.     numsyms = p->pCvPublics.count;
  537.     numbuckets = (numsyms+9) / 10;
  538.     numbuckets = (1 + numbuckets) & ~1;
  539.     numbuckets = __max(numbuckets, MINHASH);
  540.  
  541.     symHashStart =
  542.     symHash = (SYMHASH *) malloc( numsyms * sizeof(SYMHASH) );
  543.     if (symHashStart == NULL) {
  544.         return 0;
  545.     }
  546.  
  547.     memset( symHashStart, 0, numsyms * sizeof(SYMHASH) );
  548.  
  549.     pHashData = (LPVOID) p->pCvCurr;
  550.     pCHash = (USHORT *) pHashData;
  551.     pHashTable = (DWORD *) ((DWORD)pHashData + sizeof(DWORD));
  552.     pBucketCounts = (DWORD *) ((DWORD)pHashTable +
  553.                                   (sizeof(DWORD) * numbuckets));
  554.     memset(pBucketCounts, 0, sizeof(DWORD) * numbuckets);
  555.  
  556.     pChainTable = (DWORD *) ((DWORD)pBucketCounts +
  557.                                  ((sizeof(ULONG) * numbuckets)));
  558.  
  559.     omfSymHash = (OMFSymHash *) p->pCvPublics.ptr;
  560.     dataSymStart =
  561.     dataSym = (DATASYM16 *) ((DWORD)omfSymHash + sizeof(OMFSymHash));
  562.  
  563.     *pCHash = (USHORT)numbuckets;
  564.  
  565.     /*
  566.      *  cruise thru the symbols and calculate the hash values
  567.      *  and the hash bucket numbers; save the info away for later use
  568.      */
  569.     for (i=0; i<numsyms; i++, symHash++) {
  570.         switch( dataSym->rectyp ) {
  571.         case S_PUB16:
  572.             sz = dataSym->name;
  573.             break;
  574.  
  575.         case S_PUB32:
  576.             sz = ((DATASYM32 *) dataSym)->name;
  577.             break;
  578.  
  579.         default:
  580.             continue;
  581.         }
  582.  
  583.         symHash->dwHashVal = DWordXorLrl( sz );
  584.         symHash->dwHashBucket = symHash->dwHashVal % numbuckets;
  585.         pBucketCounts[symHash->dwHashBucket] += 1;
  586.         symHash->dataSym = dataSym;
  587.         dataSym = ((DATASYM16 *) ((char *) dataSym + dataSym->reclen + 2));
  588.     }
  589.  
  590.     qsort( (void*)symHashStart, numsyms, sizeof(SYMHASH), SymHashCompare );
  591.  
  592.     j = (char *)pChainTable - (char *)pHashData;
  593.     for (i=0, k = 0;
  594.          i < numbuckets;
  595.          k += pBucketCounts[i], i += 1, pHashTable++ )
  596.     {
  597.         *pHashTable = (DWORD) j + (k * sizeof(DWORD) * 2);
  598.     }
  599.  
  600.     dataSymStart = (DATASYM16 *) (PUCHAR)((DWORD)omfSymHash);
  601.     for (i=0,symHash=symHashStart; i<numsyms; i++,symHash++,pChainTable++) {
  602.         *pChainTable = (DWORD) (DWORD)symHash->dataSym - (DWORD)dataSymStart;
  603.         ++pChainTable;
  604.         *pChainTable = symHash->dwHashVal;
  605.     }
  606.  
  607.     UpdatePtrs( p, &p->pCvSymHash, (LPVOID)pChainTable, numsyms );
  608.  
  609.     omfSymHash->symhash = 10;
  610.     omfSymHash->cbHSym = p->pCvSymHash.size;
  611.  
  612.     free( symHashStart );
  613.  
  614.     return numbuckets;
  615. }                               /* CreateSymbolHashTable() */
  616.  
  617.  
  618. VOID
  619. UpdatePtrs( PPOINTERS p, PPTRINFO pi, LPVOID lpv, DWORD count )
  620.  
  621. /*++
  622.  
  623. Routine Description:
  624.  
  625.     This function is called by ALL functions that put data into the
  626.     CV data area.  After putting the data into the CV memory this function
  627.     must be called.  It will adjust all of the necessary pointers so the
  628.     the next guy doesn't get hosed.
  629.  
  630.  
  631. Arguments:
  632.  
  633.     p        - pointer to a POINTERS structure (see symcvt.h)
  634.     pi       - the CV pointer that is to be updated
  635.     lpv      - current pointer into the CV data
  636.     count    - the number of items that were placed into the CV data
  637.  
  638.  
  639. Return Value:
  640.  
  641.     void
  642.  
  643. --*/
  644.  
  645. {
  646.     if (!count) {
  647.         return;
  648.     }
  649.  
  650.     pi->ptr = p->pCvCurr;
  651.     pi->size = (DWORD) ((DWORD)lpv - (DWORD)p->pCvCurr);
  652.     pi->count = count;
  653.  
  654.     p->pCvStart.size += pi->size;
  655.     p->pCvCurr = (PUCHAR) lpv;
  656.  
  657.     return;
  658. }                               /* UpdatePtrs() */
  659.  
  660.  
  661. int
  662. _CRTAPI1
  663. OffsetSortCompare( const void *arg1, const void *arg2 )
  664.  
  665. /*++
  666.  
  667. Routine Description:
  668.  
  669.     Sort compare function for sorting OFFETSORT records by section number.
  670.  
  671.  
  672. Arguments:
  673.  
  674.     arg1     - record #1
  675.     arg2     - record #2
  676.  
  677.  
  678. Return Value:
  679.  
  680.    -1        - record #1 is < record #2
  681.     0        - records are equal
  682.     1        - record #1 is > record #2
  683.  
  684. --*/
  685.  
  686. {
  687.     if (((OFFSETSORT*)arg1)->dwSection < ((OFFSETSORT*)arg2)->dwSection) {
  688.         return -1;
  689.     }
  690.     if (((OFFSETSORT*)arg1)->dwSection > ((OFFSETSORT*)arg2)->dwSection) {
  691.         return 1;
  692.     }
  693.     if (((OFFSETSORT*)arg1)->dwOffset < ((OFFSETSORT*)arg2)->dwOffset) {
  694.         return -1;
  695.     }
  696.     if (((OFFSETSORT*)arg1)->dwOffset > ((OFFSETSORT*)arg2)->dwOffset) {
  697.         return 1;
  698.     }
  699.     return 0;
  700. }                               /* OffsetSortCompare() */
  701.  
  702.  
  703. DWORD
  704. CreateAddressSortTable( PPOINTERS p )
  705.  
  706. /*++
  707.  
  708. Routine Description:
  709.  
  710.  
  711.     Creates the CV address sort table. This hash table is used
  712.     primarily by debuggers to access symbols in a quick manner when
  713.     all you have is an address.
  714.  
  715. Arguments:
  716.  
  717.     p        - pointer to a POINTERS structure (see symcvt.h)
  718.  
  719.  
  720. Return Value:
  721.  
  722.     The number of sections in the table.
  723.  
  724. --*/
  725.  
  726. {
  727.     DWORD               i;
  728.     DWORD               j;
  729.     int                 k;
  730.     DWORD               numsyms = p->pCvPublics.count;
  731.     DWORD               numsections;
  732.     OMFSymHash          *omfSymHash;
  733.     DATASYM16           *dataSymStart;
  734.     DATASYM16           *dataSym;
  735.     LPVOID              pAddressData;
  736.     USHORT              *pCSeg;
  737.     DWORD               *pSegTable;
  738.     DWORD               *pOffsetCounts;
  739.     DWORD               *pOffsetTable;
  740.     OFFSETSORT          *pOffsetSortStart;
  741.     OFFSETSORT          *pOffsetSort;
  742.  
  743.     extern int          CSymSegs;
  744.  
  745.     if (p->iptrs.fileHdr) {
  746.         numsections = p->iptrs.fileHdr->NumberOfSections;
  747.     } else if (p->iptrs.sepHdr) {
  748.         numsections = p->iptrs.sepHdr->NumberOfSections;
  749.     } else {
  750.         numsections = CSymSegs;
  751.     }
  752.  
  753.     pOffsetSortStart =
  754.       pOffsetSort = (OFFSETSORT *) malloc( numsyms * sizeof(OFFSETSORT) );
  755.  
  756.     if (pOffsetSort == NULL) {
  757.         return 0;
  758.     }
  759.  
  760.     memset( pOffsetSortStart, 0, numsyms * sizeof(OFFSETSORT) );
  761.  
  762.     pAddressData = (LPVOID) p->pCvCurr;
  763.     pCSeg = (USHORT *) pAddressData;
  764.     pSegTable = (DWORD *) ((DWORD)pAddressData + sizeof(DWORD));
  765.     pOffsetCounts = (DWORD *) ((DWORD)pSegTable +
  766.                                 (sizeof(DWORD) * numsections));
  767.     pOffsetTable = (DWORD *) ((DWORD)pOffsetCounts +
  768.                               ((sizeof(DWORD) * numsections)));
  769. //    if (numsections & 1) {
  770. //        pOffsetTable = (DWORD *) ((DWORD)pOffsetTable + 2);
  771. //    }
  772.  
  773.     omfSymHash = (OMFSymHash *) p->pCvPublics.ptr;
  774.     dataSymStart =
  775.       dataSym = (DATASYM16 *) ((DWORD)omfSymHash + sizeof(OMFSymHash));
  776.  
  777.     *pCSeg = (USHORT)numsections;
  778.  
  779.     for (i=0;
  780.          i<numsyms;
  781.          i++, pOffsetSort++)
  782.     {
  783.         switch(dataSym->rectyp) {
  784.         case S_PUB16:
  785.             pOffsetSort->dwOffset = dataSym->off;
  786.             pOffsetSort->dwSection = dataSym->seg;
  787.             break;
  788.  
  789.         case S_PUB32:
  790.             pOffsetSort->dwOffset = ((DATASYM32 *) dataSym)->off;
  791.             pOffsetSort->dwSection = ((DATASYM32 *) dataSym)->seg;
  792.         }
  793.  
  794.         pOffsetSort->dataSym = dataSym;
  795.         pOffsetCounts[pOffsetSort->dwSection - 1] += 1;
  796.         dataSym = ((DATASYM16 *) ((char *) dataSym + dataSym->reclen + 2));    }
  797.  
  798. //#if 0
  799.     qsort((void*)pOffsetSortStart, numsyms, sizeof(OFFSETSORT),
  800.           OffsetSortCompare );
  801. //#endif
  802.  
  803.     j = (DWORD) (DWORD)pOffsetTable - (DWORD)pAddressData;
  804.     for (i=0, k=0;
  805.          i < numsections;
  806.          k += pOffsetCounts[i], i += 1, pSegTable++)
  807.     {
  808.         *pSegTable = (DWORD) j + (k * sizeof(DWORD) * 2);
  809.     }
  810.  
  811.     dataSymStart = (DATASYM16 *) (PUCHAR)((DWORD)omfSymHash);
  812.     for (i=0, pOffsetSort=pOffsetSortStart;
  813.          i < numsyms;
  814.          i++, pOffsetSort++, pOffsetTable++)
  815.     {
  816.         *pOffsetTable = (DWORD)pOffsetSort->dataSym - (DWORD)dataSymStart;
  817.         pOffsetTable++;
  818.         *pOffsetTable = pOffsetSort->dwOffset;
  819.     }
  820.  
  821.     UpdatePtrs( p, &p->pCvAddrSort, (LPVOID)pOffsetTable, numsyms );
  822.  
  823.     omfSymHash->addrhash = 12;
  824.     omfSymHash->cbHAddr = p->pCvAddrSort.size;
  825.  
  826.     free( pOffsetSortStart );
  827.  
  828.     return numsections;
  829. }                               /* CreateAddressSort() */
  830.