diff options
Diffstat (limited to 'src/inc/pedecoder.inl')
-rw-r--r-- | src/inc/pedecoder.inl | 1429 |
1 files changed, 1429 insertions, 0 deletions
diff --git a/src/inc/pedecoder.inl b/src/inc/pedecoder.inl new file mode 100644 index 0000000000..b75c4959f9 --- /dev/null +++ b/src/inc/pedecoder.inl @@ -0,0 +1,1429 @@ +// 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.inl +// + +// -------------------------------------------------------------------------------- + +#ifndef _PEDECODER_INL_ +#define _PEDECODER_INL_ + +#include "pedecoder.h" +#include "ex.h" + +#ifndef DACCESS_COMPILE + +inline PEDecoder::PEDecoder() + : m_base(0), + m_size(0), + m_flags(0), + m_pNTHeaders(nullptr), + m_pCorHeader(nullptr), + m_pNativeHeader(nullptr), + m_pReadyToRunHeader(nullptr) +{ + CONTRACTL + { + CONSTRUCTOR_CHECK; + NOTHROW; + CANNOT_TAKE_LOCK; + GC_NOTRIGGER; + } + CONTRACTL_END; +} +#else +inline PEDecoder::PEDecoder() +{ + LIMITED_METHOD_CONTRACT; +} +#endif // #ifndef DACCESS_COMPILE + +inline PTR_VOID PEDecoder::GetBase() const +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return PTR_VOID(m_base); +} + +inline BOOL PEDecoder::IsMapped() const +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return (m_flags & FLAG_MAPPED) != 0; +} + +inline BOOL PEDecoder::IsRelocated() const +{ + LIMITED_METHOD_CONTRACT; + + return (m_flags & FLAG_RELOCATED) != 0; +} + +inline void PEDecoder::SetRelocated() +{ + m_flags |= FLAG_RELOCATED; +} + +inline BOOL PEDecoder::IsFlat() const +{ + LIMITED_METHOD_CONTRACT; + + return HasContents() && !IsMapped(); +} + +inline BOOL PEDecoder::HasContents() const +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return (m_flags & FLAG_CONTENTS) != 0; +} + +inline COUNT_T PEDecoder::GetSize() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return m_size; +} + +inline PEDecoder::PEDecoder(PTR_VOID mappedBase, bool fixedUp /*= FALSE*/) + : m_base(dac_cast<TADDR>(mappedBase)), + m_size(0), + m_flags(FLAG_MAPPED | FLAG_CONTENTS | FLAG_NT_CHECKED | (fixedUp ? FLAG_RELOCATED : 0)), + m_pNTHeaders(nullptr), + m_pCorHeader(nullptr), + m_pNativeHeader(nullptr), + m_pReadyToRunHeader(nullptr) +{ + CONTRACTL + { + CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(mappedBase)); + PRECONDITION(CheckAligned(mappedBase, OS_PAGE_SIZE)); + PRECONDITION(PEDecoder(mappedBase,fixedUp).CheckNTHeaders()); + THROWS; + GC_NOTRIGGER; + SO_TOLERANT; + SUPPORTS_DAC; + } + CONTRACTL_END; + + // Temporarily set the size to 2 pages, so we can get the headers. + m_size = OS_PAGE_SIZE*2; + + m_pNTHeaders = PTR_IMAGE_NT_HEADERS(FindNTHeaders()); + if (!m_pNTHeaders) + ThrowHR(COR_E_BADIMAGEFORMAT); + + m_size = VAL32(m_pNTHeaders->OptionalHeader.SizeOfImage); +} + +#ifndef DACCESS_COMPILE + +//REM +//what's the right way to do this? +//we want to use some against TADDR, but also want to do +//some against what's just in the current process. +//m_base is a TADDR in DAC all the time, though. +//Have to implement separate fn to do the lookup?? +inline PEDecoder::PEDecoder(void *flatBase, COUNT_T size) + : m_base((TADDR)flatBase), + m_size(size), + m_flags(FLAG_CONTENTS), + m_pNTHeaders(NULL), + m_pCorHeader(NULL), + m_pNativeHeader(NULL), + m_pReadyToRunHeader(NULL) +{ + CONTRACTL + { + CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(flatBase)); + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; +} + +inline void PEDecoder::Init(void *flatBase, COUNT_T size) +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION((size == 0) || CheckPointer(flatBase)); + PRECONDITION(!HasContents()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + m_base = (TADDR)flatBase; + m_size = size; + m_flags = FLAG_CONTENTS; +} + + + +inline HRESULT PEDecoder::Init(void *mappedBase, bool fixedUp /*= FALSE*/) +{ + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(CheckPointer(mappedBase)); + PRECONDITION(CheckAligned(mappedBase, OS_PAGE_SIZE)); + PRECONDITION(!HasContents()); + } + CONTRACTL_END; + + m_base = (TADDR)mappedBase; + m_flags = FLAG_MAPPED | FLAG_CONTENTS; + if (fixedUp) + m_flags |= FLAG_RELOCATED; + + // Temporarily set the size to 2 pages, so we can get the headers. + m_size = OS_PAGE_SIZE*2; + + m_pNTHeaders = FindNTHeaders(); + if (!m_pNTHeaders) + return COR_E_BADIMAGEFORMAT; + + m_size = VAL32(m_pNTHeaders->OptionalHeader.SizeOfImage); + return S_OK; +} + +inline void PEDecoder::Reset() +{ + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + m_base=NULL; + m_flags=NULL; + m_size=NULL; + m_pNTHeaders=NULL; + m_pCorHeader=NULL; + m_pNativeHeader=NULL; + m_pReadyToRunHeader=NULL; +} +#endif // #ifndef DACCESS_COMPILE + + +inline IMAGE_NT_HEADERS32 *PEDecoder::GetNTHeaders32() const +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return dac_cast<PTR_IMAGE_NT_HEADERS32>(FindNTHeaders()); +} + +inline IMAGE_NT_HEADERS64 *PEDecoder::GetNTHeaders64() const +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return dac_cast<PTR_IMAGE_NT_HEADERS64>(FindNTHeaders()); +} + +inline BOOL PEDecoder::Has32BitNTHeaders() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(HasNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + SUPPORTS_DAC; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return (FindNTHeaders()->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC)); +} + +inline const void *PEDecoder::GetHeaders(COUNT_T *pSize) const +{ + CONTRACT(const void *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + } + CONTRACT_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + if (pSize != NULL) + *pSize = VAL32(FindNTHeaders()->OptionalHeader.SizeOfHeaders); + + RETURN (const void *) m_base; +} + +inline BOOL PEDecoder::IsDll() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return ((FindNTHeaders()->FileHeader.Characteristics & VAL16(IMAGE_FILE_DLL)) != 0); +} + +inline BOOL PEDecoder::HasBaseRelocations() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return ((FindNTHeaders()->FileHeader.Characteristics & VAL16(IMAGE_FILE_RELOCS_STRIPPED)) == 0); +} + +inline const void *PEDecoder::GetPreferredBase() const +{ + CONTRACT(const void *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); + } + CONTRACT_END; + + if (Has32BitNTHeaders()) + RETURN (const void *) (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.ImageBase); + else + RETURN (const void *) (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.ImageBase); +} + +inline COUNT_T PEDecoder::GetVirtualSize() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + SO_TOLERANT; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL32(FindNTHeaders()->OptionalHeader.SizeOfImage); +} + +inline WORD PEDecoder::GetSubsystem() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + SO_TOLERANT; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL16(FindNTHeaders()->OptionalHeader.Subsystem); +} + +inline WORD PEDecoder::GetDllCharacteristics() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL16(FindNTHeaders()->OptionalHeader.DllCharacteristics); +} + +inline DWORD PEDecoder::GetTimeDateStamp() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return VAL32(FindNTHeaders()->FileHeader.TimeDateStamp); +} + +inline DWORD PEDecoder::GetCheckSum() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL32(FindNTHeaders()->OptionalHeader.CheckSum); +} + +inline DWORD PEDecoder::GetFileAlignment() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL32(FindNTHeaders()->OptionalHeader.FileAlignment); +} + +inline DWORD PEDecoder::GetSectionAlignment() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL32(FindNTHeaders()->OptionalHeader.SectionAlignment); +} + +inline WORD PEDecoder::GetMachine() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return VAL16(FindNTHeaders()->FileHeader.Machine); +} + +inline WORD PEDecoder::GetCharacteristics() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return VAL16(FindNTHeaders()->FileHeader.Characteristics); +} + +inline SIZE_T PEDecoder::GetSizeOfStackReserve() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfStackReserve); + else + return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfStackReserve); +} + + +inline SIZE_T PEDecoder::GetSizeOfStackCommit() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfStackCommit); + else + return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfStackCommit); +} + + +inline SIZE_T PEDecoder::GetSizeOfHeapReserve() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfHeapReserve); + else + return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfHeapReserve); +} + + +inline SIZE_T PEDecoder::GetSizeOfHeapCommit() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfHeapCommit); + else + return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfHeapCommit); +} + +inline UINT32 PEDecoder::GetLoaderFlags() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return VAL32(GetNTHeaders32()->OptionalHeader.LoaderFlags); + else + return VAL32(GetNTHeaders64()->OptionalHeader.LoaderFlags); +} + +inline UINT32 PEDecoder::GetWin32VersionValue() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return VAL32(GetNTHeaders32()->OptionalHeader.Win32VersionValue); + else + return VAL32(GetNTHeaders64()->OptionalHeader.Win32VersionValue); +} + +inline COUNT_T PEDecoder::GetNumberOfRvaAndSizes() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return VAL32(GetNTHeaders32()->OptionalHeader.NumberOfRvaAndSizes); + else + return VAL32(GetNTHeaders64()->OptionalHeader.NumberOfRvaAndSizes); +} + +inline BOOL PEDecoder::HasDirectoryEntry(int entry) const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + SO_TOLERANT; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return (GetNTHeaders32()->OptionalHeader.DataDirectory[entry].VirtualAddress != 0); + else + return (GetNTHeaders64()->OptionalHeader.DataDirectory[entry].VirtualAddress != 0); +} + +inline IMAGE_DATA_DIRECTORY *PEDecoder::GetDirectoryEntry(int entry) const +{ + CONTRACT(IMAGE_DATA_DIRECTORY *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + SO_TOLERANT; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + if (Has32BitNTHeaders()) + RETURN dac_cast<PTR_IMAGE_DATA_DIRECTORY>( + dac_cast<TADDR>(GetNTHeaders32()) + + offsetof(IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory) + + entry * sizeof(IMAGE_DATA_DIRECTORY)); + else + RETURN dac_cast<PTR_IMAGE_DATA_DIRECTORY>( + dac_cast<TADDR>(GetNTHeaders64()) + + offsetof(IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory) + + entry * sizeof(IMAGE_DATA_DIRECTORY)); +} + +inline TADDR PEDecoder::GetDirectoryEntryData(int entry, COUNT_T *pSize) const +{ + CONTRACT(TADDR) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckDirectoryEntry(entry, 0, NULL_OK)); + PRECONDITION(CheckPointer(pSize, NULL_OK)); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer((void *)RETVAL, NULL_OK)); + SO_TOLERANT; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + IMAGE_DATA_DIRECTORY *pDir = GetDirectoryEntry(entry); + + if (pSize != NULL) + *pSize = VAL32(pDir->Size); + + RETURN GetDirectoryData(pDir); +} + +inline TADDR PEDecoder::GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir) const +{ + CONTRACT(TADDR) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckDirectory(pDir, 0, NULL_OK)); + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + SUPPORTS_DAC; + POSTCONDITION(CheckPointer((void *)RETVAL, NULL_OK)); + CANNOT_TAKE_LOCK; + } + CONTRACT_END; + + RETURN GetRvaData(VAL32(pDir->VirtualAddress)); +} + +inline TADDR PEDecoder::GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir, COUNT_T *pSize) const +{ + CONTRACT(TADDR) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckDirectory(pDir, 0, NULL_OK)); + PRECONDITION(CheckPointer(pSize)); + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + SUPPORTS_DAC; + POSTCONDITION(CheckPointer((void *)RETVAL, NULL_OK)); + CANNOT_TAKE_LOCK; + } + CONTRACT_END; + + *pSize = VAL32(pDir->Size); + + RETURN GetRvaData(VAL32(pDir->VirtualAddress)); +} + +inline TADDR PEDecoder::GetInternalAddressData(SIZE_T address) const +{ + CONTRACT(TADDR) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckInternalAddress(address, NULL_OK)); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer((void *)RETVAL)); + SO_TOLERANT; + } + CONTRACT_END; + + RETURN GetRvaData(InternalAddressToRva(address)); +} + +inline BOOL PEDecoder::HasCorHeader() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + SUPPORTS_DAC; + GC_NOTRIGGER; + SO_TOLERANT; + } + CONTRACTL_END; + + return HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_COMHEADER); +} + +inline BOOL PEDecoder::IsILOnly() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(HasCorHeader()); + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + SUPPORTS_DAC; + } + CONTRACTL_END; + + // Pretend that ready-to-run images are IL-only + return((GetCorHeader()->Flags & VAL32(COMIMAGE_FLAGS_ILONLY)) != 0) || HasReadyToRunHeader(); +} + +inline COUNT_T PEDecoder::RvaToOffset(RVA rva) const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckRva(rva,NULL_OK)); + NOTHROW; + CANNOT_TAKE_LOCK; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + if(rva > 0) + { + IMAGE_SECTION_HEADER *section = RvaToSection(rva); + if (section == NULL) + return rva; + + return rva - VAL32(section->VirtualAddress) + VAL32(section->PointerToRawData); + } + else return 0; +} + +inline RVA PEDecoder::OffsetToRva(COUNT_T fileOffset) const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckOffset(fileOffset,NULL_OK)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + if(fileOffset > 0) + { + IMAGE_SECTION_HEADER *section = OffsetToSection(fileOffset); + PREFIX_ASSUME (section!=NULL); //TODO: actually it is possible that it si null we need to rethink how we handle this cases and do better there + + return fileOffset - VAL32(section->PointerToRawData) + VAL32(section->VirtualAddress); + } + else return 0; +} + + +inline BOOL PEDecoder::IsStrongNameSigned() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(HasCorHeader()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + SO_TOLERANT; + } + CONTRACTL_END; + + return ((GetCorHeader()->Flags & VAL32(COMIMAGE_FLAGS_STRONGNAMESIGNED)) != 0); +} + + +inline BOOL PEDecoder::HasStrongNameSignature() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(HasCorHeader()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + SO_TOLERANT; + } + CONTRACTL_END; + + return (GetCorHeader()->StrongNameSignature.VirtualAddress != 0); +} + +inline CHECK PEDecoder::CheckStrongNameSignature() const +{ + CONTRACT_CHECK + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasCorHeader()); + PRECONDITION(HasStrongNameSignature()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_CHECK_END; + + return CheckDirectory(&GetCorHeader()->StrongNameSignature, IMAGE_SCN_MEM_WRITE, NULL_OK); +} + +inline PTR_CVOID PEDecoder::GetStrongNameSignature(COUNT_T *pSize) const +{ + CONTRACT(PTR_CVOID) + { + INSTANCE_CHECK; + PRECONDITION(HasCorHeader()); + PRECONDITION(HasStrongNameSignature()); + PRECONDITION(CheckStrongNameSignature()); + PRECONDITION(CheckPointer(pSize, NULL_OK)); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + } + CONTRACT_END; + + IMAGE_DATA_DIRECTORY *pDir = &GetCorHeader()->StrongNameSignature; + + if (pSize != NULL) + *pSize = VAL32(pDir->Size); + + RETURN dac_cast<PTR_CVOID>(GetDirectoryData(pDir)); +} + +inline BOOL PEDecoder::HasTls() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + } + CONTRACTL_END; + + return HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_TLS); +} + +inline CHECK PEDecoder::CheckTls() const +{ + CONTRACT_CHECK + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + } + CONTRACT_CHECK_END; + + CHECK(CheckDirectoryEntry(IMAGE_DIRECTORY_ENTRY_TLS, 0, NULL_OK)); + + IMAGE_TLS_DIRECTORY *pTlsHeader = (IMAGE_TLS_DIRECTORY *) GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_TLS); + + CHECK(CheckUnderflow(VALPTR(pTlsHeader->EndAddressOfRawData), VALPTR(pTlsHeader->StartAddressOfRawData))); + CHECK(VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData) <= COUNT_T_MAX); + + CHECK(CheckInternalAddress(VALPTR(pTlsHeader->StartAddressOfRawData), + (COUNT_T) (VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData)))); + + CHECK_OK; +} + +inline PTR_VOID PEDecoder::GetTlsRange(COUNT_T * pSize) const +{ + CONTRACT(void *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasTls()); + PRECONDITION(CheckTls()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + } + CONTRACT_END; + + IMAGE_TLS_DIRECTORY *pTlsHeader = + PTR_IMAGE_TLS_DIRECTORY(GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_TLS)); + + if (pSize != 0) + *pSize = (COUNT_T) (VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData)); + PREFIX_ASSUME (pTlsHeader!=NULL); + RETURN PTR_VOID(GetInternalAddressData(pTlsHeader->StartAddressOfRawData)); +} + +inline UINT32 PEDecoder::GetTlsIndex() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasTls()); + PRECONDITION(CheckTls()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + IMAGE_TLS_DIRECTORY *pTlsHeader = (IMAGE_TLS_DIRECTORY *) GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_TLS); + + return (UINT32)*PTR_UINT32(GetInternalAddressData((SIZE_T)VALPTR(pTlsHeader->AddressOfIndex))); +} + +inline IMAGE_COR20_HEADER *PEDecoder::GetCorHeader() const +{ + CONTRACT(IMAGE_COR20_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasCorHeader()); + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + POSTCONDITION(CheckPointer(RETVAL)); + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + if (m_pCorHeader == NULL) + const_cast<PEDecoder *>(this)->m_pCorHeader = + dac_cast<PTR_IMAGE_COR20_HEADER>(FindCorHeader()); + + RETURN m_pCorHeader; +} + +inline BOOL PEDecoder::IsNativeMachineFormat() const +{ + if (!HasContents() || !HasNTHeaders() ) + return FALSE; + _ASSERTE(m_pNTHeaders); + WORD expectedFormat = HasCorHeader() && (HasNativeHeader() || HasReadyToRunHeader()) ? + IMAGE_FILE_MACHINE_NATIVE_NI : + IMAGE_FILE_MACHINE_NATIVE; + //do not call GetNTHeaders as we do not want to bother with PE32->PE32+ conversion + return m_pNTHeaders->FileHeader.Machine==expectedFormat; +} + +inline BOOL PEDecoder::IsI386() const +{ + if (!HasContents() || !HasNTHeaders() ) + return FALSE; + _ASSERTE(m_pNTHeaders); + //do not call GetNTHeaders as we do not want to bother with PE32->PE32+ conversion + return m_pNTHeaders->FileHeader.Machine==IMAGE_FILE_MACHINE_I386; +} + +inline CORCOMPILE_HEADER *PEDecoder::GetNativeHeader() const +{ + CONTRACT(CORCOMPILE_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasCorHeader()); + PRECONDITION(HasNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + SO_TOLERANT; + SUPPORTS_DAC; + CANNOT_TAKE_LOCK; + SO_TOLERANT; + } + CONTRACT_END; + + if (m_pNativeHeader == NULL) + const_cast<PEDecoder *>(this)->m_pNativeHeader = + dac_cast<PTR_CORCOMPILE_HEADER>(FindNativeHeader()); + + RETURN m_pNativeHeader; +} + +#ifdef FEATURE_PREJIT +inline const void * PEDecoder::GetNativePreferredBase() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return (const void *) GetNativeHeader()->ImageBase; +} + +inline BOOL PEDecoder::GetNativeILHasSecurityDirectory() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return (GetNativeHeader()->Flags & CORCOMPILE_HEADER_HAS_SECURITY_DIRECTORY) != 0; +} + +inline BOOL PEDecoder::GetNativeILIsIbcOptimized() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return (GetNativeHeader()->Flags & CORCOMPILE_HEADER_IS_IBC_OPTIMIZED) != 0; +} + +inline BOOL PEDecoder::GetNativeILHasReadyToRunHeader() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return (GetNativeHeader()->Flags & CORCOMPILE_HEADER_IS_READY_TO_RUN) != 0; +} + +inline BOOL PEDecoder::IsNativeILILOnly() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return((GetNativeHeader()->COR20Flags & VAL32(COMIMAGE_FLAGS_ILONLY)) != 0); +} + +inline BOOL PEDecoder::IsNativeILDll() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return((GetNativeHeader()->Characteristics & VAL16(IMAGE_FILE_DLL)) != 0); +} + + +inline void PEDecoder::GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine) const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + CORCOMPILE_HEADER * pNativeHeader = GetNativeHeader(); + PREFIX_ASSUME (pNativeHeader!=NULL); + + if (pdwKind != NULL) + *pdwKind = pNativeHeader->PEKind; + if (pdwMachine != NULL) + *pdwMachine = pNativeHeader->Machine; +} + +inline CORCOMPILE_DEPENDENCY * PEDecoder::GetNativeDependencies(COUNT_T *pCount) const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + IMAGE_DATA_DIRECTORY *pDir = &GetNativeHeader()->Dependencies; + + if (pCount != NULL) + *pCount = VAL32(pDir->Size)/sizeof(CORCOMPILE_DEPENDENCY); + + return (CORCOMPILE_DEPENDENCY *) GetDirectoryData(pDir); +} + +#endif // FEATURE_PREJIT + +// static +inline PTR_IMAGE_SECTION_HEADER PEDecoder::FindFirstSection(IMAGE_NT_HEADERS * pNTHeaders) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return dac_cast<PTR_IMAGE_SECTION_HEADER>( + dac_cast<TADDR>(pNTHeaders) + + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + + VAL16(pNTHeaders->FileHeader.SizeOfOptionalHeader)); +} + +inline COUNT_T PEDecoder::GetNumberOfSections() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return VAL16(FindNTHeaders()->FileHeader.NumberOfSections); +} + + +inline DWORD PEDecoder::GetImageIdentity() const +{ + WRAPPER_NO_CONTRACT; + return GetTimeDateStamp() ^ GetCheckSum() ^ DWORD( GetVirtualSize() ); +} + + +inline IMAGE_SECTION_HEADER *PEDecoder::FindFirstSection() const +{ + CONTRACT(IMAGE_SECTION_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + SUPPORTS_DAC; + } + CONTRACT_END; + + RETURN FindFirstSection(FindNTHeaders()); +} + +inline IMAGE_NT_HEADERS *PEDecoder::FindNTHeaders() const +{ + CONTRACT(IMAGE_NT_HEADERS *) + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + SO_TOLERANT; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + RETURN PTR_IMAGE_NT_HEADERS(m_base + VAL32(PTR_IMAGE_DOS_HEADER(m_base)->e_lfanew)); +} + +inline IMAGE_COR20_HEADER *PEDecoder::FindCorHeader() const +{ + CONTRACT(IMAGE_COR20_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(HasCorHeader()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + CANNOT_TAKE_LOCK; + SO_TOLERANT; + SUPPORTS_DAC; + } + CONTRACT_END; + + const IMAGE_COR20_HEADER * pCor=PTR_IMAGE_COR20_HEADER(GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_COMHEADER)); + RETURN ((IMAGE_COR20_HEADER*)pCor); +} + +inline CORCOMPILE_HEADER *PEDecoder::FindNativeHeader() const +{ + CONTRACT(CORCOMPILE_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(HasNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + SO_TOLERANT; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + RETURN PTR_CORCOMPILE_HEADER(GetDirectoryData(&GetCorHeader()->ManagedNativeHeader)); +} + +inline CHECK PEDecoder::CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva) +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + CHECK(CheckOverflow(rangeBase, rangeSize)); + CHECK(rva >= rangeBase); + CHECK(rva <= rangeBase + rangeSize); + CHECK_OK; +} + +inline CHECK PEDecoder::CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva, COUNT_T size) +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + CHECK(CheckOverflow(rangeBase, rangeSize)); + CHECK(CheckOverflow(rva, size)); + CHECK(rva >= rangeBase); + CHECK(rva + size <= rangeBase + rangeSize); + CHECK_OK; +} + +inline CHECK PEDecoder::CheckBounds(const void *rangeBase, COUNT_T rangeSize, const void *pointer) +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + CHECK(CheckOverflow(dac_cast<PTR_CVOID>(rangeBase), rangeSize)); + CHECK(dac_cast<TADDR>(pointer) >= dac_cast<TADDR>(rangeBase)); + CHECK(dac_cast<TADDR>(pointer) <= dac_cast<TADDR>(rangeBase) + rangeSize); + CHECK_OK; +} + +inline CHECK PEDecoder::CheckBounds(PTR_CVOID rangeBase, COUNT_T rangeSize, PTR_CVOID pointer, COUNT_T size) +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + CHECK(CheckOverflow(rangeBase, rangeSize)); + CHECK(CheckOverflow(pointer, size)); + CHECK(dac_cast<TADDR>(pointer) >= dac_cast<TADDR>(rangeBase)); + CHECK(dac_cast<TADDR>(pointer) + size <= dac_cast<TADDR>(rangeBase) + rangeSize); + CHECK_OK; +} + +inline void PEDecoder::GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + DWORD dwKind=0,dwMachine=0; + if(HasContents() && HasNTHeaders()) + { + dwMachine = GetMachine(); + + BOOL fIsPE32Plus = !Has32BitNTHeaders(); + + if (fIsPE32Plus) + dwKind |= (DWORD)pe32Plus; + + if (HasCorHeader()) + { + IMAGE_COR20_HEADER * pCorHdr = GetCorHeader(); + if(pCorHdr != NULL) + { + DWORD dwCorFlags = pCorHdr->Flags; + + if (dwCorFlags & VAL32(COMIMAGE_FLAGS_ILONLY)) + { + dwKind |= (DWORD)peILonly; +#ifdef _WIN64 + // compensate for shim promotion of PE32/ILONLY headers to PE32+ on WIN64 + if (fIsPE32Plus && (GetMachine() == IMAGE_FILE_MACHINE_I386)) + dwKind &= ~((DWORD)pe32Plus); +#endif + } + + if (COR_IS_32BIT_REQUIRED(dwCorFlags)) + dwKind |= (DWORD)pe32BitRequired; + else if (COR_IS_32BIT_PREFERRED(dwCorFlags)) + dwKind |= (DWORD)pe32BitPreferred; + + // compensate for MC++ peculiarity + if(dwKind == 0) + dwKind = (DWORD)pe32BitRequired; + } + else + { + dwKind |= (DWORD)pe32Unmanaged; + } + + if (HasReadyToRunHeader()) + { + if (dwMachine == IMAGE_FILE_MACHINE_NATIVE_NI) + { + // Supply the original machine type to the assembly binder + dwMachine = IMAGE_FILE_MACHINE_NATIVE; + } + + if ((GetReadyToRunHeader()->Flags & READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE) != 0) + { + // Supply the original PEKind/Machine to the assembly binder to make the full assembly name look like the original + dwKind = peILonly; + dwMachine = IMAGE_FILE_MACHINE_I386; + } + } + } + else + { + dwKind |= (DWORD)pe32Unmanaged; + } + } + + *pdwPEKind = dwKind; + *pdwMachine = dwMachine; +} + +inline BOOL PEDecoder::IsPlatformNeutral() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + DWORD dwKind, dwMachine; + GetPEKindAndMachine(&dwKind, &dwMachine); + return ((dwKind & (peILonly | pe32Plus | pe32BitRequired)) == peILonly) && (dwMachine == IMAGE_FILE_MACHINE_I386); +} + +inline BOOL PEDecoder::HasReadyToRunHeader() const +{ + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_TOLERANT; + SUPPORTS_DAC; + } + CONTRACTL_END; + + if (m_flags & FLAG_HAS_NO_READYTORUN_HEADER) + return FALSE; + + if (m_pReadyToRunHeader != NULL) + return TRUE; + + return FindReadyToRunHeader() != NULL; +} + +inline READYTORUN_HEADER * PEDecoder::GetReadyToRunHeader() const +{ + CONTRACT(READYTORUN_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasCorHeader()); + PRECONDITION(HasReadyToRunHeader()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + SO_TOLERANT; + SUPPORTS_DAC; + CANNOT_TAKE_LOCK; + SO_TOLERANT; + } + CONTRACT_END; + + if (m_pReadyToRunHeader != NULL) + RETURN m_pReadyToRunHeader; + + RETURN FindReadyToRunHeader(); +} + +#endif // _PEDECODER_INL_ |