|
|
/*++
Copyright 1996 - 1997 Microsoft Corporation
Module Name:
file.c
Abstract:
This module handles all file i/o for SYMCVT. This includes the mapping of all files and establishing all file pointers for the mapped file(s).
Author:
Wesley A. Witt (wesw) 19-April-1993
Environment:
Win32, User Mode
--*/
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define _SYMCVT_SOURCE_
#include "symcvt.h"
static BOOL CalculateOutputFilePointers( PIMAGEPOINTERS pi, PIMAGEPOINTERS po ); static BOOL CalculateInputFilePointers( PIMAGEPOINTERS p );
MapInputFile ( PPOINTERS p, HANDLE hFile, char * fname ) /*++
Routine Description:
Maps the input file specified by the fname argument and saves the file handle & file pointer in the POINTERS structure.
Arguments:
p - Supplies pointer to a POINTERS structure hFile - OPTIONAL Supplies handle for file if already open fname - Supplies ascii string for the file name
Return Value:
TRUE - file mapped ok FALSE - file could not be mapped
--*/
{ BOOL rVal = TRUE;
memset( p, 0, sizeof(POINTERS) );
strcpy( p->iptrs.szName, fname );
if (hFile != NULL) {
p->iptrs.hFile = hFile;
} else {
p->iptrs.hFile = CreateFileA(p->iptrs.szName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); }
if (p->iptrs.hFile == INVALID_HANDLE_VALUE) {
rVal = FALSE;
} else {
p->iptrs.fsize = GetFileSize( p->iptrs.hFile, NULL ); p->iptrs.hMap = CreateFileMapping( p->iptrs.hFile, NULL, PAGE_READONLY, 0, 0, NULL );
if (p->iptrs.hMap == INVALID_HANDLE_VALUE) {
p->iptrs.hMap = NULL; rVal = FALSE;
} else {
p->iptrs.fptr = MapViewOfFile( p->iptrs.hMap, FILE_MAP_READ, 0, 0, 0 ); if (p->iptrs.fptr == NULL) { CloseHandle( p->iptrs.hMap ); p->iptrs.hMap = NULL; rVal = FALSE; } } }
if (!hFile && p->iptrs.hFile != INVALID_HANDLE_VALUE) { CloseHandle(p->iptrs.hFile); p->iptrs.hFile = NULL; }
return rVal; } /* MapInputFile() */
BOOL UnMapInputFile ( PPOINTERS p ) /*++
Routine Description:
Unmaps the input file specified by the fname argument and then closes the file.
Arguments:
p - pointer to a POINTERS structure
Return Value:
TRUE - file mapped ok FALSE - file could not be mapped
--*/
{ if ( p->iptrs.fptr ) { UnmapViewOfFile( p->iptrs.fptr ); p->iptrs.fptr = NULL; } if ( p->iptrs.hMap ) { CloseHandle( p->iptrs.hMap ); p->iptrs.hMap = NULL; } if (p->iptrs.hFile != NULL) { CloseHandle( p->iptrs.hFile ); p->iptrs.hFile = NULL; } return TRUE; } /* UnMapInputFile() */
BOOL FillInSeparateImagePointers( PIMAGEPOINTERS p ) /*++
Routine Description:
This routine will go through the exe file and fill in the pointers needed relative to the separate debug information files
Arguments:
p - Supplies the structure to fill in
Return Value:
TRUE if successful and FALSE otherwise.
--*/
{ int li; int numDebugDirs; PIMAGE_DEBUG_DIRECTORY pDebugDir; PIMAGE_COFF_SYMBOLS_HEADER pCoffHdr;
p->sectionHdrs = (PIMAGE_SECTION_HEADER) (p->fptr + sizeof(IMAGE_SEPARATE_DEBUG_HEADER));
numDebugDirs = p->sepHdr->DebugDirectorySize/sizeof(IMAGE_DEBUG_DIRECTORY);
if (numDebugDirs == 0) { return FALSE; }
/*
* For each debug directory, determine the debug directory type * and cache any information about them. */
pDebugDir = (PIMAGE_DEBUG_DIRECTORY) (p->fptr + sizeof(IMAGE_SEPARATE_DEBUG_HEADER) + p->sepHdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + p->sepHdr->ExportedNamesSize);
for (li=0; li<numDebugDirs; li++, pDebugDir++) { if (((int) pDebugDir->Type) > p->cDebugDir) { p->cDebugDir += 10; p->rgDebugDir = realloc((char *) p->rgDebugDir, p->cDebugDir * sizeof(p->rgDebugDir[0])); memset(&p->rgDebugDir[p->cDebugDir-10], 0, 10*sizeof(p->rgDebugDir[0])); }
p->rgDebugDir[pDebugDir->Type] = pDebugDir; }
if (p->rgDebugDir[IMAGE_DEBUG_TYPE_COFF] != NULL) { pCoffHdr = (PIMAGE_COFF_SYMBOLS_HEADER) (p->fptr + p->rgDebugDir[IMAGE_DEBUG_TYPE_COFF]->PointerToRawData); p->AllSymbols = (PIMAGE_SYMBOL) ((char *) pCoffHdr + pCoffHdr->LvaToFirstSymbol); p->stringTable = pCoffHdr->NumberOfSymbols * IMAGE_SIZEOF_SYMBOL + (char *) p->AllSymbols; p->numberOfSymbols = pCoffHdr->NumberOfSymbols; } p->numberOfSections = p->sepHdr->NumberOfSections;
return TRUE; } /* FillInSeparateImagePointers() */
BOOL CalculateNtImagePointers( PIMAGEPOINTERS p ) /*++
Routine Description:
This function reads an NT image and its associated COFF headers and file pointers and build a set of pointers into the mapped image. The pointers are all relative to the image's mapped file pointer and allow direct access to the necessary data.
Arguments:
p - pointer to a IMAGEPOINTERS structure
Return Value:
TRUE - pointers were created FALSE - pointers could not be created
--*/ { PIMAGE_DEBUG_DIRECTORY debugDir; PIMAGE_SECTION_HEADER sh; DWORD i, li, rva, numDebugDirs; PIMAGE_FILE_HEADER pFileHdr; PIMAGE_OPTIONAL_HEADER pOptHdr; DWORD offDebugInfo;
try { /*
* Based on wheither or not we find the dos (MZ) header * at the beginning of the file, attempt to get a pointer * to where the PE header is suppose to be. */
p->dosHdr = (PIMAGE_DOS_HEADER) p->fptr; if (p->dosHdr->e_magic == IMAGE_DOS_SIGNATURE) { p->ntHdr = (PIMAGE_NT_HEADERS) ((DWORD)p->dosHdr->e_lfanew + p->fptr); p->fRomImage = FALSE; } else if (p->dosHdr->e_magic == IMAGE_SEPARATE_DEBUG_SIGNATURE) { p->sepHdr = (PIMAGE_SEPARATE_DEBUG_HEADER) p->fptr; p->dosHdr = NULL; p->fRomImage = FALSE; return FillInSeparateImagePointers(p); } else { p->romHdr = (PIMAGE_ROM_HEADERS) p->fptr; if (p->romHdr->FileHeader.SizeOfOptionalHeader == IMAGE_SIZEOF_ROM_OPTIONAL_HEADER && p->romHdr->OptionalHeader.Magic == IMAGE_ROM_OPTIONAL_HDR_MAGIC) { //
// its a rom image
//
p->fRomImage = TRUE; p->ntHdr = NULL; p->dosHdr = NULL; } else { p->fRomImage = FALSE; p->ntHdr = (PIMAGE_NT_HEADERS) p->fptr; p->dosHdr = NULL; p->romHdr = NULL; } }
/*
* What comes next must be a PE header. If not then pop out */
if ( p->ntHdr ) { if ( p->dosHdr && (DWORD)p->dosHdr->e_lfanew > (DWORD)p->fsize ) { return FALSE; }
if ( p->ntHdr->Signature != IMAGE_NT_SIGNATURE ) { return FALSE; }
/*
* We did find a PE header so start setting pointers to various * structures in the exe file. */
pFileHdr = p->fileHdr = &p->ntHdr->FileHeader; pOptHdr = p->optHdr = &p->ntHdr->OptionalHeader; } else if (p->romHdr) { pFileHdr = p->fileHdr = &p->romHdr->FileHeader; pOptHdr = (PIMAGE_OPTIONAL_HEADER) &p->romHdr->OptionalHeader; p->optHdr = (PIMAGE_OPTIONAL_HEADER) &p->romHdr->OptionalHeader; } else { return FALSE; }
if (!(pFileHdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) { return FALSE; }
if (pFileHdr->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) { return(FALSE); }
/*
* If they exists then get a pointer to the symbol table and * the string table */
if (pFileHdr->PointerToSymbolTable) { p->AllSymbols = (PIMAGE_SYMBOL) (pFileHdr->PointerToSymbolTable + p->fptr); p->stringTable = (LPSTR)((ULONG)p->AllSymbols + (IMAGE_SIZEOF_SYMBOL * pFileHdr->NumberOfSymbols)); p->numberOfSymbols = pFileHdr->NumberOfSymbols; }
p->numberOfSections = pFileHdr->NumberOfSections;
if (p->romHdr) {
sh = p->sectionHdrs = (PIMAGE_SECTION_HEADER) (p->romHdr+1);
p->cDebugDir = 10; p->rgDebugDir = calloc(sizeof(IMAGE_DEBUG_DIRECTORY) * 10, 1);
debugDir = 0;
for (i=0; i<pFileHdr->NumberOfSections; i++, sh++) { if (!strcmp(sh->Name, ".rdata")) { debugDir = (PIMAGE_DEBUG_DIRECTORY)(sh->PointerToRawData + p->fptr); }
if (strncmp(sh->Name,".debug",8)==0) { p->debugSection = sh; } }
if (debugDir) { do { if ((int)debugDir->Type > p->cDebugDir) { p->cDebugDir += 10; p->rgDebugDir = realloc((char *) p->rgDebugDir, p->cDebugDir * sizeof(p->rgDebugDir[0])); memset(&p->rgDebugDir[p->cDebugDir-10], 0, 10*sizeof(IMAGE_DEBUG_DIRECTORY)); } p->rgDebugDir[debugDir->Type] = debugDir; debugDir++; } while (debugDir->Type != 0); } } else {
/*
* Locate the debug directory */
rva = pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
numDebugDirs = pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / sizeof(IMAGE_DEBUG_DIRECTORY);
if (numDebugDirs == 0) { return FALSE; }
sh = p->sectionHdrs = IMAGE_FIRST_SECTION( p->ntHdr );
/*
* Find the section the debug directory is in. */
for (i=0; i<pFileHdr->NumberOfSections; i++, sh++) { if (rva >= sh->VirtualAddress && rva < sh->VirtualAddress+sh->SizeOfRawData) { break; } }
/*
* For each debug directory, determine the debug directory * type and cache any information about them. */
debugDir = (PIMAGE_DEBUG_DIRECTORY) ( rva - sh->VirtualAddress + sh->PointerToRawData + p->fptr );
for (li=0; li<numDebugDirs; li++, debugDir++) { if (((int) debugDir->Type) > p->cDebugDir) { p->cDebugDir += 10; p->rgDebugDir = realloc((char *) p->rgDebugDir, p->cDebugDir * sizeof(p->rgDebugDir[0])); memset(&p->rgDebugDir[p->cDebugDir-10], 0, 10*sizeof(p->rgDebugDir[0])); } p->rgDebugDir[debugDir->Type] = debugDir; offDebugInfo = debugDir->AddressOfRawData; }
/*
* Check to see if the debug information is mapped and if * there is a section called .debug */
sh = p->sectionHdrs = IMAGE_FIRST_SECTION( p->ntHdr );
for (i=0; i<pFileHdr->NumberOfSections; i++, sh++) { if ((offDebugInfo >= sh->VirtualAddress) && (offDebugInfo < sh->VirtualAddress+sh->SizeOfRawData)) { p->debugSection = sh; break; } } }
return TRUE; } except (EXCEPTION_EXECUTE_HANDLER) { return FALSE; } } /* CalcuateNtImagePointers() */
|