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 / cofftocv.c next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  28.3 KB  |  993 lines

  1. /*++
  2.  
  3.  
  4. Copyright 1996 - 1997 Microsoft Corporation
  5.  
  6. Module Name:
  7.  
  8.     cv.c
  9.  
  10. Abstract:
  11.  
  12.     This module handles the conversion activities requires for converting
  13.     COFF debug data to CODEVIEW debug data.
  14.  
  15. Author:
  16.  
  17.     Wesley A. Witt (wesw) 19-April-1993
  18.  
  19. Environment:
  20.  
  21.     Win32, User Mode
  22.  
  23. --*/
  24.  
  25. #include <windows.h>
  26. #include <imagehlp.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30.  
  31. #include "cv.h"
  32. #define _SYMCVT_SOURCE_
  33. #include "symcvt.h"
  34. #include "cvcommon.h"
  35.  
  36. typedef struct tagOFFSETSORT {
  37.     DWORD       dwOffset;          // offset for the symbol
  38.     DWORD       dwSection;         // section number of the symbol
  39.     DATASYM32   *dataSym;          // pointer to the symbol info
  40. } OFFSETSORT;
  41.  
  42.  
  43. #define n_name          N.ShortName
  44. #define n_zeroes        N.Name.Short
  45. #define n_nptr          N.LongName[1]
  46. #define n_offset        N.Name.Long
  47.  
  48. static LPSTR GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable, char *s );
  49. DWORD  CreateModulesFromCoff( PPOINTERS p );
  50. DWORD  CreatePublicsFromCoff( PPOINTERS p );
  51. DWORD  CreateSegMapFromCoff( PPOINTERS p );
  52. DWORD  CreateSrcLinenumbers( PPOINTERS p );
  53.  
  54.  
  55.  
  56. LONG
  57. GuardPageFilterFunction(
  58.     DWORD                ec,
  59.     LPEXCEPTION_POINTERS lpep
  60.     )
  61.  
  62. /*++
  63.  
  64. Routine Description:
  65.  
  66.     This function catches all exceptions from the convertcofftocv function
  67.     and all that it calls.  The purpose of this function is allocate memory
  68.     when it is necessary.  This happens because the cofftocv conversion cannot
  69.     estimate the memory requirements before the conversion takes place.  To
  70.     handle this properly space in the virtual address space is reserved, the
  71.     reservation amount is 10 times the image size.  The first page is commited
  72.     and then the conversion is started.  When an access violation occurs and the
  73.     page that is trying to be access has a protection of noaccess then the
  74.     page is committed.  Any other exception is not handled.
  75.  
  76. Arguments:
  77.  
  78.     ec      - the ecxeption code (should be EXCEPTION_ACCESS_VIOLATION)
  79.     lpep    - pointer to the exception record and context record
  80.  
  81.  
  82. Return Value:
  83.  
  84.     EXCEPTION_CONTINUE_EXECUTION    - access violation handled
  85.     EXCEPTION_EXECUTE_HANDLER       - unknown exception and is not handled
  86.  
  87. --*/
  88.  
  89. {
  90.     LPVOID                      vaddr;
  91.     SYSTEM_INFO                 si;
  92.     MEMORY_BASIC_INFORMATION    mbi;
  93.  
  94.  
  95.     if (ec == EXCEPTION_ACCESS_VIOLATION) {
  96.         vaddr = (LPVOID)lpep->ExceptionRecord->ExceptionInformation[1];
  97.         VirtualQuery( vaddr, &mbi, sizeof(mbi) );
  98.         if (mbi.AllocationProtect == PAGE_NOACCESS) {
  99.             GetSystemInfo( &si );
  100.             VirtualAlloc( vaddr, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
  101.             return EXCEPTION_CONTINUE_EXECUTION;
  102.         }
  103.     }
  104.  
  105. //  return EXCEPTION_CONTINUE_SEARCH;
  106.     return EXCEPTION_EXECUTE_HANDLER;
  107. }
  108.  
  109.  
  110. BOOL
  111. ConvertCoffToCv( PPOINTERS p )
  112.  
  113. /*++
  114.  
  115. Routine Description:
  116.  
  117.     This is the control function for the conversion of COFF to CODEVIEW
  118.     debug data.  It calls individual functions for the conversion of
  119.     specific types of debug data.
  120.  
  121.  
  122. Arguments:
  123.  
  124.     p        - pointer to a POINTERS structure
  125.  
  126.  
  127. Return Value:
  128.  
  129.     TRUE     - conversion succeded
  130.     FALSE    - conversion failed
  131.  
  132. --*/
  133.  
  134. {
  135.     SYSTEM_INFO                 si;
  136.     DWORD                       cbsize;
  137.     BOOL                        rval = TRUE;
  138.  
  139.  
  140.     GetSystemInfo( &si );
  141.     cbsize = max( p->iptrs.fsize * 10, si.dwPageSize * 10 );
  142.  
  143.     //
  144.     // reserve all necessary pages
  145.     //
  146.     p->pCvCurr = p->pCvStart.ptr = VirtualAlloc( NULL, cbsize, MEM_RESERVE, PAGE_NOACCESS );
  147.  
  148.     //
  149.     // commit the first pages
  150.     //
  151.     VirtualAlloc( p->pCvCurr, min( cbsize, 5 * si.dwPageSize), MEM_COMMIT, PAGE_READWRITE );
  152.  
  153.  
  154.     try {
  155.  
  156.         CreateSignature( p );
  157.         CreateModulesFromCoff( p );
  158.         CreatePublicsFromCoff( p );
  159.         CreateSymbolHashTable( p );
  160.         CreateAddressSortTable( p );
  161.         CreateSegMapFromCoff( p );
  162. //      CreateSrcLinenumbers( p );
  163.         CreateDirectories( p );
  164.  
  165.     } except ( GuardPageFilterFunction( GetExceptionCode(), GetExceptionInformation() )) {
  166.  
  167.         VirtualFree( p->pCvStart.ptr, cbsize, MEM_DECOMMIT );
  168.         p->pCvStart.ptr = NULL;
  169.         rval = FALSE;
  170.  
  171.     }
  172.  
  173.     if (rval) {
  174.         p->pCvCurr = malloc( p->pCvStart.size );
  175.         CopyMemory( p->pCvCurr, p->pCvStart.ptr, p->pCvStart.size );
  176.         VirtualFree( p->pCvStart.ptr, cbsize, MEM_DECOMMIT );
  177.         p->pCvStart.ptr = p->pCvCurr;
  178.     }
  179.  
  180.     return rval;
  181. }
  182.  
  183.  
  184. DWORD
  185. CreateModulesFromCoff( PPOINTERS p )
  186.  
  187. /*++
  188.  
  189. Routine Description:
  190.  
  191.     Creates the individual CV module records.  There is one CV module
  192.     record for each .FILE record in the COFF debug data.  This is true
  193.     even if the COFF size is zero.
  194.  
  195.  
  196. Arguments:
  197.  
  198.     p        - pointer to a POINTERS structure
  199.  
  200.  
  201. Return Value:
  202.  
  203.     The number of modules that were created.
  204.  
  205. --*/
  206.  
  207. {
  208.     int                 i,j;
  209.     DWORD               dwOff;
  210.     DWORD               numaux;
  211.     DWORD               nummods = 0;
  212.     char                szSymName[256];
  213.     PIMAGE_SYMBOL       Symbol;
  214.     PIMAGE_AUX_SYMBOL   AuxSymbol;
  215.     OMFModule           *m = NULL;
  216.     int                 cSeg = 0;
  217.     char *              pb;
  218.     BOOLEAN             rgfCode[500];
  219.  
  220.  
  221.     memset(rgfCode, 2, sizeof(rgfCode));
  222.  
  223.     for (i=0,j=0, Symbol=p->iptrs.AllSymbols;
  224.          i<(int)p->iptrs.numberOfSymbols;
  225.          i+=numaux+1,Symbol+=numaux+1) {
  226.  
  227.         numaux = Symbol->NumberOfAuxSymbols;
  228.         if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE) {
  229.             j++;
  230.         }
  231.  
  232.     }
  233.  
  234.     p->pMi = (LPMODULEINFO) malloc( sizeof(MODULEINFO) * (j + 1) );
  235.     ZeroMemory( p->pMi, sizeof(MODULEINFO) * (j + 1) );
  236.  
  237.  
  238.     if (!j) {
  239.         //
  240.         //  Handle the situation where there are not any .file records in the
  241.         //  COFF symbol table.  This can happen for ROM images.  If this happens
  242.         //  then we will fabricate a bogus module.
  243.         //
  244.         m = (OMFModule *) p->pCvCurr;
  245.         m->ovlNumber = 0;
  246.         m->iLib = 0;
  247.         m->Style[0] = 'C';
  248.         m->Style[1] = 'V';
  249.  
  250.         for (i=0,j=0, dwOff=0; i<p->iptrs.numberOfSections; i++) {
  251.             if (p->iptrs.sectionHdrs[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) {
  252.                 m->SegInfo[j].Seg = i + 1;
  253.                 m->SegInfo[j].cbSeg = p->iptrs.sectionHdrs[i].SizeOfRawData;
  254.                 m->SegInfo[j++].Off = dwOff;
  255.             }
  256.             dwOff += p->iptrs.sectionHdrs[i].SizeOfRawData;
  257.         }
  258.  
  259.         m->cSeg = j;
  260.  
  261.         strcpy(szSymName,"foo.c");
  262.         pb = (char *) &m->SegInfo[j];
  263.         *pb = strlen(szSymName);
  264.         memcpy(pb+1, szSymName, *pb);
  265.  
  266.         p->pMi[0].name = strdup(szSymName);
  267.         p->pMi[0].iMod = 1;
  268.         p->pMi[0].cb = 0;
  269.         p->pMi[0].SrcModule = 0;
  270.  
  271.         m = NextMod(m);
  272.         p->modcnt = 1;
  273.         UpdatePtrs( p, &p->pCvModules, (LPVOID)m, 1 );
  274.  
  275.         return 1;
  276.     }
  277.  
  278.  
  279.     for (i=0, Symbol = p->iptrs.AllSymbols;
  280.          i < (int) p->iptrs.numberOfSymbols;
  281.          i += numaux + 1, Symbol += numaux + 1) {
  282.  
  283.         //
  284.         // Get the number of aux symbol records for this symbol
  285.         //
  286.         numaux = Symbol->NumberOfAuxSymbols;
  287.         AuxSymbol = (PIMAGE_AUX_SYMBOL) (Symbol+1);
  288.  
  289.         if ((i == 0) && ((Symbol+numaux+1)->StorageClass != IMAGE_SYM_CLASS_FILE)) {
  290.             //
  291.             // we have a situation where the first '.file' record
  292.             // is missing.  currently this only happens with the
  293.             // claxp compiler on alpha.
  294.             //
  295.             m = (OMFModule *) p->pCvCurr;
  296.             cSeg = 0;
  297.             m->ovlNumber = 0;
  298.             m->iLib = 0;
  299.             m->Style[0] = 'C';
  300.             m->Style[1] = 'V';
  301.             strcpy( szSymName, "fake.c" );
  302.         } else
  303.  
  304.         //
  305.         //  If this is a FILE record -- then we need to create a
  306.         //      module item to correspond to this file record.
  307.         //
  308.  
  309.         if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE) {
  310.             if (m == NULL) {
  311.                 m = (OMFModule *) p->pCvCurr;
  312.             } else {
  313.                 //
  314.                 //      Clean up the last item,  if we saw any
  315.                 //      section records then drop them in here
  316.                 //
  317.  
  318.                 if (cSeg > 0) {
  319.                     m->cSeg  = cSeg;
  320.                     pb = (char *) &m->SegInfo[cSeg];
  321.                     *pb = strlen(szSymName);
  322.                     memcpy(pb+1, szSymName, *pb);
  323.  
  324.                     p->pMi[nummods].name = strdup(szSymName);
  325.                     p->pMi[nummods].iMod = nummods + 1;
  326.                     p->pMi[nummods].cb = 0;
  327.                     p->pMi[nummods].SrcModule = 0;
  328.  
  329.                     m = NextMod(m);
  330.                     nummods++;
  331.                 }
  332.             }
  333.  
  334.             cSeg = 0;
  335.             m->ovlNumber        = 0;
  336.             m->iLib             = 0;
  337.             m->Style[0]         = 'C';
  338.             m->Style[1]         = 'V';
  339.  
  340.             /*
  341.              *  Save off the file name to use when we have finished
  342.              *  processing this module
  343.              */
  344.  
  345.             memcpy(szSymName, (char *)AuxSymbol, numaux*sizeof(IMAGE_AUX_SYMBOL));
  346.             szSymName[numaux*sizeof(IMAGE_AUX_SYMBOL)] = 0;
  347.  
  348.         }
  349.         /*
  350.          *  We have found a "SECTION" record.  Add the info to the
  351.          *      module record
  352.          */
  353.         else
  354.         if ((Symbol->SectionNumber & 0xffff) > 0xfff0) {
  355.             continue;
  356.         } else
  357.         if (Symbol->SectionNumber > sizeof(rgfCode)/sizeof(rgfCode[0])) {
  358.             return 0;
  359.         } else
  360.         if ((m != NULL) &&
  361.             (rgfCode[Symbol->SectionNumber] != 0) &&
  362.             (Symbol->StorageClass == IMAGE_SYM_CLASS_STATIC) &&
  363.             ((*Symbol->n_name == '.') ||
  364.              (Symbol->Type == IMAGE_SYM_TYPE_NULL)) &&
  365.             (Symbol->NumberOfAuxSymbols == 1) &&
  366.             (AuxSymbol->Section.Length != 0)) {
  367.  
  368.             if (rgfCode[Symbol->SectionNumber] == 2) {
  369.                 if ((p->iptrs.sectionHdrs[Symbol->SectionNumber - 1].
  370.                     Characteristics & IMAGE_SCN_CNT_CODE) == 0) {
  371.                     rgfCode[Symbol->SectionNumber] = 0;
  372.                     continue;
  373.                 }
  374.                 rgfCode[Symbol->SectionNumber] = 1;
  375.             }
  376.  
  377.             m->SegInfo[cSeg].Seg = Symbol->SectionNumber;
  378.             m->SegInfo[cSeg].cbSeg = AuxSymbol->Section.Length;
  379.             m->SegInfo[cSeg].Off = Symbol->Value -
  380.                      p->iptrs.sectionHdrs[Symbol->SectionNumber-1].
  381.                        VirtualAddress;
  382.             cSeg += 1;
  383.         }
  384.     }
  385.  
  386.     /*
  387.      *  Wrap up the last possible open module record
  388.      */
  389.  
  390.     if (m != NULL) {
  391.         if (cSeg > 0) {
  392.             m->cSeg             = cSeg;
  393.             pb = (char *) &m->SegInfo[cSeg];
  394.             *pb = strlen(szSymName);
  395.             memcpy(pb+1, szSymName, *pb);
  396.  
  397.             p->pMi[nummods].name = strdup(szSymName);
  398.             p->pMi[nummods].iMod = nummods + 1;
  399.             p->pMi[nummods].cb = 0;
  400.             p->pMi[nummods].SrcModule = 0;
  401.  
  402.             m = NextMod(m);
  403.             nummods++;
  404.         }
  405.     }
  406.  
  407.  
  408.     p->modcnt = nummods;
  409.     UpdatePtrs( p, &p->pCvModules, (LPVOID)m, nummods );
  410.  
  411.     return nummods;
  412. }
  413.  
  414.  
  415. DWORD
  416. CreatePublicsFromCoff( PPOINTERS p )
  417.  
  418. /*++
  419.  
  420. Routine Description:
  421.  
  422.     Creates the individual CV public symbol records.  There is one CV
  423.     public record created for each COFF symbol that is marked as EXTERNAL
  424.     and has a section number greater than zero.  The resulting CV publics
  425.     are sorted by section and offset.
  426.  
  427.  
  428. Arguments:
  429.  
  430.     p        - pointer to a POINTERS structure
  431.  
  432.  
  433. Return Value:
  434.  
  435.     The number of publics created.
  436.  
  437. --*/
  438.  
  439. {
  440.     int                 i;
  441.     DWORD               numaux;
  442.     DWORD               numsyms = 0;
  443.     char                szSymName[256];
  444.     PIMAGE_SYMBOL       Symbol;
  445.     OMFSymHash          *omfSymHash;
  446.     DATASYM32           *dataSym;
  447.     DATASYM32           *dataSym2;
  448.  
  449.     omfSymHash = (OMFSymHash *) p->pCvCurr;
  450.     dataSym = (DATASYM32 *) (PUCHAR)((DWORD)omfSymHash + sizeof(OMFSymHash));
  451.  
  452.     for (i= 0, Symbol = p->iptrs.AllSymbols;
  453.          i < p->iptrs.numberOfSymbols;
  454.          i += numaux + 1, Symbol += numaux + 1) {
  455.  
  456.         if ((Symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) &&
  457.             (Symbol->SectionNumber > 0)) {
  458.  
  459.             if (GetSymName( Symbol, p->iptrs.stringTable, szSymName )) {
  460.                 dataSym->rectyp = S_PUB32;
  461.                 dataSym->seg = Symbol->SectionNumber;
  462.                 dataSym->off = Symbol->Value -
  463.                      p->iptrs.sectionHdrs[Symbol->SectionNumber-1].VirtualAddress;
  464.                 dataSym->typind = 0;
  465.                 dataSym->name[0] = strlen( szSymName );
  466.                 strcpy( &dataSym->name[1], szSymName );
  467.                 dataSym2 = NextSym32( dataSym );
  468.                 dataSym->reclen = (USHORT) ((DWORD)dataSym2 - (DWORD)dataSym) - 2;
  469.                 dataSym = dataSym2;
  470.                 numsyms += 1;
  471.             }
  472.         }
  473.         numaux = Symbol->NumberOfAuxSymbols;
  474.     }
  475.  
  476.     UpdatePtrs( p, &p->pCvPublics, (LPVOID)dataSym, numsyms );
  477.  
  478.     omfSymHash->cbSymbol = p->pCvPublics.size - sizeof(OMFSymHash);
  479.     omfSymHash->symhash  = 0;
  480.     omfSymHash->addrhash = 0;
  481.     omfSymHash->cbHSym   = 0;
  482.     omfSymHash->cbHAddr  = 0;
  483.  
  484.     return numsyms;
  485. }                               /* CreatePublisFromCoff() */
  486.  
  487.  
  488. DWORD
  489. CreateSrcLinenumbers(
  490.     PPOINTERS p
  491.     )
  492.  
  493. /*++
  494.  
  495. Routine Description:
  496.  
  497.     Creates the individual CV soure line number records.
  498.  
  499.  
  500. Arguments:
  501.  
  502.     p        - pointer to a POINTERS structure
  503.  
  504.  
  505. Return Value:
  506.  
  507.     The number of publics created.
  508.  
  509. --*/
  510.  
  511. {
  512.     typedef struct _SEGINFO {
  513.         DWORD   start;
  514.         DWORD   end;
  515.         DWORD   cbLines;
  516.         DWORD   ptrLines;
  517.         DWORD   va;
  518.         DWORD   num;
  519.         BOOL    used;
  520.     } SEGINFO, *LPSEGINFO;
  521.  
  522.     typedef struct _SRCINFO {
  523.         LPSEGINFO   seg;
  524.         DWORD       numSeg;
  525.         DWORD       cbSeg;
  526.         CHAR        name[MAX_PATH+1];
  527.     } SRCINFO, *LPSRCINFO;
  528.  
  529.     typedef struct _SECTINFO {
  530.         DWORD       va;
  531.         DWORD       size;
  532.         DWORD       ptrLines;
  533.         DWORD       numLines;
  534.     } SECTINFO, *LPSECTINFO;
  535.  
  536.  
  537.     DWORD               i;
  538.     DWORD               j;
  539.     DWORD               k;
  540.     DWORD               l;
  541.     DWORD               actual;
  542.     DWORD               sidx;
  543.     DWORD               NumSrcFiles;
  544.     DWORD               SrcFileCnt;
  545.     DWORD               numaux;
  546.     PIMAGE_SYMBOL       Symbol;
  547.     PIMAGE_AUX_SYMBOL   AuxSymbol;
  548.     BOOL                first = TRUE;
  549.     OMFSourceModule     *SrcModule;
  550.     OMFSourceFile       *SrcFile;
  551.     OMFSourceLine       *SrcLine;
  552.     LPBYTE              lpb;
  553.     LPDWORD             lpdw;
  554.     PUSHORT             lps;
  555.     PUCHAR              lpc;
  556.     PIMAGE_LINENUMBER   pil, pilSave;
  557.     LPSRCINFO           si;
  558.     LPSECTINFO          sections;
  559.  
  560.  
  561.     //
  562.     // setup the section info structure
  563.     //
  564.     sections = (LPSECTINFO) malloc( sizeof(SECTINFO) * p->iptrs.numberOfSections );
  565.     for (i=0; i<(DWORD)p->iptrs.numberOfSections; i++) {
  566.         sections[i].va        = p->iptrs.sectionHdrs[i].VirtualAddress;
  567.         sections[i].size      = p->iptrs.sectionHdrs[i].SizeOfRawData;
  568.         sections[i].ptrLines  = p->iptrs.sectionHdrs[i].PointerToLinenumbers;
  569.         sections[i].numLines  = p->iptrs.sectionHdrs[i].NumberOfLinenumbers;
  570.     }
  571.  
  572.     //
  573.     // count the number of source files that contibute linenumbers
  574.     //
  575.     SrcFileCnt = 100;
  576.     si = (LPSRCINFO) malloc( sizeof(SRCINFO) * SrcFileCnt );
  577.     ZeroMemory( si, sizeof(SRCINFO) * SrcFileCnt );
  578.     for (i=0, j=0, Symbol=p->iptrs.AllSymbols, NumSrcFiles=0;
  579.          i<(DWORD)p->iptrs.numberOfSymbols;
  580.          i+=(numaux+1), Symbol+=(numaux + 1)) {
  581.  
  582.         numaux = Symbol->NumberOfAuxSymbols;
  583.         AuxSymbol = (PIMAGE_AUX_SYMBOL) (Symbol+1);
  584.  
  585.         if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE) {
  586.  
  587.             if (!first) {
  588.                 si[NumSrcFiles].cbSeg = j;
  589.                 NumSrcFiles++;
  590.                 if (NumSrcFiles == SrcFileCnt) {
  591.                     SrcFileCnt += 100;
  592.                     si = (LPSRCINFO) realloc( si, sizeof(SRCINFO) * SrcFileCnt );
  593.                 }
  594.             }
  595.  
  596.             memcpy(si[NumSrcFiles].name, (char *)AuxSymbol, numaux*sizeof(IMAGE_AUX_SYMBOL));
  597.             si[NumSrcFiles].name[numaux*sizeof(IMAGE_AUX_SYMBOL)] = 0;
  598.             si[NumSrcFiles].numSeg = 100;
  599.             si[NumSrcFiles].seg = (LPSEGINFO) malloc( sizeof(SEGINFO) * si[NumSrcFiles].numSeg );
  600.             ZeroMemory( si[NumSrcFiles].seg, sizeof(SEGINFO) * si[NumSrcFiles].numSeg );
  601.             first = FALSE;
  602.             j = 0;
  603.  
  604.         }
  605.  
  606.         //
  607.         // we do not want to look for segment information until we
  608.         // have found a valid source file
  609.         //
  610.         if (first) {
  611.             continue;
  612.         }
  613.  
  614.         //
  615.         // check the symbol to see if it is a segment record
  616.         //
  617.         if (numaux && Symbol->StorageClass == IMAGE_SYM_CLASS_STATIC &&
  618.             (*Symbol->n_name == '.' ||
  619.              ((Symbol->Type & 0xf) == IMAGE_SYM_TYPE_NULL && AuxSymbol->Section.Length)) &&
  620.             AuxSymbol->Section.NumberOfLinenumbers > 0) {
  621.  
  622.             //
  623.             // find the section that this symbol belongs to
  624.             //
  625.             for (k=0; k<(DWORD)p->iptrs.numberOfSections; k++) {
  626.                 if (Symbol->Value >= sections[k].va &&
  627.                     Symbol->Value < sections[k].va + sections[k].size) {
  628.  
  629.                     sidx = k;
  630.                     break;
  631.  
  632.                 }
  633.             }
  634.  
  635.             if (k != (DWORD)p->iptrs.numberOfSections &&
  636.                 p->iptrs.sectionHdrs[k].NumberOfLinenumbers) {
  637.  
  638.                 pil = (PIMAGE_LINENUMBER) (p->iptrs.fptr + sections[sidx].ptrLines);
  639.                 k = 0;
  640.  
  641.                 while( k < AuxSymbol->Section.NumberOfLinenumbers ) {
  642.  
  643.                     //
  644.                     // count the linenumbers in this section or sub-section
  645.                     //
  646.                     for ( pilSave=pil,l=0;
  647.                           k<AuxSymbol->Section.NumberOfLinenumbers;
  648.                           k++,pilSave++,l++ ) {
  649.  
  650.                         if ((k != (DWORD)AuxSymbol->Section.NumberOfLinenumbers-1) &&
  651.                             (pilSave->Linenumber > (pilSave+1)->Linenumber)) {
  652.                             pilSave++;
  653.                             l++;
  654.                             break;
  655.                         }
  656.  
  657.                     }
  658.  
  659.                     //
  660.                     // pil     == beginning of the range
  661.                     // pilSave == end of the range
  662.                     //
  663.  
  664.                     si[NumSrcFiles].seg[j].start =
  665.                                      (pil->Type.VirtualAddress - sections[sidx].va);
  666.  
  667.                     if (sections[sidx].numLines == l) {
  668.                         pilSave--;
  669.                         si[NumSrcFiles].seg[j].end =
  670.                                      (pilSave->Type.VirtualAddress - sections[sidx].va) + 1;
  671. //                                   (Symbol->Value - sections[sidx].va) + 1;
  672.                     } else {
  673.                         si[NumSrcFiles].seg[j].end =
  674.                                      (pilSave->Type.VirtualAddress - sections[sidx].va) - 1;
  675. //                                   (Symbol->Value - sections[sidx].va) - 1;
  676.                     }
  677.  
  678.                     si[NumSrcFiles].seg[j].ptrLines = sections[sidx].ptrLines;
  679.                     si[NumSrcFiles].seg[j].cbLines = l;
  680.                     si[NumSrcFiles].seg[j].va = sections[sidx].va;
  681.                     si[NumSrcFiles].seg[j].num = sidx + 1;
  682.                     si[NumSrcFiles].seg[j].used = FALSE;
  683.  
  684.                     sections[sidx].ptrLines += (l * sizeof(IMAGE_LINENUMBER));
  685.                     sections[sidx].numLines -= l;
  686.  
  687.                     j++;
  688.                     if (j == si[NumSrcFiles].numSeg) {
  689.                         si[NumSrcFiles].numSeg += 100;
  690.                         si[NumSrcFiles].seg = (LPSEGINFO) realloc( si[NumSrcFiles].seg, sizeof(SEGINFO) * si[NumSrcFiles].numSeg );
  691.                     }
  692.                     k++;
  693.                     pil = pilSave;
  694.                 }
  695.  
  696.             }
  697.  
  698.         }
  699.  
  700.     }
  701.  
  702.     lpb = (LPBYTE) p->pCvCurr;
  703.  
  704.     //
  705.     // if there is nothing to do then bail out
  706.     //
  707.     if (!NumSrcFiles) {
  708.         UpdatePtrs( p, &p->pCvSrcModules, (LPVOID)lpb, 0 );
  709.         return 0;
  710.     }
  711.  
  712.     for (i=0,actual=0,l=0; i<NumSrcFiles; i++) {
  713.  
  714.         if (si[i].cbSeg == 0) {
  715.             continue;
  716.         }
  717.  
  718.         //
  719.         // create the source module header
  720.         //
  721.         SrcModule = (OMFSourceModule*) lpb;
  722.         SrcModule->cFile = 1;
  723.         SrcModule->cSeg = (USHORT)si[i].cbSeg;
  724.         SrcModule->baseSrcFile[0] = 0;
  725.  
  726.         //
  727.         // write the start/end pairs
  728.         //
  729.         lpdw = (LPDWORD) ((LPBYTE)SrcModule + sizeof(OMFSourceModule));
  730.         for (k=0; k<si[i].cbSeg; k++) {
  731.             *lpdw++ = si[i].seg[k].start;
  732.             *lpdw++ = si[i].seg[k].end;
  733.         }
  734.  
  735.         //
  736.         // write the segment numbers
  737.         //
  738.         lps = (PUSHORT) lpdw;
  739.         for (k=0; k<si[i].cbSeg; k++) {
  740.             *lps++ = (USHORT)si[i].seg[k].num;
  741.         }
  742.  
  743.         //
  744.         // align to a dword boundry
  745.         //
  746.         lps = (PUSHORT) ((LPBYTE)lps + align(lps));
  747.  
  748.         //
  749.         // update the base pointer
  750.         //
  751.         SrcModule->baseSrcFile[0] = (DWORD) ((LPBYTE)lps - (LPBYTE)SrcModule);
  752.  
  753.         //
  754.         // write the source file record
  755.         //
  756.         SrcFile = (OMFSourceFile*) lps;
  757.         SrcFile->cSeg = (USHORT)si[i].cbSeg;
  758.         SrcFile->reserved = 0;
  759.  
  760.         for (k=0; k<si[i].cbSeg; k++) {
  761.             SrcFile->baseSrcLn[k] = 0;
  762.         }
  763.  
  764.         //
  765.         // write the start/end pairs
  766.         //
  767.         lpdw = (LPDWORD) ((LPBYTE)SrcFile + 4 + (4 * si[i].cbSeg));
  768.         for (k=0; k<si[i].cbSeg; k++) {
  769.             *lpdw++ = si[i].seg[k].start;
  770.             *lpdw++ = si[i].seg[k].end;
  771.         }
  772.  
  773.         //
  774.         // write the source file name
  775.         //
  776.         lpc = (PUCHAR) lpdw;
  777.         k = strlen(si[i].name);
  778.         *lpc++ = (UCHAR) k;
  779.         strcpy( lpc, si[i].name );
  780.         lpb = lpc + k;
  781.  
  782.         //
  783.         // find the module info struct
  784.         //
  785.         for (; l<p->modcnt; l++) {
  786.             if (stricmp(p->pMi[l].name,si[i].name)==0) {
  787.                 break;
  788.             }
  789.         }
  790.  
  791.         p->pMi[l].SrcModule = (DWORD) SrcModule;
  792.  
  793.         //
  794.         // align to a dword boundry
  795.         //
  796.         lpb = (LPBYTE) (lpb + align(lpb));
  797.  
  798.         //
  799.         // create the line number pairs
  800.         //
  801.         for (k=0; k<si[i].cbSeg; k++) {
  802.  
  803.             //
  804.             // find the first line number that applies to this segment
  805.             //
  806.             pil = (PIMAGE_LINENUMBER) (p->iptrs.fptr + si[i].seg[k].ptrLines);
  807.  
  808.             //
  809.             // update the base pointer
  810.             //
  811.             SrcFile->baseSrcLn[k] = (DWORD) (lpb - (LPBYTE)SrcModule);
  812.  
  813.             //
  814.             // write the line numbers
  815.             //
  816.             SrcLine = (OMFSourceLine*) lpb;
  817.             SrcLine->Seg = (USHORT)si[i].seg[k].num;
  818.             SrcLine->cLnOff = (USHORT) si[i].seg[k].cbLines;
  819.             pilSave = pil;
  820.             lpdw = (LPDWORD) (lpb + 4);
  821.             for (j=0; j<SrcLine->cLnOff; j++) {
  822.                 *lpdw++ = pil->Type.VirtualAddress - si[i].seg[k].va;
  823.                 pil++;
  824.             }
  825.             lps = (PUSHORT) lpdw;
  826.             pil = pilSave;
  827.             for (j=0; j<SrcLine->cLnOff; j++) {
  828.                 *lps++ = pil->Linenumber;
  829.                 pil++;
  830.             }
  831.  
  832.             //
  833.             // align to a dword boundry
  834.             //
  835.             lps = (PUSHORT) ((LPBYTE)lps + align(lps));
  836.  
  837.             lpb = (LPBYTE) lps;
  838.         }
  839.  
  840.         p->pMi[l].cb = (DWORD)lpb - (DWORD)SrcModule;
  841.         actual++;
  842.  
  843.     }
  844.  
  845.     UpdatePtrs( p, &p->pCvSrcModules, (LPVOID)lpb, actual );
  846.  
  847.     //
  848.     // cleanup all allocated memory
  849.     //
  850.  
  851.     free( sections );
  852.  
  853.     for (i=0; i<SrcFileCnt; i++) {
  854.         if (si[i].seg) {
  855.             free( si[i].seg );
  856.         }
  857.     }
  858.  
  859.     free( si );
  860.  
  861.     return NumSrcFiles;
  862. }                               /* CreateSrcLinenumbers() */
  863.  
  864.  
  865. DWORD
  866. CreateSegMapFromCoff( PPOINTERS p )
  867.  
  868. /*++
  869.  
  870. Routine Description:
  871.  
  872.     Creates the CV segment map.  The segment map is used by debuggers
  873.     to aid in address lookups.  One segment is created for each COFF
  874.     section in the image.
  875.  
  876. Arguments:
  877.  
  878.     p        - pointer to a POINTERS structure
  879.  
  880.  
  881. Return Value:
  882.  
  883.     The number of segments in the map.
  884.  
  885. --*/
  886.  
  887. {
  888.     int                         i;
  889.     SGM                         *sgm;
  890.     SGI                         *sgi;
  891.     PIMAGE_SECTION_HEADER       sh;
  892.  
  893.  
  894.     sgm = (SGM *) p->pCvCurr;
  895.     sgi = (SGI *) ((DWORD)p->pCvCurr + sizeof(SGM));
  896.  
  897.     sgm->cSeg = p->iptrs.numberOfSections;
  898.     sgm->cSegLog = p->iptrs.numberOfSections;
  899.  
  900.     sh = p->iptrs.sectionHdrs;
  901.  
  902.     for (i=0; i<p->iptrs.numberOfSections; i++, sh++) {
  903.         sgi->sgf.fRead        = (USHORT) (sh->Characteristics & IMAGE_SCN_MEM_READ) ==    IMAGE_SCN_MEM_READ;
  904.         sgi->sgf.fWrite       = (USHORT) (sh->Characteristics & IMAGE_SCN_MEM_WRITE) ==   IMAGE_SCN_MEM_WRITE;
  905.         sgi->sgf.fExecute     = (USHORT) (sh->Characteristics & IMAGE_SCN_MEM_EXECUTE) == IMAGE_SCN_MEM_EXECUTE;
  906.         sgi->sgf.f32Bit       = 1;
  907.         sgi->sgf.fSel         = 0;
  908.         sgi->sgf.fAbs         = 0;
  909.         sgi->sgf.fGroup       = 1;
  910.         sgi->iovl             = 0;
  911.         sgi->igr              = 0;
  912.         sgi->isgPhy           = (USHORT) i + 1;
  913.         sgi->isegName         = 0;
  914.         sgi->iclassName       = 0;
  915.         sgi->doffseg          = 0;
  916.         sgi->cbSeg            = sh->SizeOfRawData;
  917.         sgi++;
  918.     }
  919.  
  920.     UpdatePtrs( p, &p->pCvSegMap, (LPVOID)sgi, i );
  921.  
  922.     return i;
  923. }
  924.  
  925.  
  926. LPSTR
  927. GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable, char *s )
  928.  
  929. /*++
  930.  
  931. Routine Description:
  932.  
  933.     Extracts the COFF symbol from the image symbol pointer and puts
  934.     the ascii text in the character pointer passed in.
  935.  
  936.  
  937. Arguments:
  938.  
  939.     Symbol        - COFF Symbol Record
  940.     StringTable   - COFF string table
  941.     s             - buffer for the symbol string
  942.  
  943.  
  944. Return Value:
  945.  
  946.     void
  947.  
  948. --*/
  949.  
  950. {
  951.     DWORD i;
  952.  
  953.     if (Symbol->n_zeroes) {
  954.         for (i=0; i<8; i++) {
  955.             if ((Symbol->n_name[i]>0x1f) && (Symbol->n_name[i]<0x7f)) {
  956.                 *s++ = Symbol->n_name[i];
  957.             }
  958.         }
  959.         *s = 0;
  960.     }
  961.     else {
  962.         if (StringTable[Symbol->n_offset] == '?') {
  963.             i = UnDecorateSymbolName( &StringTable[Symbol->n_offset],
  964.                                   s,
  965.                                   255,
  966.                                   UNDNAME_COMPLETE                |
  967.                                   UNDNAME_NO_LEADING_UNDERSCORES  |
  968.                                   UNDNAME_NO_MS_KEYWORDS          |
  969.                                   UNDNAME_NO_FUNCTION_RETURNS     |
  970.                                   UNDNAME_NO_ALLOCATION_MODEL     |
  971.                                   UNDNAME_NO_ALLOCATION_LANGUAGE  |
  972.                                   UNDNAME_NO_MS_THISTYPE          |
  973.                                   UNDNAME_NO_CV_THISTYPE          |
  974.                                   UNDNAME_NO_THISTYPE             |
  975.                                   UNDNAME_NO_ACCESS_SPECIFIERS    |
  976.                                   UNDNAME_NO_THROW_SIGNATURES     |
  977.                                   UNDNAME_NO_MEMBER_TYPE          |
  978.                                   UNDNAME_NO_RETURN_UDT_MODEL     |
  979.                                   UNDNAME_NO_ARGUMENTS            |
  980.                                   UNDNAME_NO_SPECIAL_SYMS         |
  981.                                   UNDNAME_NAME_ONLY
  982.                                 );
  983.             if (!i) {
  984.                 return NULL;
  985.             }
  986.         } else {
  987.             strcpy( s, &StringTable[Symbol->n_offset] );
  988.         }
  989.     }
  990.  
  991.     return s;
  992. }
  993.