467 lines
13 KiB
C
467 lines
13 KiB
C
/*++
|
|
|
|
|
|
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() */
|