summaryrefslogtreecommitdiff
path: root/src/inc/pedecoder.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/pedecoder.h')
-rw-r--r--src/inc/pedecoder.h478
1 files changed, 478 insertions, 0 deletions
diff --git a/src/inc/pedecoder.h b/src/inc/pedecoder.h
new file mode 100644
index 0000000000..d5bae87bb7
--- /dev/null
+++ b/src/inc/pedecoder.h
@@ -0,0 +1,478 @@
+// 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.
+// --------------------------------------------------------------------------------
+// PEDecoder.h
+//
+
+// --------------------------------------------------------------------------------
+
+// --------------------------------------------------------------------------------
+// PEDecoder - Utility class for reading and verifying PE files.
+//
+// Note that the Check step is optional if you are willing to trust the
+// integrity of the image.
+// (Or at any rate can be factored into an initial verification step.)
+//
+// Functions which access the memory of the PE file take a "flat" flag - this
+// indicates whether the PE images data has been loaded flat the way it resides in the file,
+// or if the sections have been mapped into memory at the proper base addresses.
+//
+// Finally, some functions take an optional "size" argument, which can be used for
+// range verification. This is an optional parameter, but if you omit it be sure
+// you verify the size in some other way.
+// --------------------------------------------------------------------------------
+
+
+#ifndef PEDECODER_H_
+#define PEDECODER_H_
+
+// --------------------------------------------------------------------------------
+// Required headers
+// --------------------------------------------------------------------------------
+
+#include "windows.h"
+#include "clrtypes.h"
+#include "check.h"
+#include "contract.h"
+#include "cor.h"
+#include "corhdr.h"
+
+#ifdef FEATURE_PREJIT
+#include "corcompile.h"
+#else // FEATURE_PREJIT
+typedef DPTR(struct COR_ILMETHOD) PTR_COR_ILMETHOD;
+struct CORCOMPILE_HEADER { int dummy_field; };
+typedef DPTR(struct CORCOMPILE_HEADER) PTR_CORCOMPILE_HEADER;
+#define CORCOMPILE_IS_POINTER_TAGGED(fixup) (false)
+#endif // FEATURE_PREJIT
+
+#include "readytorun.h"
+typedef DPTR(struct READYTORUN_HEADER) PTR_READYTORUN_HEADER;
+
+typedef DPTR(IMAGE_COR20_HEADER) PTR_IMAGE_COR20_HEADER;
+
+// --------------------------------------------------------------------------------
+// Forward declared types
+// --------------------------------------------------------------------------------
+
+class Module;
+
+// --------------------------------------------------------------------------------
+// RVA definition
+// --------------------------------------------------------------------------------
+
+// Needs to be DWORD to avoid conflict with <imagehlp.h>
+typedef DWORD RVA;
+
+#ifdef _MSC_VER
+// Wrapper to suppress ambigous overload problems with MSVC.
+inline CHECK CheckOverflow(RVA value1, COUNT_T value2)
+{
+ WRAPPER_NO_CONTRACT;
+ CHECK(CheckOverflow((UINT32) value1, (UINT32) value2));
+ CHECK_OK;
+}
+#endif // _MSC_VER
+
+// --------------------------------------------------------------------------------
+// IMAGE_FILE_MACHINE_NATIVE
+// --------------------------------------------------------------------------------
+
+#if defined(_TARGET_X86_)
+#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_I386
+#elif defined(_TARGET_AMD64_)
+#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_AMD64
+#elif defined(_TARGET_ARM_)
+#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARMNT
+#elif defined(_TARGET_ARM64_)
+#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARM64
+#else
+#error "port me"
+#endif
+
+// Machine code for native images
+#if defined(__APPLE__)
+#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x4644
+#elif defined(__FreeBSD__)
+#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0xADC4
+#elif defined(__linux__)
+#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x7B79
+#elif defined(__NetBSD__)
+#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x1993
+#else
+#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0
+#endif
+
+#define IMAGE_FILE_MACHINE_NATIVE_NI (IMAGE_FILE_MACHINE_NATIVE ^ IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE)
+
+// --------------------------------------------------------------------------------
+// Types
+// --------------------------------------------------------------------------------
+
+typedef DPTR(class PEDecoder) PTR_PEDecoder;
+
+class PEDecoder
+{
+ public:
+
+ // ------------------------------------------------------------
+ // Public API
+ // ------------------------------------------------------------
+
+ // Access functions are divided into 3 categories:
+ // Has - check if the element is present
+ // Check - Do consistency checks on the element (requires Has).
+ // This step is optional if you are willing to trust the integrity of the
+ // image. (It is asserted in a checked build.)
+ // Get - Access the element (requires Has and Check)
+
+ PEDecoder();
+ PEDecoder(void *flatBase, COUNT_T size); // flatBase is the raw disk layout data (using MapViewOfFile)
+ PEDecoder(PTR_VOID mappedBase, bool relocated = FALSE); // mappedBase is the mapped/expanded file (using LoadLibrary)
+
+ void Init(void *flatBase, COUNT_T size);
+ HRESULT Init(void *mappedBase, bool relocated = FALSE);
+ void Reset(); //make sure you don't have a thread race
+
+ PTR_VOID GetBase() const; // Currently loaded base, as opposed to GetPreferredBase()
+ BOOL IsMapped() const;
+ BOOL IsRelocated() const;
+ BOOL IsFlat() const;
+ BOOL HasContents() const;
+ COUNT_T GetSize() const; // size of file on disk, as opposed to GetVirtualSize()
+
+ // High level image checks:
+
+ CHECK CheckFormat() const; // Check whatever is present
+ CHECK CheckNTFormat() const; // Check a PE file image
+ CHECK CheckCORFormat() const; // Check a COR image (IL or native)
+ CHECK CheckILFormat() const; // Check a managed image
+ CHECK CheckILOnlyFormat() const; // Check an IL only image
+ CHECK CheckNativeFormat() const; // Check a native image
+
+ // NT header access
+
+ BOOL HasNTHeaders() const;
+ CHECK CheckNTHeaders() const;
+
+ IMAGE_NT_HEADERS32 *GetNTHeaders32() const;
+ IMAGE_NT_HEADERS64 *GetNTHeaders64() const;
+ BOOL Has32BitNTHeaders() const;
+
+ const void *GetHeaders(COUNT_T *pSize = NULL) const;
+
+ BOOL IsDll() const;
+ BOOL HasBaseRelocations() const;
+ const void *GetPreferredBase() const; // OptionalHeaders.ImageBase
+ COUNT_T GetVirtualSize() const; // OptionalHeaders.SizeOfImage - size of mapped/expanded image in memory
+ WORD GetSubsystem() const;
+ WORD GetDllCharacteristics() const;
+ DWORD GetTimeDateStamp() const;
+ DWORD GetCheckSum() const;
+ WORD GetMachine() const;
+ WORD GetCharacteristics() const;
+ DWORD GetFileAlignment() const;
+ DWORD GetSectionAlignment() const;
+ SIZE_T GetSizeOfStackReserve() const;
+ SIZE_T GetSizeOfStackCommit() const;
+ SIZE_T GetSizeOfHeapReserve() const;
+ SIZE_T GetSizeOfHeapCommit() const;
+ UINT32 GetLoaderFlags() const;
+ UINT32 GetWin32VersionValue() const;
+ COUNT_T GetNumberOfRvaAndSizes() const;
+ COUNT_T GetNumberOfSections() const;
+ IMAGE_SECTION_HEADER *FindFirstSection() const;
+ IMAGE_SECTION_HEADER *FindSection(LPCSTR sectionName) const;
+
+ DWORD GetImageIdentity() const;
+
+ // Directory entry access
+
+ BOOL HasDirectoryEntry(int entry) const;
+ CHECK CheckDirectoryEntry(int entry, int forbiddenFlags = 0, IsNullOK ok = NULL_NOT_OK) const;
+ IMAGE_DATA_DIRECTORY *GetDirectoryEntry(int entry) const;
+ TADDR GetDirectoryEntryData(int entry, COUNT_T *pSize = NULL) const;
+
+ // IMAGE_DATA_DIRECTORY access
+
+ CHECK CheckDirectory(IMAGE_DATA_DIRECTORY *pDir, int forbiddenFlags = 0, IsNullOK ok = NULL_NOT_OK) const;
+ TADDR GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir) const;
+ TADDR GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir, COUNT_T *pSize) const;
+
+ // Basic RVA access
+
+ CHECK CheckRva(RVA rva, IsNullOK ok = NULL_NOT_OK) const;
+ CHECK CheckRva(RVA rva, COUNT_T size, int forbiddenFlags=0, IsNullOK ok = NULL_NOT_OK) const;
+ TADDR GetRvaData(RVA rva, IsNullOK ok = NULL_NOT_OK) const;
+ // Called with ok=NULL_OK only for mapped fields (RVA statics)
+
+ CHECK CheckData(const void *data, IsNullOK ok = NULL_NOT_OK) const;
+ CHECK CheckData(const void *data, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const;
+ RVA GetDataRva(const TADDR data) const;
+ BOOL PointerInPE(PTR_CVOID data) const;
+
+ // Flat mapping utilities - using PointerToRawData instead of (Relative)VirtualAddress
+ CHECK CheckOffset(COUNT_T fileOffset, IsNullOK ok = NULL_NOT_OK) const;
+ CHECK CheckOffset(COUNT_T fileOffset, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const;
+ TADDR GetOffsetData(COUNT_T fileOffset, IsNullOK ok = NULL_NOT_OK) const;
+ // Called with ok=NULL_OK only for mapped fields (RVA statics)
+
+ // Mapping between RVA and file offsets
+ COUNT_T RvaToOffset(RVA rva) const;
+ RVA OffsetToRva(COUNT_T fileOffset) const;
+
+ // Base intra-image pointer access
+ // (These are for pointers retrieved out of the PE image)
+
+ CHECK CheckInternalAddress(SIZE_T address, IsNullOK ok = NULL_NOT_OK) const;
+ CHECK CheckInternalAddress(SIZE_T address, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const;
+ TADDR GetInternalAddressData(SIZE_T address) const;
+
+ // CLR loader IL Image verification - these checks apply to IL_ONLY images.
+
+ BOOL IsILOnly() const;
+ CHECK CheckILOnly() const;
+
+ void LayoutILOnly(void *base, BOOL allowFullPE = FALSE) const;
+
+ // Strong name & hashing support
+
+ BOOL HasStrongNameSignature() const;
+ CHECK CheckStrongNameSignature() const;
+ PTR_CVOID GetStrongNameSignature(COUNT_T *pSize = NULL) const;
+
+ // CorHeader flag support
+
+ // IsStrongNameSigned indicates whether the signature has been filled in.
+ // (otherwise if it has a signature it is delay signed.)
+ BOOL IsStrongNameSigned() const; // TRUE if the COMIMAGE_FLAGS_STRONGNAMESIGNED flag is set
+
+ // TLS
+
+ BOOL HasTls() const;
+ CHECK CheckTls() const;
+ PTR_VOID GetTlsRange(COUNT_T *pSize = NULL) const;
+ UINT32 GetTlsIndex() const;
+
+#ifndef FEATURE_PAL
+ // Win32 resources
+ void *GetWin32Resource(LPCWSTR lpName, LPCWSTR lpType, COUNT_T *pSize = NULL) const;
+#endif // FEATURE_PAL
+
+ // COR header fields
+
+ BOOL HasCorHeader() const;
+ CHECK CheckCorHeader() const;
+ IMAGE_COR20_HEADER *GetCorHeader() const;
+
+ PTR_CVOID GetMetadata(COUNT_T *pSize = NULL) const;
+
+ const void *GetResources(COUNT_T *pSize = NULL) const;
+ CHECK CheckResource(COUNT_T offset) const;
+ const void *GetResource(COUNT_T offset, COUNT_T *pSize = NULL) const;
+
+ BOOL HasManagedEntryPoint() const;
+ ULONG GetEntryPointToken() const;
+ IMAGE_COR_VTABLEFIXUP *GetVTableFixups(COUNT_T *pCount = NULL) const;
+
+ // Native header access
+ BOOL HasNativeHeader() const;
+ CHECK CheckNativeHeader() const;
+ CORCOMPILE_HEADER *GetNativeHeader() const;
+ BOOL IsNativeMachineFormat() const;
+ BOOL IsI386() const;
+
+ void GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine); // Returns CorPEKind flags
+ BOOL IsPlatformNeutral(); // Returns TRUE for IL-only platform neutral images
+
+ //
+ // Verifies that the IL is within the bounds of the image.
+ //
+ CHECK CheckILMethod(RVA rva);
+
+ //
+ // Compute size of IL blob. Assumes that the IL is within the bounds of the image - make sure
+ // to call CheckILMethod before calling this method.
+ //
+ static SIZE_T ComputeILMethodSize(TADDR pIL);
+
+ // Debug directory access, returns NULL if no such entry
+ PTR_IMAGE_DEBUG_DIRECTORY GetDebugDirectoryEntry(UINT index) const;
+
+#ifdef FEATURE_PREJIT
+ CHECK CheckNativeHeaderVersion() const;
+
+ // ManagedNative fields
+ CORCOMPILE_CODE_MANAGER_ENTRY *GetNativeCodeManagerTable() const;
+ CORCOMPILE_EE_INFO_TABLE *GetNativeEEInfoTable() const;
+ void *GetNativeHelperTable(COUNT_T *pSize = NULL) const;
+ CORCOMPILE_VERSION_INFO *GetNativeVersionInfo() const;
+ CORCOMPILE_VERSION_INFO *GetNativeVersionInfoMaybeNull(bool skipCheckNativeHeader = false) const;
+ BOOL HasNativeDebugMap() const;
+ TADDR GetNativeDebugMap(COUNT_T *pSize = NULL) const;
+ Module *GetPersistedModuleImage(COUNT_T *pSize = NULL) const;
+ PCODE GetNativeHotCode(COUNT_T * pSize = NULL) const;
+ PCODE GetNativeCode(COUNT_T * pSize = NULL) const;
+ PCODE GetNativeColdCode(COUNT_T * pSize = NULL) const;
+
+ CORCOMPILE_METHOD_PROFILE_LIST *GetNativeProfileDataList(COUNT_T *pSize = NULL) const;
+ PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize = NULL) const;
+ const void *GetNativePreferredBase() const;
+ BOOL GetNativeILHasSecurityDirectory() const;
+ BOOL GetNativeILIsIbcOptimized() const;
+ BOOL GetNativeILHasReadyToRunHeader() const;
+ BOOL IsNativeILILOnly() const;
+ BOOL IsNativeILDll() const;
+ void GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine) const;
+ CORCOMPILE_DEPENDENCY * GetNativeDependencies(COUNT_T *pCount = NULL) const;
+
+ COUNT_T GetNativeImportTableCount() const;
+ CORCOMPILE_IMPORT_TABLE_ENTRY *GetNativeImportFromIndex(COUNT_T index) const;
+ CHECK CheckNativeImportFromIndex(COUNT_T index) const;
+
+ PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSections(COUNT_T *pCount = NULL) const;
+ PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSectionFromIndex(COUNT_T index) const;
+ PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSectionForRVA(RVA rva) const;
+
+ TADDR GetStubsTable(COUNT_T *pSize = NULL) const;
+ TADDR GetVirtualSectionsTable(COUNT_T *pSize = NULL) const;
+#endif // FEATURE_PREJIT
+
+ BOOL HasReadyToRunHeader() const;
+ READYTORUN_HEADER *GetReadyToRunHeader() const;
+
+ void GetEXEStackSizes(SIZE_T *PE_SizeOfStackReserve, SIZE_T *PE_SizeOfStackCommit) const;
+
+ CHECK CheckWillCreateGuardPage() const;
+
+ // Native DLLMain Entrypoint
+ BOOL HasNativeEntryPoint() const;
+ void *GetNativeEntryPoint() const;
+
+#ifdef _DEBUG
+ // Stress mode for relocations
+ static BOOL GetForceRelocs();
+ static BOOL ForceRelocForDLL(LPCWSTR lpFileName);
+#endif
+
+#ifdef DACCESS_COMPILE
+ void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, bool enumThis);
+#endif
+
+ protected:
+
+ // ------------------------------------------------------------
+ // Protected API for subclass use
+ // ------------------------------------------------------------
+
+ // Checking utilites
+ static CHECK CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva);
+ static CHECK CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva, COUNT_T size);
+
+ static CHECK CheckBounds(const void *rangeBase, COUNT_T rangeSize, const void *pointer);
+ static CHECK CheckBounds(PTR_CVOID rangeBase, COUNT_T rangeSize, PTR_CVOID pointer, COUNT_T size);
+
+ protected:
+
+ // Flat mapping utilities - using PointerToRawData instead of (Relative)VirtualAddress
+ IMAGE_SECTION_HEADER *RvaToSection(RVA rva) const;
+ IMAGE_SECTION_HEADER *OffsetToSection(COUNT_T fileOffset) const;
+
+ void SetRelocated();
+
+ private:
+
+ // ------------------------------------------------------------
+ // Internal functions
+ // ------------------------------------------------------------
+
+ enum METADATA_SECTION_TYPE
+ {
+ METADATA_SECTION_FULL,
+#ifdef FEATURE_PREJIT
+ METADATA_SECTION_MANIFEST
+#endif
+ };
+
+ IMAGE_DATA_DIRECTORY *GetMetaDataHelper(METADATA_SECTION_TYPE type) const;
+
+ static PTR_IMAGE_SECTION_HEADER FindFirstSection(IMAGE_NT_HEADERS * pNTHeaders);
+
+ IMAGE_NT_HEADERS *FindNTHeaders() const;
+ IMAGE_COR20_HEADER *FindCorHeader() const;
+ CORCOMPILE_HEADER *FindNativeHeader() const;
+ READYTORUN_HEADER *FindReadyToRunHeader() const;
+
+ // Flat mapping utilities
+ RVA InternalAddressToRva(SIZE_T address) const;
+
+ // NT header subchecks
+ CHECK CheckSection(COUNT_T previousAddressEnd, COUNT_T addressStart, COUNT_T addressSize,
+ COUNT_T previousOffsetEnd, COUNT_T offsetStart, COUNT_T offsetSize) const;
+
+ // Pure managed subchecks
+ CHECK CheckILOnlyImportDlls() const;
+ CHECK CheckILOnlyImportByNameTable(RVA rva) const;
+ CHECK CheckILOnlyBaseRelocations() const;
+ CHECK CheckILOnlyEntryPoint() const;
+
+ // ------------------------------------------------------------
+ // Instance members
+ // ------------------------------------------------------------
+
+ enum
+ {
+ FLAG_MAPPED = 0x01, // the file is mapped/hydrated (vs. the raw disk layout)
+ FLAG_CONTENTS = 0x02, // the file has contents
+ FLAG_RELOCATED = 0x04, // relocs have been applied
+ FLAG_NT_CHECKED = 0x10,
+ FLAG_COR_CHECKED = 0x20,
+ FLAG_IL_ONLY_CHECKED = 0x40,
+ FLAG_NATIVE_CHECKED = 0x80,
+
+ FLAG_HAS_NO_READYTORUN_HEADER = 0x100,
+ };
+
+ TADDR m_base;
+ COUNT_T m_size; // size of file on disk, as opposed to OptionalHeaders.SizeOfImage
+ ULONG m_flags;
+
+ PTR_IMAGE_NT_HEADERS m_pNTHeaders;
+ PTR_IMAGE_COR20_HEADER m_pCorHeader;
+ PTR_CORCOMPILE_HEADER m_pNativeHeader;
+ PTR_READYTORUN_HEADER m_pReadyToRunHeader;
+};
+
+//
+// MethodSectionIterator class is used to iterate hot (or) cold method section in an ngen image.
+// It can also iterate nibble maps generated by the JIT in a regular HeapList.
+//
+class MethodSectionIterator
+{
+ private:
+ PTR_DWORD m_codeTableStart;
+ PTR_DWORD m_codeTable;
+ PTR_DWORD m_codeTableEnd;
+
+ BYTE *m_code;
+
+ DWORD m_dword;
+ DWORD m_index;
+
+ BYTE *m_current;
+
+ public:
+
+ //If code is a target pointer, then GetMethodCode and FindMethodCode return
+ //target pointers. codeTable may be a pointer of either type, since it is
+ //converted internally into a host pointer.
+ MethodSectionIterator(const void *code, SIZE_T codeSize,
+ const void *codeTable, SIZE_T codeTableSize);
+ BOOL Next();
+ BYTE *GetMethodCode() { return m_current; } // Get the start of method code of the current method in the iterator
+};
+
+#include "pedecoder.inl"
+
+#endif // PEDECODER_H_