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 / file.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  14KB  |  473 lines

  1. /*++
  2.  
  3.  
  4. Copyright 1996 - 1997 Microsoft Corporation
  5.  
  6. Module Name:
  7.  
  8.     file.c
  9.  
  10. Abstract:
  11.  
  12.     This module handles all file i/o for SYMCVT.  This includes the
  13.     mapping of all files and establishing all file pointers for the
  14.     mapped file(s).
  15.  
  16. Author:
  17.  
  18.     Wesley A. Witt (wesw) 19-April-1993
  19.  
  20. Environment:
  21.  
  22.     Win32, User Mode
  23.  
  24. --*/
  25.  
  26. #include <windows.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <stdio.h>
  30.  
  31. #define _SYMCVT_SOURCE_
  32. #include "symcvt.h"
  33.  
  34. static BOOL CalculateOutputFilePointers( PIMAGEPOINTERS pi, PIMAGEPOINTERS po );
  35. static BOOL CalculateInputFilePointers( PIMAGEPOINTERS p );
  36.  
  37.  
  38.  
  39. BOOL
  40. MapInputFile (
  41.               PPOINTERS   p,
  42.               HANDLE      hFile,
  43.               char *      fname
  44.               )
  45. /*++
  46.  
  47. Routine Description:
  48.  
  49.     Maps the input file specified by the fname argument and saves the
  50.     file handle & file pointer in the POINTERS structure.
  51.  
  52.  
  53. Arguments:
  54.  
  55.     p        - Supplies pointer to a POINTERS structure
  56.     hFile    - OPTIONAL Supplies handle for file if already open
  57.     fname    - Supplies ascii string for the file name
  58.  
  59. Return Value:
  60.  
  61.     TRUE     - file mapped ok
  62.     FALSE    - file could not be mapped
  63.  
  64. --*/
  65.  
  66. {
  67.     BOOL        rVal = TRUE;
  68.     DWORD       lwFsize;
  69.  
  70.     memset( p, 0, sizeof(POINTERS) );
  71.  
  72.     strcpy( p->iptrs.szName, fname );
  73.  
  74.     if (hFile != NULL) {
  75.  
  76.         p->iptrs.hFile = hFile;
  77.  
  78.     } else {
  79.  
  80.         p->iptrs.hFile = CreateFile( p->iptrs.szName,
  81.                                     GENERIC_READ,
  82.                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
  83.                                     NULL,
  84.                                     OPEN_EXISTING,
  85.                                     0,
  86.                                     NULL );
  87.     }
  88.  
  89.     if (p->iptrs.hFile == INVALID_HANDLE_VALUE) {
  90.  
  91.         rVal = FALSE;
  92.  
  93.     } else {
  94.  
  95.         p->iptrs.fsize = GetFileSize( p->iptrs.hFile, NULL );
  96.         if (lwFsize == 0xffffffff) {
  97.             ;
  98.         }
  99.         p->iptrs.hMap = CreateFileMapping( p->iptrs.hFile,
  100.                                            NULL,
  101.                                            PAGE_READONLY,
  102.                                            0,
  103.                                            0,
  104.                                            NULL
  105.                                          );
  106.  
  107.         if (p->iptrs.hMap == INVALID_HANDLE_VALUE) {
  108.  
  109.             p->iptrs.hMap = NULL;
  110.             rVal = FALSE;
  111.  
  112.         } else {
  113.  
  114.             p->iptrs.fptr = MapViewOfFile( p->iptrs.hMap,
  115.                                            FILE_MAP_READ,
  116.                                            0, 0, 0 );
  117.             if (p->iptrs.fptr == NULL) {
  118.                 CloseHandle( p->iptrs.hMap );
  119.                 p->iptrs.hMap = NULL;
  120.                 rVal = FALSE;
  121.             }
  122.         }
  123.     }
  124.  
  125.     if (!hFile && p->iptrs.hFile != INVALID_HANDLE_VALUE) {
  126.         CloseHandle(p->iptrs.hFile);
  127.         p->iptrs.hFile = NULL;
  128.     }
  129.  
  130.     return rVal;
  131. }                               /* MapInputFile() */
  132.  
  133.  
  134.  
  135. BOOL
  136. UnMapInputFile (
  137.     PPOINTERS p
  138.     )
  139. /*++
  140.  
  141. Routine Description:
  142.  
  143.     Unmaps the input file specified by the fname argument and then
  144.     closes the file.
  145.  
  146.  
  147. Arguments:
  148.  
  149.     p        - pointer to a POINTERS structure
  150.  
  151. Return Value:
  152.  
  153.     TRUE     - file mapped ok
  154.     FALSE    - file could not be mapped
  155.  
  156. --*/
  157.  
  158. {
  159.     if ( p->iptrs.fptr ) {
  160.         UnmapViewOfFile( p->iptrs.fptr );
  161.         p->iptrs.fptr = NULL;
  162.     }
  163.     if ( p->iptrs.hMap ) {
  164.         CloseHandle( p->iptrs.hMap );
  165.         p->iptrs.hMap = NULL;
  166.     }
  167.     if (p->iptrs.hFile != NULL) {
  168.         CloseHandle( p->iptrs.hFile );
  169.         p->iptrs.hFile = NULL;
  170.     }
  171.     return TRUE;
  172. }                               /* UnMapInputFile() */
  173.  
  174.  
  175. BOOL
  176. FillInSeparateImagePointers(
  177.                             PIMAGEPOINTERS      p
  178.                             )
  179. /*++
  180.  
  181. Routine Description:
  182.  
  183.     This routine will go through the exe file and fill in the
  184.     pointers needed relative to the separate debug information files
  185.  
  186. Arguments:
  187.  
  188.     p  - Supplies the structure to fill in
  189.  
  190. Return Value:
  191.  
  192.     TRUE if successful and FALSE otherwise.
  193.  
  194. --*/
  195.  
  196. {
  197.     int                         li;
  198.     int                         numDebugDirs;
  199.     PIMAGE_DEBUG_DIRECTORY      pDebugDir;
  200.     PIMAGE_COFF_SYMBOLS_HEADER  pCoffHdr;
  201.  
  202.     p->sectionHdrs = (PIMAGE_SECTION_HEADER)
  203.       (p->fptr + sizeof(IMAGE_SEPARATE_DEBUG_HEADER));
  204.  
  205.     numDebugDirs = p->sepHdr->DebugDirectorySize/sizeof(IMAGE_DEBUG_DIRECTORY);
  206.  
  207.     if (numDebugDirs == 0) {
  208.         return FALSE;
  209.     }
  210.  
  211.     /*
  212.      *  For each debug directory, determine the debug directory type
  213.      *  and cache any information about them.
  214.      */
  215.  
  216.     pDebugDir = (PIMAGE_DEBUG_DIRECTORY)
  217.       (p->fptr + sizeof(IMAGE_SEPARATE_DEBUG_HEADER) +
  218.        p->sepHdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
  219.        p->sepHdr->ExportedNamesSize);
  220.  
  221.     for (li=0; li<numDebugDirs; li++, pDebugDir++) {
  222.         if (((int) pDebugDir->Type) > p->cDebugDir) {
  223.             p->cDebugDir += 10;
  224.             p->rgDebugDir = realloc((char *) p->rgDebugDir,
  225.                                     p->cDebugDir * sizeof(p->rgDebugDir[0]));
  226.             memset(&p->rgDebugDir[p->cDebugDir-10], 0,
  227.                    10*sizeof(p->rgDebugDir[0]));
  228.         }
  229.  
  230.         p->rgDebugDir[pDebugDir->Type] = pDebugDir;
  231.     }
  232.  
  233.     if (p->rgDebugDir[IMAGE_DEBUG_TYPE_COFF] != NULL) {
  234.         pCoffHdr = (PIMAGE_COFF_SYMBOLS_HEADER) (p->fptr +
  235.           p->rgDebugDir[IMAGE_DEBUG_TYPE_COFF]->PointerToRawData);
  236.         p->AllSymbols = (PIMAGE_SYMBOL)
  237.           ((char *) pCoffHdr + pCoffHdr->LvaToFirstSymbol);
  238.         p->stringTable = pCoffHdr->NumberOfSymbols * IMAGE_SIZEOF_SYMBOL +
  239.           (char *) p->AllSymbols;
  240.         p->numberOfSymbols = pCoffHdr->NumberOfSymbols;
  241.     }
  242.     p->numberOfSections = p->sepHdr->NumberOfSections;
  243.  
  244.     return TRUE;
  245. }                               /* FillInSeparateImagePointers() */
  246.  
  247.  
  248.  
  249. BOOL
  250. CalculateNtImagePointers(
  251.     PIMAGEPOINTERS p
  252.     )
  253. /*++
  254.  
  255. Routine Description:
  256.  
  257.     This function reads an NT image and its associated COFF headers
  258.     and file pointers and build a set of pointers into the mapped image.
  259.     The pointers are all relative to the image's mapped file pointer
  260.     and allow direct access to the necessary data.
  261.  
  262. Arguments:
  263.  
  264.     p        - pointer to a IMAGEPOINTERS structure
  265.  
  266. Return Value:
  267.  
  268.     TRUE     - pointers were created
  269.     FALSE    - pointers could not be created
  270.  
  271. --*/
  272. {
  273.     PIMAGE_DEBUG_DIRECTORY      debugDir;
  274.     PIMAGE_SECTION_HEADER       sh;
  275.     DWORD                       i, li, rva, numDebugDirs;
  276.     PIMAGE_FILE_HEADER          pFileHdr;
  277.     PIMAGE_OPTIONAL_HEADER      pOptHdr;
  278.     DWORD                       offDebugInfo;
  279.  
  280.     try {
  281.         /*
  282.          *      Based on wheither or not we find the dos (MZ) header
  283.          *      at the beginning of the file, attempt to get a pointer
  284.          *      to where the PE header is suppose to be.
  285.          */
  286.  
  287.         p->dosHdr = (PIMAGE_DOS_HEADER) p->fptr;
  288.         if (p->dosHdr->e_magic == IMAGE_DOS_SIGNATURE) {
  289.             p->ntHdr = (PIMAGE_NT_HEADERS)
  290.               ((DWORD)p->dosHdr->e_lfanew + p->fptr);
  291.             p->fRomImage = FALSE;
  292.         } else if (p->dosHdr->e_magic == IMAGE_SEPARATE_DEBUG_SIGNATURE) {
  293.             p->sepHdr = (PIMAGE_SEPARATE_DEBUG_HEADER) p->fptr;
  294.             p->dosHdr = NULL;
  295.             p->fRomImage = FALSE;
  296.             return FillInSeparateImagePointers(p);
  297.         } else {
  298.             p->romHdr = (PIMAGE_ROM_HEADERS) p->fptr;
  299.             if (p->romHdr->FileHeader.SizeOfOptionalHeader ==
  300.                                           IMAGE_SIZEOF_ROM_OPTIONAL_HEADER &&
  301.                 p->romHdr->OptionalHeader.Magic ==
  302.                                           IMAGE_ROM_OPTIONAL_HDR_MAGIC) {
  303.                 //
  304.                 // its a rom image
  305.                 //
  306.                 p->fRomImage = TRUE;
  307.                 p->ntHdr = NULL;
  308.                 p->dosHdr = NULL;
  309.             } else {
  310.                 p->fRomImage = FALSE;
  311.                 p->ntHdr = (PIMAGE_NT_HEADERS) p->fptr;
  312.                 p->dosHdr = NULL;
  313.                 p->romHdr = NULL;
  314.             }
  315.         }
  316.  
  317.         /*
  318.          *  What comes next must be a PE header.  If not then pop out
  319.          */
  320.  
  321.         if ( p->ntHdr ) {
  322.             if ( p->dosHdr && (DWORD)p->dosHdr->e_lfanew > (DWORD)p->fsize ) {
  323.                 return FALSE;
  324.             }
  325.  
  326.             if ( p->ntHdr->Signature != IMAGE_NT_SIGNATURE ) {
  327.                 return FALSE;
  328.             }
  329.  
  330.             /*
  331.              *  We did find a PE header so start setting pointers to various
  332.              *      structures in the exe file.
  333.              */
  334.  
  335.             pFileHdr = p->fileHdr = &p->ntHdr->FileHeader;
  336.             pOptHdr = p->optHdr = &p->ntHdr->OptionalHeader;
  337.         } else if (p->romHdr) {
  338.             pFileHdr = p->fileHdr = &p->romHdr->FileHeader;
  339.             pOptHdr = (PIMAGE_OPTIONAL_HEADER) &p->romHdr->OptionalHeader;
  340.             p->optHdr = (PIMAGE_OPTIONAL_HEADER) &p->romHdr->OptionalHeader;
  341.         } else {
  342.             return FALSE;
  343.         }
  344.  
  345.         if (!(pFileHdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {
  346.             return FALSE;
  347.         }
  348.  
  349.         if (pFileHdr->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) {
  350.             return(FALSE);
  351.         }
  352.  
  353.         /*
  354.          *  If they exists then get a pointer to the symbol table and
  355.          *      the string table
  356.          */
  357.  
  358.         if (pFileHdr->PointerToSymbolTable) {
  359.             p->AllSymbols = (PIMAGE_SYMBOL)
  360.                               (pFileHdr->PointerToSymbolTable + p->fptr);
  361.             p->stringTable = (LPSTR)((ULONG)p->AllSymbols +
  362.                            (IMAGE_SIZEOF_SYMBOL * pFileHdr->NumberOfSymbols));
  363.             p->numberOfSymbols = pFileHdr->NumberOfSymbols;
  364.         }
  365.  
  366.         p->numberOfSections = pFileHdr->NumberOfSections;
  367.  
  368.         if (p->romHdr) {
  369.  
  370.             sh = p->sectionHdrs = (PIMAGE_SECTION_HEADER) (p->romHdr+1);
  371.  
  372.             p->cDebugDir = 10;
  373.             p->rgDebugDir = calloc(sizeof(IMAGE_DEBUG_DIRECTORY) * 10, 1);
  374.  
  375.             debugDir = 0;
  376.  
  377.             for (i=0; i<pFileHdr->NumberOfSections; i++, sh++) {
  378.                 if (!strcmp(sh->Name, ".rdata")) {
  379.                     debugDir = (PIMAGE_DEBUG_DIRECTORY)(sh->PointerToRawData + p->fptr);
  380.                 }
  381.  
  382.                 if (strncmp(sh->Name,".debug",8)==0) {
  383.                     p->debugSection = sh;
  384.                 }
  385.             }
  386.  
  387.             if (debugDir) {
  388.                 do {
  389.                     if ((int)debugDir->Type > p->cDebugDir) {
  390.                         p->cDebugDir += 10;
  391.                         p->rgDebugDir = realloc((char *) p->rgDebugDir,
  392.                                             p->cDebugDir * sizeof(p->rgDebugDir[0]));
  393.                         memset(&p->rgDebugDir[p->cDebugDir-10],
  394.                                 0,
  395.                                 10*sizeof(IMAGE_DEBUG_DIRECTORY));
  396.                     }
  397.                     p->rgDebugDir[debugDir->Type] = debugDir;
  398.                     debugDir++;
  399.                 } while (debugDir->Type != 0);
  400.             }
  401.         } else {
  402.  
  403.             /*
  404.              *  Locate the debug directory
  405.              */
  406.  
  407.             rva =
  408.               pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  409.  
  410.             numDebugDirs =
  411.               pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
  412.                 sizeof(IMAGE_DEBUG_DIRECTORY);
  413.  
  414.             if (numDebugDirs == 0) {
  415.                 return FALSE;
  416.             }
  417.  
  418.             sh = p->sectionHdrs = IMAGE_FIRST_SECTION( p->ntHdr );
  419.  
  420.             /*
  421.              * Find the section the debug directory is in.
  422.              */
  423.  
  424.             for (i=0; i<pFileHdr->NumberOfSections; i++, sh++) {
  425.                 if (rva >= sh->VirtualAddress &&
  426.                     rva < sh->VirtualAddress+sh->SizeOfRawData) {
  427.                     break;
  428.                 }
  429.             }
  430.  
  431.             /*
  432.              *   For each debug directory, determine the debug directory
  433.              *      type and cache any information about them.
  434.              */
  435.  
  436.             debugDir = (PIMAGE_DEBUG_DIRECTORY) ( rva - sh->VirtualAddress +
  437.                                                  sh->PointerToRawData +
  438.                                                  p->fptr );
  439.  
  440.             for (li=0; li<numDebugDirs; li++, debugDir++) {
  441.                 if (((int) debugDir->Type) > p->cDebugDir) {
  442.                     p->cDebugDir += 10;
  443.                     p->rgDebugDir = realloc((char *) p->rgDebugDir,
  444.                                             p->cDebugDir * sizeof(p->rgDebugDir[0]));
  445.                     memset(&p->rgDebugDir[p->cDebugDir-10], 0,
  446.                            10*sizeof(p->rgDebugDir[0]));
  447.                 }
  448.                 p->rgDebugDir[debugDir->Type] = debugDir;
  449.                 offDebugInfo = debugDir->AddressOfRawData;
  450.             }
  451.  
  452.             /*
  453.              *  Check to see if the debug information is mapped and if
  454.              *      there is a section called .debug
  455.              */
  456.  
  457.             sh = p->sectionHdrs = IMAGE_FIRST_SECTION( p->ntHdr );
  458.  
  459.             for (i=0; i<pFileHdr->NumberOfSections; i++, sh++) {
  460.                 if ((offDebugInfo >= sh->VirtualAddress) &&
  461.                     (offDebugInfo < sh->VirtualAddress+sh->SizeOfRawData)) {
  462.                     p->debugSection = sh;
  463.                     break;
  464.                 }
  465.             }
  466.         }
  467.  
  468.         return TRUE;
  469.     } except (EXCEPTION_EXECUTE_HANDLER) {
  470.         return FALSE;
  471.     }
  472. }                               /* CalcuateNtImagePointers() */
  473.