windows-nt/Source/XPSP1/NT/sdktools/debuggers/imagehlp/imagedir.c
2020-09-26 16:20:57 +08:00

459 lines
12 KiB
C

/*++
Copyright (c) 1991-1995 Microsoft Corporation
Module Name:
imagedir.c
Abstract:
The module contains the code to translate an image directory type to
the address of the data for that entry.
Environment:
User Mode or Kernel Mode
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <private.h>
PVOID
ImageDirectoryEntryToData (
IN PVOID Base,
IN BOOLEAN MappedAsImage,
IN USHORT DirectoryEntry,
OUT PULONG Size
);
PIMAGE_NT_HEADERS
ImageNtHeader (
IN PVOID Base
)
/*++
Routine Description:
This function returns the address of the NT Header.
Arguments:
Base - Supplies the base of the image.
Return Value:
Returns the address of the NT Header.
--*/
{
return RtlpImageNtHeader( Base );
}
PVOID
ImageDirectoryEntryToDataRom (
IN PVOID Base,
IN BOOLEAN MappedAsImage,
IN USHORT DirectoryEntry,
OUT PULONG Size,
OUT PIMAGE_SECTION_HEADER *FoundSection OPTIONAL,
IN PIMAGE_FILE_HEADER FileHeader,
IN PIMAGE_ROM_OPTIONAL_HEADER OptionalHeader
)
{
ULONG i;
PIMAGE_SECTION_HEADER NtSection;
//
// There's not much we can get from ROM images. See if the info requested
// is one of the known ones (debug/exception data)
//
NtSection = (PIMAGE_SECTION_HEADER)((ULONG_PTR)OptionalHeader +
FileHeader->SizeOfOptionalHeader);
for (i = 0; i < FileHeader->NumberOfSections; i++, NtSection++) {
if ( DirectoryEntry == IMAGE_DIRECTORY_ENTRY_DEBUG ) {
if (!_stricmp((char *)NtSection->Name, ".rdata")) {
PIMAGE_DEBUG_DIRECTORY DebugDirectory;
*Size = 0;
DebugDirectory = (PIMAGE_DEBUG_DIRECTORY)((ULONG_PTR)NtSection->PointerToRawData + (ULONG_PTR)Base);
while (DebugDirectory->Type != 0) {
*Size += sizeof(IMAGE_DEBUG_DIRECTORY);
DebugDirectory++;
}
if (FoundSection) {
*FoundSection = NtSection;
}
return (PVOID)((ULONG_PTR)NtSection->PointerToRawData + (ULONG_PTR)Base);
}
} else
if ( DirectoryEntry == IMAGE_DIRECTORY_ENTRY_EXCEPTION ) {
if (!_stricmp((char *)NtSection->Name, ".pdata")) {
if (FoundSection) {
*FoundSection = NtSection;
}
return (PVOID)((ULONG_PTR)NtSection->PointerToRawData + (ULONG_PTR)Base);
}
}
}
// Not one of the known sections. Return error.
*Size = 0;
return( NULL );
}
PVOID
ImageDirectoryEntryToData64 (
IN PVOID Base,
IN BOOLEAN MappedAsImage,
IN USHORT DirectoryEntry,
OUT PULONG Size,
OUT PIMAGE_SECTION_HEADER *FoundSection OPTIONAL,
IN PIMAGE_FILE_HEADER FileHeader,
IN PIMAGE_OPTIONAL_HEADER64 OptionalHeader
)
{
ULONG i;
PIMAGE_SECTION_HEADER NtSection;
ULONG DirectoryAddress;
if (DirectoryEntry >= OptionalHeader->NumberOfRvaAndSizes) {
*Size = 0;
return( NULL );
}
if (!(DirectoryAddress = OptionalHeader->DataDirectory[ DirectoryEntry ].VirtualAddress)) {
*Size = 0;
return( NULL );
}
*Size = OptionalHeader->DataDirectory[ DirectoryEntry ].Size;
if (MappedAsImage || DirectoryAddress < OptionalHeader->SizeOfHeaders) {
if (FoundSection) {
*FoundSection = NULL;
}
return( (PVOID)((ULONG_PTR)Base + DirectoryAddress) );
}
NtSection = (PIMAGE_SECTION_HEADER)((ULONG_PTR)OptionalHeader +
FileHeader->SizeOfOptionalHeader);
for (i=0; i<FileHeader->NumberOfSections; i++) {
if (DirectoryAddress >= NtSection->VirtualAddress &&
DirectoryAddress < NtSection->VirtualAddress + NtSection->SizeOfRawData) {
if (FoundSection) {
*FoundSection = NtSection;
}
return( (PVOID)((ULONG_PTR)Base + (DirectoryAddress - NtSection->VirtualAddress) + NtSection->PointerToRawData) );
}
++NtSection;
}
return( NULL );
}
PVOID
ImageDirectoryEntryToData32 (
IN PVOID Base,
IN BOOLEAN MappedAsImage,
IN USHORT DirectoryEntry,
OUT PULONG Size,
OUT PIMAGE_SECTION_HEADER *FoundSection OPTIONAL,
IN PIMAGE_FILE_HEADER FileHeader,
IN PIMAGE_OPTIONAL_HEADER32 OptionalHeader
)
{
ULONG i;
PIMAGE_SECTION_HEADER NtSection;
ULONG DirectoryAddress;
if (DirectoryEntry >= OptionalHeader->NumberOfRvaAndSizes) {
*Size = 0;
return( NULL );
}
if (!(DirectoryAddress = OptionalHeader->DataDirectory[ DirectoryEntry ].VirtualAddress)) {
*Size = 0;
return( NULL );
}
*Size = OptionalHeader->DataDirectory[ DirectoryEntry ].Size;
if (MappedAsImage || DirectoryAddress < OptionalHeader->SizeOfHeaders) {
if (FoundSection) {
*FoundSection = NULL;
}
return( (PVOID)((ULONG_PTR)Base + DirectoryAddress) );
}
NtSection = (PIMAGE_SECTION_HEADER)((ULONG_PTR)OptionalHeader +
FileHeader->SizeOfOptionalHeader);
for (i=0; i<FileHeader->NumberOfSections; i++) {
if (DirectoryAddress >= NtSection->VirtualAddress &&
DirectoryAddress < NtSection->VirtualAddress + NtSection->SizeOfRawData) {
if (FoundSection) {
*FoundSection = NtSection;
}
return( (PVOID)((ULONG_PTR)Base + (DirectoryAddress - NtSection->VirtualAddress) + NtSection->PointerToRawData) );
}
++NtSection;
}
return( NULL );
}
PVOID
ImageDirectoryEntryToDataEx (
IN PVOID Base,
IN BOOLEAN MappedAsImage,
IN USHORT DirectoryEntry,
OUT PULONG Size,
OUT PIMAGE_SECTION_HEADER *FoundSection OPTIONAL
)
/*++
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. It may optionally return the
section header, if any, for the found data.
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.
FoundSection - Returns the section header, if any, for the data
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 NtHeader;
PIMAGE_FILE_HEADER FileHeader;
PIMAGE_OPTIONAL_HEADER OptionalHeader;
if ((ULONG_PTR)Base & 0x00000001) {
Base = (PVOID)((ULONG_PTR)Base & ~0x1);
MappedAsImage = FALSE;
}
NtHeader = ImageNtHeader(Base);
if (NtHeader) {
FileHeader = &NtHeader->FileHeader;
OptionalHeader = &NtHeader->OptionalHeader;
} else {
// Handle case where Image passed in doesn't have a dos stub (ROM images for instance);
FileHeader = (PIMAGE_FILE_HEADER)Base;
OptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((ULONG_PTR)Base + IMAGE_SIZEOF_FILE_HEADER);
}
if (OptionalHeader->Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
return (ImageDirectoryEntryToData32 ( Base,
MappedAsImage,
DirectoryEntry,
Size,
FoundSection,
FileHeader,
(PIMAGE_OPTIONAL_HEADER32)OptionalHeader));
} else if (OptionalHeader->Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
return (ImageDirectoryEntryToData64 ( Base,
MappedAsImage,
DirectoryEntry,
Size,
FoundSection,
FileHeader,
(PIMAGE_OPTIONAL_HEADER64)OptionalHeader));
} else if (OptionalHeader->Magic == IMAGE_ROM_OPTIONAL_HDR_MAGIC) {
return (ImageDirectoryEntryToDataRom ( Base,
MappedAsImage,
DirectoryEntry,
Size,
FoundSection,
FileHeader,
(PIMAGE_ROM_OPTIONAL_HEADER)OptionalHeader));
} else {
*Size = 0;
return NULL;
}
}
PVOID
ImageDirectoryEntryToData (
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.
This just calls ImageDirectoryToDataEx without a FoundSection arg.
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.
--*/
{
return ImageDirectoryEntryToDataEx(Base, MappedAsImage, DirectoryEntry, Size, NULL);
}
PIMAGE_SECTION_HEADER
ImageRvaToSection(
IN PIMAGE_NT_HEADERS NtHeaders,
IN PVOID Base,
IN ULONG Rva
)
/*++
Routine Description:
This function locates an RVA 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.
Rva - Supplies the relative virtual address (RVA) 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 (Rva >= NtSection->VirtualAddress &&
Rva < NtSection->VirtualAddress + NtSection->SizeOfRawData
) {
return NtSection;
}
++NtSection;
}
return NULL;
}
PVOID
ImageRvaToVa(
IN PIMAGE_NT_HEADERS NtHeaders,
IN PVOID Base,
IN ULONG Rva,
IN OUT PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL
)
/*++
Routine Description:
This function locates an RVA within the image header of a file that
is mapped as a file and returns the virtual addrees of the
corresponding byte in the file.
Arguments:
NtHeaders - Supplies the pointer to the image or data file.
Base - Supplies the base of the image or data file.
Rva - Supplies the relative virtual address (RVA) to locate.
LastRvaSection - Optional parameter that if specified, points
to a variable that contains the last section value used for
the specified image to translate and RVA to a VA.
Return Value:
NULL - The file does not contain the specified RVA
NON-NULL - Returns the virtual addrees in the mapped file.
--*/
{
PIMAGE_SECTION_HEADER NtSection;
if (LastRvaSection == NULL ||
(NtSection = *LastRvaSection) == NULL ||
NtSection == NULL ||
Rva < NtSection->VirtualAddress ||
Rva >= NtSection->VirtualAddress + NtSection->SizeOfRawData
) {
NtSection = ImageRvaToSection( NtHeaders,
Base,
Rva
);
}
if (NtSection != NULL) {
if (LastRvaSection != NULL) {
*LastRvaSection = NtSection;
}
return (PVOID)((ULONG_PTR)Base +
(Rva - NtSection->VirtualAddress) +
NtSection->PointerToRawData
);
}
else {
return NULL;
}
}