/*++
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 );
BOOL
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;
DWORD lwFsize;
memset( p, 0, sizeof(POINTERS) );
strcpy( p->iptrs.szName, fname );
if (hFile != NULL) {
p->iptrs.hFile = hFile;
} else {
p->iptrs.hFile = CreateFile( 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 );
if (lwFsize == 0xffffffff) {
;
}
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() */