You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
338 lines
9.3 KiB
338 lines
9.3 KiB
/*++
|
|
|
|
Copyright (c) 1999-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
imagedir.c
|
|
|
|
Abstract:
|
|
|
|
For backwards compatability on Win9x platforms, the imagehlp ImageNtHeader
|
|
etc. functions have been physically compiled into minidump.dll.
|
|
|
|
Author:
|
|
|
|
Matthew D Hendel (math) 28-April-1999
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "pch.cpp"
|
|
|
|
void
|
|
GenImageNtHdr32To64(PIMAGE_NT_HEADERS32 Hdr32,
|
|
PIMAGE_NT_HEADERS64 Hdr64)
|
|
{
|
|
#define CP(x) Hdr64->x = Hdr32->x
|
|
#define SE64(x) Hdr64->x = (ULONG64) (LONG64) (LONG) Hdr32->x
|
|
ULONG i;
|
|
|
|
CP(Signature);
|
|
CP(FileHeader);
|
|
CP(OptionalHeader.Magic);
|
|
CP(OptionalHeader.MajorLinkerVersion);
|
|
CP(OptionalHeader.MinorLinkerVersion);
|
|
CP(OptionalHeader.SizeOfCode);
|
|
CP(OptionalHeader.SizeOfInitializedData);
|
|
CP(OptionalHeader.SizeOfUninitializedData);
|
|
CP(OptionalHeader.AddressOfEntryPoint);
|
|
CP(OptionalHeader.BaseOfCode);
|
|
SE64(OptionalHeader.ImageBase);
|
|
CP(OptionalHeader.SectionAlignment);
|
|
CP(OptionalHeader.FileAlignment);
|
|
CP(OptionalHeader.MajorOperatingSystemVersion);
|
|
CP(OptionalHeader.MinorOperatingSystemVersion);
|
|
CP(OptionalHeader.MajorImageVersion);
|
|
CP(OptionalHeader.MinorImageVersion);
|
|
CP(OptionalHeader.MajorSubsystemVersion);
|
|
CP(OptionalHeader.MinorSubsystemVersion);
|
|
CP(OptionalHeader.Win32VersionValue);
|
|
CP(OptionalHeader.SizeOfImage);
|
|
CP(OptionalHeader.SizeOfHeaders);
|
|
CP(OptionalHeader.CheckSum);
|
|
CP(OptionalHeader.Subsystem);
|
|
CP(OptionalHeader.DllCharacteristics);
|
|
// Sizes are not sign extended, just copied.
|
|
CP(OptionalHeader.SizeOfStackReserve);
|
|
CP(OptionalHeader.SizeOfStackCommit);
|
|
CP(OptionalHeader.SizeOfHeapReserve);
|
|
CP(OptionalHeader.SizeOfHeapCommit);
|
|
CP(OptionalHeader.LoaderFlags);
|
|
CP(OptionalHeader.NumberOfRvaAndSizes);
|
|
for (i = 0; i < ARRAY_COUNT(Hdr32->OptionalHeader.DataDirectory); i++)
|
|
{
|
|
CP(OptionalHeader.DataDirectory[i]);
|
|
}
|
|
#undef CP
|
|
#undef SE64
|
|
}
|
|
|
|
PIMAGE_NT_HEADERS
|
|
GenImageNtHeader(
|
|
IN PVOID Base,
|
|
OUT OPTIONAL PIMAGE_NT_HEADERS64 Generic
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the address of the NT Header.
|
|
|
|
Return Value:
|
|
|
|
Returns the address of the NT Header.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIMAGE_NT_HEADERS NtHeaders = NULL;
|
|
|
|
if (Base != NULL && Base != (PVOID)-1) {
|
|
__try {
|
|
if (((PIMAGE_DOS_HEADER)Base)->e_magic == IMAGE_DOS_SIGNATURE) {
|
|
NtHeaders = (PIMAGE_NT_HEADERS)((PCHAR)Base + ((PIMAGE_DOS_HEADER)Base)->e_lfanew);
|
|
|
|
if (NtHeaders->Signature != IMAGE_NT_SIGNATURE ||
|
|
(NtHeaders->OptionalHeader.Magic !=
|
|
IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
|
|
NtHeaders->OptionalHeader.Magic !=
|
|
IMAGE_NT_OPTIONAL_HDR64_MAGIC)) {
|
|
NtHeaders = NULL;
|
|
} else if (Generic) {
|
|
if (NtHeaders->OptionalHeader.Magic ==
|
|
IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
|
GenImageNtHdr32To64((PIMAGE_NT_HEADERS32)NtHeaders,
|
|
Generic);
|
|
} else {
|
|
memcpy(Generic, NtHeaders, sizeof(*Generic));
|
|
}
|
|
}
|
|
}
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
NtHeaders = NULL;
|
|
}
|
|
}
|
|
|
|
return NtHeaders;
|
|
}
|
|
|
|
|
|
PIMAGE_SECTION_HEADER
|
|
GenSectionTableFromVirtualAddress (
|
|
IN PIMAGE_NT_HEADERS NtHeaders,
|
|
IN PVOID Base,
|
|
IN ULONG Address
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function locates a VirtualAddress within the image header
|
|
of a file that is mapped as a file and returns a pointer to the
|
|
section table entry for that virtual address
|
|
|
|
Arguments:
|
|
|
|
NtHeaders - Supplies the pointer to the image or data file.
|
|
|
|
Base - Supplies the base of the image or data file.
|
|
|
|
Address - Supplies the virtual address to locate.
|
|
|
|
Return Value:
|
|
|
|
NULL - The file does not contain data for the specified directory entry.
|
|
|
|
NON-NULL - Returns the pointer of the section entry containing the data.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG i;
|
|
PIMAGE_SECTION_HEADER NtSection;
|
|
|
|
NtSection = IMAGE_FIRST_SECTION( NtHeaders );
|
|
for (i=0; i<NtHeaders->FileHeader.NumberOfSections; i++) {
|
|
if ((ULONG)Address >= NtSection->VirtualAddress &&
|
|
(ULONG)Address < NtSection->VirtualAddress + NtSection->SizeOfRawData
|
|
) {
|
|
return NtSection;
|
|
}
|
|
++NtSection;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
PVOID
|
|
GenAddressInSectionTable (
|
|
IN PIMAGE_NT_HEADERS NtHeaders,
|
|
IN PVOID Base,
|
|
IN ULONG Address
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function locates a VirtualAddress within the image header
|
|
of a file that is mapped as a file and returns the seek address
|
|
of the data the Directory describes.
|
|
|
|
Arguments:
|
|
|
|
NtHeaders - Supplies the pointer to the image or data file.
|
|
|
|
Base - Supplies the base of the image or data file.
|
|
|
|
Address - Supplies the virtual address to locate.
|
|
|
|
Return Value:
|
|
|
|
NULL - The file does not contain data for the specified directory entry.
|
|
|
|
NON-NULL - Returns the address of the raw data the directory describes.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIMAGE_SECTION_HEADER NtSection;
|
|
|
|
NtSection = GenSectionTableFromVirtualAddress( NtHeaders,
|
|
Base,
|
|
Address
|
|
);
|
|
if (NtSection != NULL) {
|
|
return( ((PCHAR)Base + ((ULONG_PTR)Address - NtSection->VirtualAddress) + NtSection->PointerToRawData) );
|
|
}
|
|
else {
|
|
return( NULL );
|
|
}
|
|
}
|
|
|
|
|
|
PVOID
|
|
GenImageDirectoryEntryToData32 (
|
|
IN PVOID Base,
|
|
IN BOOLEAN MappedAsImage,
|
|
IN USHORT DirectoryEntry,
|
|
OUT PULONG Size,
|
|
PIMAGE_NT_HEADERS32 NtHeaders
|
|
)
|
|
{
|
|
ULONG DirectoryAddress;
|
|
|
|
if (DirectoryEntry >= NtHeaders->OptionalHeader.NumberOfRvaAndSizes) {
|
|
return( NULL );
|
|
}
|
|
|
|
if (!(DirectoryAddress = NtHeaders->OptionalHeader.DataDirectory[ DirectoryEntry ].VirtualAddress)) {
|
|
return( NULL );
|
|
}
|
|
|
|
*Size = NtHeaders->OptionalHeader.DataDirectory[ DirectoryEntry ].Size;
|
|
if (MappedAsImage || DirectoryAddress < NtHeaders->OptionalHeader.SizeOfHeaders) {
|
|
return( (PVOID)((PCHAR)Base + DirectoryAddress) );
|
|
}
|
|
|
|
return( GenAddressInSectionTable((PIMAGE_NT_HEADERS)NtHeaders, Base, DirectoryAddress ));
|
|
}
|
|
|
|
|
|
PVOID
|
|
GenImageDirectoryEntryToData64 (
|
|
IN PVOID Base,
|
|
IN BOOLEAN MappedAsImage,
|
|
IN USHORT DirectoryEntry,
|
|
OUT PULONG Size,
|
|
PIMAGE_NT_HEADERS64 NtHeaders
|
|
)
|
|
{
|
|
ULONG DirectoryAddress;
|
|
|
|
if (DirectoryEntry >= NtHeaders->OptionalHeader.NumberOfRvaAndSizes) {
|
|
return( NULL );
|
|
}
|
|
|
|
if (!(DirectoryAddress = NtHeaders->OptionalHeader.DataDirectory[ DirectoryEntry ].VirtualAddress)) {
|
|
return( NULL );
|
|
}
|
|
|
|
*Size = NtHeaders->OptionalHeader.DataDirectory[ DirectoryEntry ].Size;
|
|
if (MappedAsImage || DirectoryAddress < NtHeaders->OptionalHeader.SizeOfHeaders) {
|
|
return( (PVOID)((PCHAR)Base + DirectoryAddress) );
|
|
}
|
|
|
|
return( GenAddressInSectionTable((PIMAGE_NT_HEADERS)NtHeaders, Base, DirectoryAddress ));
|
|
}
|
|
|
|
|
|
PVOID
|
|
GenImageDirectoryEntryToData (
|
|
IN PVOID Base,
|
|
IN BOOLEAN MappedAsImage,
|
|
IN USHORT DirectoryEntry,
|
|
OUT PULONG Size
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function locates a Directory Entry within the image header
|
|
and returns either the virtual address or seek address of the
|
|
data the Directory describes.
|
|
|
|
Arguments:
|
|
|
|
Base - Supplies the base of the image or data file.
|
|
|
|
MappedAsImage - FALSE if the file is mapped as a data file.
|
|
- TRUE if the file is mapped as an image.
|
|
|
|
DirectoryEntry - Supplies the directory entry to locate.
|
|
|
|
Size - Return the size of the directory.
|
|
|
|
Return Value:
|
|
|
|
NULL - The file does not contain data for the specified directory entry.
|
|
|
|
NON-NULL - Returns the address of the raw data the directory describes.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIMAGE_NT_HEADERS NtHeaders;
|
|
|
|
if ((ULONG_PTR)Base & 0x00000001) {
|
|
Base = (PVOID)((ULONG_PTR)Base & ~0x00000001);
|
|
MappedAsImage = FALSE;
|
|
}
|
|
|
|
NtHeaders = GenImageNtHeader(Base, NULL);
|
|
|
|
if (!NtHeaders)
|
|
return NULL;
|
|
|
|
if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
|
return (GenImageDirectoryEntryToData32(Base,
|
|
MappedAsImage,
|
|
DirectoryEntry,
|
|
Size,
|
|
(PIMAGE_NT_HEADERS32)NtHeaders));
|
|
} else if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
|
return (GenImageDirectoryEntryToData64(Base,
|
|
MappedAsImage,
|
|
DirectoryEntry,
|
|
Size,
|
|
(PIMAGE_NT_HEADERS64)NtHeaders));
|
|
} else {
|
|
return (NULL);
|
|
}
|
|
}
|