// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // /*============================================================ ** ** CorImage.cpp ** ** IMAGEHLP routines so we can avoid early binding to that DLL. ** ===========================================================*/ #include "stdafx.h" #include "contract.h" #include #include "corimage.h" #include "safemath.h" #define RTL_MEG (1024UL * 1024UL) #define RTLP_IMAGE_MAX_DOS_HEADER ( 256UL * RTL_MEG) // IMAGE_FIRST_SECTION doesn't need 32/64 versions since the file header is // the same either way. #define PTR_IMAGE_FIRST_SECTION( ntheader ) \ PTR_IMAGE_SECTION_HEADER \ (dac_cast(ntheader) + \ FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ VAL16((ntheader)->FileHeader.SizeOfOptionalHeader) \ ) #ifndef DACCESS_COMPILE IMAGE_NT_HEADERS *Cor_RtlImageNtHeader(VOID *pvBase, ULONG FileLength) { LIMITED_METHOD_CONTRACT; IMAGE_NT_HEADERS *pNtHeaders = NULL; if (pvBase && (pvBase != (VOID*)-1)) { struct Param { IMAGE_DOS_HEADER *pDos; ULONG FileLength; IMAGE_NT_HEADERS *pNtHeaders; } param; param.pDos = (IMAGE_DOS_HEADER*)pvBase; param.FileLength = FileLength; param.pNtHeaders = pNtHeaders; PAL_TRY(Param *, pParam, ¶m) { if ( (pParam->pDos->e_magic == VAL16(IMAGE_DOS_SIGNATURE)) && ((DWORD)VAL32(pParam->pDos->e_lfanew) < RTLP_IMAGE_MAX_DOS_HEADER) && ovadd_lt((DWORD)VAL32(pParam->pDos->e_lfanew), sizeof(IMAGE_FILE_HEADER) + sizeof(DWORD), pParam->FileLength)) { pParam->pNtHeaders = (IMAGE_NT_HEADERS*)((BYTE*)pParam->pDos + VAL32(pParam->pDos->e_lfanew)); if (pParam->pNtHeaders->Signature != VAL32(IMAGE_NT_SIGNATURE)) pParam->pNtHeaders = NULL; } } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { param.pNtHeaders = NULL; } PAL_ENDTRY pNtHeaders = param.pNtHeaders; } return pNtHeaders; } #endif // #ifndef DACCESS_COMPILE EXTERN_C PIMAGE_SECTION_HEADER Cor_RtlImageRvaToSection32(PTR_IMAGE_NT_HEADERS32 NtHeaders, ULONG Rva, ULONG FileLength) { LIMITED_METHOD_CONTRACT; ULONG i; PTR_IMAGE_SECTION_HEADER NtSection; NtSection = PTR_IMAGE_FIRST_SECTION( NtHeaders ); for (i=0; iFileHeader.NumberOfSections; i++) { if (FileLength && (((VAL32(NtSection->PointerToRawData) > FileLength)) || (VAL32(NtSection->SizeOfRawData) > FileLength - VAL32(NtSection->PointerToRawData)))) return NULL; if (Rva >= VAL32(NtSection->VirtualAddress) && Rva < VAL32(NtSection->VirtualAddress) + VAL32(NtSection->SizeOfRawData)) return NtSection; ++NtSection; } return NULL; } EXTERN_C PIMAGE_SECTION_HEADER Cor_RtlImageRvaToSection64(PTR_IMAGE_NT_HEADERS64 NtHeaders, ULONG Rva, ULONG FileLength) { LIMITED_METHOD_CONTRACT; ULONG i; PTR_IMAGE_SECTION_HEADER NtSection; NtSection = PTR_IMAGE_FIRST_SECTION( NtHeaders ); for (i=0; iFileHeader.NumberOfSections); i++) { if (FileLength && (((VAL32(NtSection->PointerToRawData) > FileLength)) || (VAL32(NtSection->SizeOfRawData) > FileLength - VAL32(NtSection->PointerToRawData)))) return NULL; if (Rva >= VAL32(NtSection->VirtualAddress) && Rva < VAL32(NtSection->VirtualAddress) + VAL32(NtSection->SizeOfRawData)) return NtSection; ++NtSection; } return NULL; } EXTERN_C PIMAGE_SECTION_HEADER Cor_RtlImageRvaToSection(PTR_IMAGE_NT_HEADERS NtHeaders, ULONG Rva, ULONG FileLength) { LIMITED_METHOD_CONTRACT; if (NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC)) return Cor_RtlImageRvaToSection32((PTR_IMAGE_NT_HEADERS32)NtHeaders, Rva, FileLength); else if(NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC)) return Cor_RtlImageRvaToSection64((PTR_IMAGE_NT_HEADERS64)NtHeaders, Rva, FileLength); else { _ASSERTE(!"Invalid File Type"); return NULL; } } EXTERN_C PBYTE Cor_RtlImageRvaToVa32(PTR_IMAGE_NT_HEADERS32 NtHeaders, PBYTE Base, ULONG Rva, ULONG FileLength) { LIMITED_METHOD_CONTRACT; PIMAGE_SECTION_HEADER NtSection = Cor_RtlImageRvaToSection32(NtHeaders, Rva, FileLength); if (NtSection != NULL) return (Base + (Rva - VAL32(NtSection->VirtualAddress)) + VAL32(NtSection->PointerToRawData)); else return NULL; } EXTERN_C PBYTE Cor_RtlImageRvaToVa64(PTR_IMAGE_NT_HEADERS64 NtHeaders, PBYTE Base, ULONG Rva, ULONG FileLength) { LIMITED_METHOD_CONTRACT; PIMAGE_SECTION_HEADER NtSection = Cor_RtlImageRvaToSection64(NtHeaders, Rva, FileLength); if (NtSection != NULL) return (Base + (Rva - VAL32(NtSection->VirtualAddress)) + VAL32(NtSection->PointerToRawData)); else return NULL; } EXTERN_C PBYTE Cor_RtlImageRvaToVa(PTR_IMAGE_NT_HEADERS NtHeaders, PBYTE Base, ULONG Rva, ULONG FileLength) { LIMITED_METHOD_CONTRACT; if (NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC)) return Cor_RtlImageRvaToVa32((PTR_IMAGE_NT_HEADERS32)NtHeaders, Base, Rva, FileLength); else if(NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC)) return Cor_RtlImageRvaToVa64((PTR_IMAGE_NT_HEADERS64)NtHeaders, Base, Rva, FileLength); else { _ASSERTE(!"Invalid File Type"); return NULL; } } EXTERN_C PBYTE Cor_RtlImageDirToVa(PTR_IMAGE_NT_HEADERS NtHeaders, PBYTE Base, UINT DirIndex, ULONG FileLength) { LIMITED_METHOD_CONTRACT; if (NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC)) return Cor_RtlImageRvaToVa32((PTR_IMAGE_NT_HEADERS32)NtHeaders, Base, VAL32(((PTR_IMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.DataDirectory[DirIndex].VirtualAddress), FileLength); else if(NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC)) return Cor_RtlImageRvaToVa64((PTR_IMAGE_NT_HEADERS64)NtHeaders, Base, VAL32(((PTR_IMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.DataDirectory[DirIndex].VirtualAddress), FileLength); else { _ASSERTE(!"Invalid File Type"); return NULL; } } EXTERN_C PIMAGE_SECTION_HEADER Cor_RtlImageRvaRangeToSection(PTR_IMAGE_NT_HEADERS NtHeaders, ULONG Rva, ULONG Range, ULONG FileLength) { LIMITED_METHOD_CONTRACT; ULONG i; PTR_IMAGE_SECTION_HEADER NtSection; if (!Range) return Cor_RtlImageRvaToSection(NtHeaders, Rva, FileLength); NtSection = PTR_IMAGE_FIRST_SECTION( NtHeaders ); for (i=0; iFileHeader.NumberOfSections); i++) { if (FileLength && ((VAL32(NtSection->PointerToRawData) > FileLength) || (VAL32(NtSection->SizeOfRawData) > FileLength - VAL32(NtSection->PointerToRawData)))) return NULL; if (Rva >= VAL32(NtSection->VirtualAddress) && Rva + Range <= VAL32(NtSection->VirtualAddress) + VAL32(NtSection->SizeOfRawData)) return NtSection; ++NtSection; } return NULL; } EXTERN_C DWORD Cor_RtlImageRvaToOffset(PTR_IMAGE_NT_HEADERS NtHeaders, ULONG Rva, ULONG FileLength) { LIMITED_METHOD_CONTRACT; PIMAGE_SECTION_HEADER NtSection = Cor_RtlImageRvaToSection(NtHeaders, Rva, FileLength); if (NtSection) return ((Rva - VAL32(NtSection->VirtualAddress)) + VAL32(NtSection->PointerToRawData)); else return NULL; }