summaryrefslogtreecommitdiff
path: root/src/md/enc/peparse.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/md/enc/peparse.cpp')
-rw-r--r--src/md/enc/peparse.cpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/md/enc/peparse.cpp b/src/md/enc/peparse.cpp
new file mode 100644
index 0000000000..3bb6c413cd
--- /dev/null
+++ b/src/md/enc/peparse.cpp
@@ -0,0 +1,148 @@
+// 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.
+
+#include "stdafx.h"
+
+#include <windows.h>
+#include <corhdr.h>
+#include "corerror.h"
+#include "pedecoder.h"
+
+
+static const char g_szCORMETA[] = ".cormeta";
+
+
+HRESULT CLiteWeightStgdbRW::FindImageMetaData(PVOID pImage, DWORD dwFileLength, BOOL bMappedImage, PVOID *ppMetaData, ULONG *pcbMetaData)
+{
+#ifndef DACCESS_COMPILE
+ PEDecoder pe;
+
+ // We need to use different PEDecoder initialization based on the type of data we give it.
+ // We use the one with a 'bool' as the second argument when dealing with a mapped file,
+ // and we use the one that takes a COUNT_T as the second argument when dealing with a
+ // flat file.
+ if (bMappedImage)
+ {
+ if (FAILED(pe.Init(pImage, false)) ||
+ !pe.CheckNTHeaders())
+ {
+ return COR_E_BADIMAGEFORMAT;
+ }
+ }
+ else
+ {
+ pe.Init(pImage, (COUNT_T)dwFileLength);
+ }
+
+ // Minimally validate image
+ if (!pe.CheckCorHeader())
+ return COR_E_BADIMAGEFORMAT;
+
+
+ COUNT_T size = 0;
+
+ *ppMetaData = (void *)pe.GetMetadata(&size);
+
+ // Couldn't find any IL metadata in this image
+ if (*ppMetaData == NULL)
+ return CLDB_E_NO_DATA;
+
+ if (pcbMetaData != NULL)
+ *pcbMetaData = size;
+
+ return S_OK;
+#else
+ DacNotImpl();
+ return E_NOTIMPL;
+#endif
+} // CLiteWeightStgdbRW::FindImageMetaData
+
+//
+// Note: Remove once defined in winnt.h
+//
+typedef struct ANON_OBJECT_HEADER2 {
+ WORD Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN
+ WORD Sig2; // Must be 0xffff
+ WORD Version; // >= 2 (implies the CLSID field, Flags and metadata info are present)
+ WORD Machine;
+ DWORD TimeDateStamp;
+ CLSID ClassID; // Used to invoke CoCreateInstance
+ DWORD SizeOfData; // Size of data that follows the header
+ DWORD Flags;
+ DWORD MetaDataSize; // Size of CLR metadata
+ DWORD MetaDataOffset; // Offset of CLR metadata
+} ANON_OBJECT_HEADER2;
+
+#define ANON_OBJECT_HAS_CORMETA 0x00000001
+#define ANON_OBJECT_IS_PUREMSIL 0x00000002
+
+HRESULT CLiteWeightStgdbRW::FindObjMetaData(PVOID pImage, DWORD dwFileLength, PVOID *ppMetaData, ULONG *pcbMetaData)
+{
+ DWORD dwSize = 0;
+ DWORD dwOffset = 0;
+
+ ANON_OBJECT_HEADER2 *pAnonImageHdr = (ANON_OBJECT_HEADER2 *) pImage; // Anonymous object header
+
+ // Check to see if this is a LTCG object
+ if (dwFileLength >= sizeof(ANON_OBJECT_HEADER2) &&
+ pAnonImageHdr->Sig1 == VAL16(IMAGE_FILE_MACHINE_UNKNOWN) &&
+ pAnonImageHdr->Sig2 == VAL16(IMPORT_OBJECT_HDR_SIG2))
+ {
+ // Version 1 anonymous objects don't have metadata info
+ if (VAL16(pAnonImageHdr->Version) < 2)
+ goto BadFormat;
+
+ // Anonymous objects contain the metadata info in the header
+ dwOffset = VAL32(pAnonImageHdr->MetaDataOffset);
+ dwSize = VAL32(pAnonImageHdr->MetaDataSize);
+ }
+ else
+ {
+ // Check to see if we have enough data
+ if (dwFileLength < sizeof(IMAGE_FILE_HEADER))
+ goto BadFormat;
+
+ IMAGE_FILE_HEADER *pImageHdr = (IMAGE_FILE_HEADER *) pImage; // Header for the .obj file.
+
+ // Walk each section looking for .cormeta.
+ DWORD nSections = VAL16(pImageHdr->NumberOfSections);
+
+ // Check to see if we have enough data
+ S_UINT32 nSectionsSize = S_UINT32(sizeof(IMAGE_FILE_HEADER)) + S_UINT32(nSections) * S_UINT32(sizeof(IMAGE_SECTION_HEADER));
+ if (nSectionsSize.IsOverflow() || (dwFileLength < nSectionsSize.Value()))
+ goto BadFormat;
+
+ IMAGE_SECTION_HEADER *pSectionHdr = (IMAGE_SECTION_HEADER *)(pImageHdr + 1); // Section header.
+
+ for (DWORD i=0; i<nSections; i++, pSectionHdr++)
+ {
+ // Simple comparison to section name.
+ if (memcmp((const char *) pSectionHdr->Name, g_szCORMETA, sizeof(pSectionHdr->Name)) == 0)
+ {
+ dwOffset = VAL32(pSectionHdr->PointerToRawData);
+ dwSize = VAL32(pSectionHdr->SizeOfRawData);
+ break;
+ }
+ }
+ }
+
+ if (dwOffset == 0 || dwSize == 0)
+ goto BadFormat;
+
+ // Check that raw data in the section is actually within the file.
+ {
+ S_UINT32 dwEndOffset = S_UINT32(dwOffset) + S_UINT32(dwSize);
+ if ((dwOffset >= dwFileLength) || dwEndOffset.IsOverflow() || (dwEndOffset.Value() > dwFileLength))
+ goto BadFormat;
+ }
+
+ *ppMetaData = (PVOID) ((ULONG_PTR) pImage + dwOffset);
+ *pcbMetaData = dwSize;
+ return (S_OK);
+
+BadFormat:
+ *ppMetaData = NULL;
+ *pcbMetaData = 0;
+ return (COR_E_BADIMAGEFORMAT);
+}