mirror of https://github.com/UMSKT/xpmgr.git
703 lines
21 KiB
C++
703 lines
21 KiB
C++
// ==++==
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ==--==
|
|
// See code:EEStartup#TableOfContents for EE overview
|
|
/*****************************************************************************
|
|
** **
|
|
** Corhlpr.h - <STRIP>this file contains a set of "as is" code that may be **
|
|
** used by developers writing compilers and tools against **
|
|
** the Common Language Runtime. The code is not officially **
|
|
** supported, but is code being used by the Runtime itself. **
|
|
** </STRIP> **
|
|
** **
|
|
*****************************************************************************/
|
|
|
|
|
|
#ifndef __CORHLPR_H__
|
|
#define __CORHLPR_H__
|
|
#if defined(_MSC_VER) && defined(_X86_)
|
|
#pragma optimize("y", on) // If routines don't get inlined, don't pay the EBP frame penalty
|
|
#endif
|
|
|
|
#if defined(_MSC_VER) && defined(_X86_) && !defined(FPO_ON)
|
|
#pragma optimize("y", on) // Small critical routines, don't put in EBP frame
|
|
#define FPO_ON 1
|
|
#define CORHLPR_TURNED_FPO_ON 1
|
|
#endif
|
|
|
|
#include "cor.h"
|
|
#include "corhdr.h"
|
|
#include "corerror.h"
|
|
|
|
// This header is consumed both within the runtime and externally. In the former
|
|
// case we need to wrap memory allocations, in the latter there is no
|
|
// infrastructure to support this. Detect which way we're building and provide a
|
|
// very simple abstraction layer (handles allocating bytes only).
|
|
#ifdef _BLD_CLR
|
|
#include "new.hpp"
|
|
|
|
|
|
#define NEW_NOTHROW(_bytes) new (nothrow) BYTE[_bytes]
|
|
#define NEW_THROWS(_bytes) new BYTE[_bytes]
|
|
void DECLSPEC_NORETURN ThrowOutOfMemory();
|
|
inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY()
|
|
{
|
|
ThrowOutOfMemory();
|
|
}
|
|
#else
|
|
#define NEW_NOTHROW(_bytes) new BYTE[_bytes]
|
|
#define NEW_THROWS(_bytes) __CorHlprNewThrows(_bytes)
|
|
static inline void DECLSPEC_NORETURN __CorHlprThrowOOM()
|
|
{
|
|
RaiseException(STATUS_NO_MEMORY, 0, 0, NULL);
|
|
}
|
|
static inline BYTE *__CorHlprNewThrows(size_t bytes)
|
|
{
|
|
BYTE *pbMemory = new BYTE[bytes];
|
|
if (pbMemory == NULL)
|
|
__CorHlprThrowOOM();
|
|
return pbMemory;
|
|
}
|
|
inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY()
|
|
{
|
|
__CorHlprThrowOOM();
|
|
}
|
|
#endif
|
|
|
|
|
|
//*****************************************************************************
|
|
// There are a set of macros commonly used in the helpers which you will want
|
|
// to override to get richer behavior. The following defines what is needed
|
|
// if you chose not to do the extra work.
|
|
//*****************************************************************************
|
|
#ifndef IfFailGoto
|
|
#define IfFailGoto(EXPR, LABEL) \
|
|
do { hr = (EXPR); if(FAILED(hr)) { goto LABEL; } } while (0)
|
|
#endif
|
|
|
|
#ifndef IfFailGo
|
|
#define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit)
|
|
#endif
|
|
|
|
#ifndef IfFailRet
|
|
#define IfFailRet(EXPR) do { hr = (EXPR); if(FAILED(hr)) { return (hr); } } while (0)
|
|
#endif
|
|
|
|
#ifndef IfNullRet
|
|
#define IfNullRet(EXPR) do { if ((EXPR) == NULL){ return (E_OUTOFMEMORY); } } while (0)
|
|
#endif
|
|
|
|
|
|
#ifndef _ASSERTE
|
|
#define _ASSERTE(expr)
|
|
#endif
|
|
|
|
#ifndef COUNTOF
|
|
#define COUNTOF(a) (sizeof(a) / sizeof(*a))
|
|
#endif
|
|
|
|
#if !BIGENDIAN
|
|
#define VAL16(x) x
|
|
#define VAL32(x) x
|
|
#endif
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//***** Macro to assist with cleaning up local static variables
|
|
//
|
|
//*****************************************************************************
|
|
|
|
#define CHECK_LOCAL_STATIC_VAR(x) \
|
|
x \
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//***** Utility helpers
|
|
//
|
|
//*****************************************************************************
|
|
|
|
|
|
#define MAX_CLASSNAME_LENGTH 1024
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//***** Signature helpers
|
|
//
|
|
//*****************************************************************************
|
|
|
|
inline bool isCallConv(unsigned sigByte, CorCallingConvention conv)
|
|
{
|
|
return ((sigByte & IMAGE_CEE_CS_CALLCONV_MASK) == (unsigned) conv);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//***** File format helper classes
|
|
//
|
|
//*****************************************************************************
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
typedef struct tagCOR_ILMETHOD_SECT_SMALL : IMAGE_COR_ILMETHOD_SECT_SMALL {
|
|
//Data follows
|
|
const BYTE* Data() const
|
|
{
|
|
return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_SMALL));
|
|
}
|
|
|
|
bool IsSmall() const
|
|
{
|
|
return (Kind & CorILMethod_Sect_FatFormat) == 0;
|
|
}
|
|
|
|
bool More() const
|
|
{
|
|
return (Kind & CorILMethod_Sect_MoreSects) != 0;
|
|
}
|
|
} COR_ILMETHOD_SECT_SMALL;
|
|
|
|
|
|
/************************************/
|
|
/* NOTE this structure must be DWORD aligned!! */
|
|
typedef struct tagCOR_ILMETHOD_SECT_FAT : IMAGE_COR_ILMETHOD_SECT_FAT {
|
|
//Data follows
|
|
const BYTE* Data() const
|
|
{
|
|
return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_FAT));
|
|
}
|
|
|
|
//Endian-safe wrappers
|
|
unsigned GetKind() const {
|
|
/* return Kind; */
|
|
return *(BYTE*)this;
|
|
}
|
|
void SetKind(unsigned kind) {
|
|
/* Kind = kind; */
|
|
*(BYTE*)this = (BYTE)kind;
|
|
}
|
|
|
|
unsigned GetDataSize() const {
|
|
/* return DataSize; */
|
|
BYTE* p = (BYTE*)this;
|
|
return ((unsigned)*(p+1)) |
|
|
(((unsigned)*(p+2)) << 8) |
|
|
(((unsigned)*(p+3)) << 16);
|
|
}
|
|
void SetDataSize(unsigned datasize) {
|
|
/* DataSize = dataSize; */
|
|
BYTE* p = (BYTE*)this;
|
|
*(p+1) = (BYTE)(datasize);
|
|
*(p+2) = (BYTE)(datasize >> 8);
|
|
*(p+3) = (BYTE)(datasize >> 16);
|
|
}
|
|
} COR_ILMETHOD_SECT_FAT;
|
|
|
|
typedef struct tagCOR_ILMETHOD_SECT_EH_CLAUSE_FAT : public IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT {
|
|
//Endian-safe wrappers
|
|
CorExceptionFlag GetFlags() const {
|
|
return (CorExceptionFlag)VAL32((unsigned)Flags);
|
|
}
|
|
void SetFlags(CorExceptionFlag flags) {
|
|
Flags = (CorExceptionFlag)VAL32((unsigned)flags);
|
|
}
|
|
|
|
DWORD GetTryOffset() const {
|
|
return VAL32(TryOffset);
|
|
}
|
|
void SetTryOffset(DWORD Offset) {
|
|
TryOffset = VAL32(Offset);
|
|
}
|
|
|
|
DWORD GetTryLength() const {
|
|
return VAL32(TryLength);
|
|
}
|
|
void SetTryLength(DWORD Length) {
|
|
TryLength = VAL32(Length);
|
|
}
|
|
|
|
DWORD GetHandlerOffset() const {
|
|
return VAL32(HandlerOffset);
|
|
}
|
|
void SetHandlerOffset(DWORD Offset) {
|
|
HandlerOffset = VAL32(Offset);
|
|
}
|
|
|
|
DWORD GetHandlerLength() const {
|
|
return VAL32(HandlerLength);
|
|
}
|
|
void SetHandlerLength(DWORD Length) {
|
|
HandlerLength = VAL32(Length);
|
|
}
|
|
|
|
DWORD GetClassToken() const {
|
|
return VAL32(ClassToken);
|
|
}
|
|
void SetClassToken(DWORD tok) {
|
|
ClassToken = VAL32(tok);
|
|
}
|
|
|
|
DWORD GetFilterOffset() const {
|
|
return VAL32(FilterOffset);
|
|
}
|
|
void SetFilterOffset(DWORD offset) {
|
|
FilterOffset = VAL32(offset);
|
|
}
|
|
|
|
} COR_ILMETHOD_SECT_EH_CLAUSE_FAT;
|
|
|
|
//*****************************************************************************
|
|
struct COR_ILMETHOD_SECT_EH_FAT : public COR_ILMETHOD_SECT_FAT {
|
|
static unsigned Size(unsigned ehCount) {
|
|
return (sizeof(COR_ILMETHOD_SECT_EH_FAT) +
|
|
sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT) * (ehCount-1));
|
|
}
|
|
|
|
IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT Clauses[1]; // actually variable size
|
|
};
|
|
|
|
typedef struct tagCOR_ILMETHOD_SECT_EH_CLAUSE_SMALL : public IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL {
|
|
//Endian-safe wrappers
|
|
CorExceptionFlag GetFlags() const {
|
|
return (CorExceptionFlag)VAL16((SHORT)Flags);
|
|
}
|
|
void SetFlags(CorExceptionFlag flags) {
|
|
Flags = (CorExceptionFlag)VAL16((SHORT)flags);
|
|
}
|
|
|
|
DWORD GetTryOffset() const {
|
|
return VAL16(TryOffset);
|
|
}
|
|
void SetTryOffset(DWORD Offset) {
|
|
_ASSERTE((Offset & ~0xffff) == 0);
|
|
TryOffset = VAL16(Offset);
|
|
}
|
|
|
|
DWORD GetTryLength() const {
|
|
return TryLength;
|
|
}
|
|
void SetTryLength(DWORD Length) {
|
|
_ASSERTE((Length & ~0xff) == 0);
|
|
TryLength = Length;
|
|
}
|
|
|
|
DWORD GetHandlerOffset() const {
|
|
return VAL16(HandlerOffset);
|
|
}
|
|
void SetHandlerOffset(DWORD Offset) {
|
|
_ASSERTE((Offset & ~0xffff) == 0);
|
|
HandlerOffset = VAL16(Offset);
|
|
}
|
|
|
|
DWORD GetHandlerLength() const {
|
|
return HandlerLength;
|
|
}
|
|
void SetHandlerLength(DWORD Length) {
|
|
_ASSERTE((Length & ~0xff) == 0);
|
|
HandlerLength = Length;
|
|
}
|
|
|
|
DWORD GetClassToken() const {
|
|
return VAL32(ClassToken);
|
|
}
|
|
void SetClassToken(DWORD tok) {
|
|
ClassToken = VAL32(tok);
|
|
}
|
|
|
|
DWORD GetFilterOffset() const {
|
|
return VAL32(FilterOffset);
|
|
}
|
|
void SetFilterOffset(DWORD offset) {
|
|
FilterOffset = VAL32(offset);
|
|
}
|
|
} COR_ILMETHOD_SECT_EH_CLAUSE_SMALL;
|
|
|
|
//*****************************************************************************
|
|
struct COR_ILMETHOD_SECT_EH_SMALL : public COR_ILMETHOD_SECT_SMALL {
|
|
static unsigned Size(unsigned ehCount) {
|
|
return (sizeof(COR_ILMETHOD_SECT_EH_SMALL) +
|
|
sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL) * (ehCount-1));
|
|
}
|
|
|
|
WORD Reserved; // alignment padding
|
|
IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL Clauses[1]; // actually variable size
|
|
};
|
|
|
|
|
|
/************************************/
|
|
/* NOTE this structure must be DWORD aligned!! */
|
|
struct COR_ILMETHOD_SECT
|
|
{
|
|
bool More() const
|
|
{
|
|
return((AsSmall()->Kind & CorILMethod_Sect_MoreSects) != 0);
|
|
}
|
|
|
|
CorILMethodSect Kind() const
|
|
{
|
|
return((CorILMethodSect) (AsSmall()->Kind & CorILMethod_Sect_KindMask));
|
|
}
|
|
|
|
const COR_ILMETHOD_SECT* Next() const
|
|
{
|
|
if (!More()) return(0);
|
|
return ((COR_ILMETHOD_SECT*)(((BYTE *)this) + DataSize()))->Align();
|
|
}
|
|
|
|
const BYTE* Data() const
|
|
{
|
|
if (IsFat()) return(AsFat()->Data());
|
|
return(AsSmall()->Data());
|
|
}
|
|
|
|
unsigned DataSize() const
|
|
{
|
|
if (Kind() == CorILMethod_Sect_EHTable)
|
|
{
|
|
// VB and MC++ shipped with bug where they have not accounted for size of COR_ILMETHOD_SECT_EH_XXX
|
|
// in DataSize. To avoid breaking these images, we will align the size of EH sections up. This works
|
|
// because IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_XXX is bigger than COR_ILMETHOD_SECT_EH_XXX
|
|
// (see VSWhidbey #99031 and related bugs for details).
|
|
|
|
if (IsFat())
|
|
return Fat.Size(Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
|
|
else
|
|
return Small.Size(Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL));
|
|
}
|
|
else
|
|
{
|
|
if (IsFat()) return(AsFat()->GetDataSize());
|
|
return(AsSmall()->DataSize);
|
|
}
|
|
}
|
|
|
|
friend struct COR_ILMETHOD;
|
|
friend struct tagCOR_ILMETHOD_FAT;
|
|
friend struct tagCOR_ILMETHOD_TINY;
|
|
bool IsFat() const
|
|
{
|
|
return((AsSmall()->Kind & CorILMethod_Sect_FatFormat) != 0);
|
|
}
|
|
|
|
const COR_ILMETHOD_SECT* Align() const
|
|
{
|
|
return((COR_ILMETHOD_SECT*) ((((UINT_PTR) this) + 3) & ~3));
|
|
}
|
|
|
|
protected:
|
|
const COR_ILMETHOD_SECT_FAT* AsFat() const
|
|
{
|
|
return((COR_ILMETHOD_SECT_FAT*) this);
|
|
}
|
|
|
|
const COR_ILMETHOD_SECT_SMALL* AsSmall() const
|
|
{
|
|
return((COR_ILMETHOD_SECT_SMALL*) this);
|
|
}
|
|
|
|
public:
|
|
// The body is either a COR_ILMETHOD_SECT_SMALL or COR_ILMETHOD_SECT_FAT
|
|
// (as indicated by the CorILMethod_Sect_FatFormat bit
|
|
union {
|
|
COR_ILMETHOD_SECT_EH_SMALL Small;
|
|
COR_ILMETHOD_SECT_EH_FAT Fat;
|
|
};
|
|
};
|
|
|
|
|
|
/***********************************/
|
|
// exported functions (implementation in Format\Format.cpp:
|
|
extern "C" {
|
|
IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* __stdcall SectEH_EHClause(void *pSectEH, unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff);
|
|
// compute the size of the section (best format)
|
|
// codeSize is the size of the method
|
|
// deprecated
|
|
unsigned __stdcall SectEH_SizeWithCode(unsigned ehCount, unsigned codeSize);
|
|
|
|
// will return worse-case size and then Emit will return actual size
|
|
unsigned __stdcall SectEH_SizeWorst(unsigned ehCount);
|
|
|
|
// will return exact size which will match the size returned by Emit
|
|
unsigned __stdcall SectEH_SizeExact(unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses);
|
|
|
|
// emit the section (best format);
|
|
unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount,
|
|
IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses,
|
|
BOOL moreSections, BYTE* outBuff,
|
|
ULONG* ehTypeOffsets = 0);
|
|
} // extern "C"
|
|
|
|
|
|
struct COR_ILMETHOD_SECT_EH : public COR_ILMETHOD_SECT
|
|
{
|
|
unsigned EHCount() const
|
|
{
|
|
return (unsigned)(IsFat() ? (Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)) :
|
|
(Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL)));
|
|
}
|
|
|
|
// return one clause in its fat form. Use 'buff' if needed
|
|
const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* EHClause(unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff) const
|
|
{
|
|
return SectEH_EHClause((void *)this, idx, buff);
|
|
};
|
|
// compute the size of the section (best format)
|
|
// codeSize is the size of the method
|
|
// deprecated
|
|
unsigned static Size(unsigned ehCount, unsigned codeSize)
|
|
{
|
|
return SectEH_SizeWithCode(ehCount, codeSize);
|
|
};
|
|
|
|
// will return worse-case size and then Emit will return actual size
|
|
unsigned static Size(unsigned ehCount)
|
|
{
|
|
return SectEH_SizeWorst(ehCount);
|
|
};
|
|
|
|
// will return exact size which will match the size returned by Emit
|
|
unsigned static Size(unsigned ehCount, const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses)
|
|
{
|
|
return SectEH_SizeExact(ehCount, (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses);
|
|
};
|
|
|
|
// emit the section (best format);
|
|
unsigned static Emit(unsigned size, unsigned ehCount,
|
|
const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses,
|
|
bool moreSections, BYTE* outBuff,
|
|
ULONG* ehTypeOffsets = 0)
|
|
{
|
|
return SectEH_Emit(size, ehCount,
|
|
(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses,
|
|
moreSections, outBuff, ehTypeOffsets);
|
|
};
|
|
};
|
|
|
|
|
|
/***************************************************************************/
|
|
/* Used when the method is tiny (< 64 bytes), and there are no local vars */
|
|
typedef struct tagCOR_ILMETHOD_TINY : IMAGE_COR_ILMETHOD_TINY
|
|
{
|
|
bool IsTiny() const
|
|
{
|
|
return((Flags_CodeSize & (CorILMethod_FormatMask >> 1)) == CorILMethod_TinyFormat);
|
|
}
|
|
|
|
unsigned GetCodeSize() const
|
|
{
|
|
return(((unsigned) Flags_CodeSize) >> (CorILMethod_FormatShift-1));
|
|
}
|
|
|
|
unsigned GetMaxStack() const
|
|
{
|
|
return(8);
|
|
}
|
|
|
|
BYTE* GetCode() const
|
|
{
|
|
return(((BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_TINY));
|
|
}
|
|
|
|
DWORD GetLocalVarSigTok() const
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
COR_ILMETHOD_SECT* GetSect() const
|
|
{
|
|
return(0);
|
|
}
|
|
} COR_ILMETHOD_TINY;
|
|
|
|
|
|
/************************************/
|
|
// This strucuture is the 'fat' layout, where no compression is attempted.
|
|
// Note that this structure can be added on at the end, thus making it extensible
|
|
typedef struct tagCOR_ILMETHOD_FAT : IMAGE_COR_ILMETHOD_FAT
|
|
{
|
|
//Endian-safe wrappers
|
|
unsigned GetSize() const {
|
|
/* return Size; */
|
|
BYTE* p = (BYTE*)this;
|
|
return *(p+1) >> 4;
|
|
}
|
|
void SetSize(unsigned size) {
|
|
/* Size = size; */
|
|
BYTE* p = (BYTE*)this;
|
|
*(p+1) = (BYTE)((*(p+1) & 0x0F) | (size << 4));
|
|
}
|
|
|
|
unsigned GetFlags() const {
|
|
/* return Flags; */
|
|
BYTE* p = (BYTE*)this;
|
|
return ((unsigned)*(p+0)) | (( ((unsigned)*(p+1)) & 0x0F) << 8);
|
|
}
|
|
void SetFlags(unsigned flags) {
|
|
/* flags = Flags; */
|
|
BYTE* p = (BYTE*)this;
|
|
*p = (BYTE)flags;
|
|
*(p+1) = (BYTE)((*(p+1) & 0xF0) | ((flags >> 8) & 0x0F));
|
|
}
|
|
|
|
bool IsFat() const {
|
|
/* return((IMAGE_COR_ILMETHOD_FAT::GetFlags() & CorILMethod_FormatMask) == CorILMethod_FatFormat); */
|
|
return (*(BYTE*)this & CorILMethod_FormatMask) == CorILMethod_FatFormat;
|
|
}
|
|
|
|
unsigned GetMaxStack() const {
|
|
/* return MaxStack; */
|
|
return VAL16(*(USHORT*)((BYTE*)this+2));
|
|
}
|
|
void SetMaxStack(unsigned maxStack) {
|
|
/* MaxStack = maxStack; */
|
|
*(USHORT*)((BYTE*)this+2) = VAL16((USHORT)maxStack);
|
|
}
|
|
|
|
unsigned GetCodeSize() const
|
|
{
|
|
return VAL32(CodeSize);
|
|
}
|
|
|
|
void SetCodeSize(DWORD Size)
|
|
{
|
|
CodeSize = VAL32(Size);
|
|
}
|
|
|
|
mdToken GetLocalVarSigTok() const
|
|
{
|
|
return VAL32(LocalVarSigTok);
|
|
}
|
|
|
|
void SetLocalVarSigTok(mdSignature tok)
|
|
{
|
|
LocalVarSigTok = VAL32(tok);
|
|
}
|
|
|
|
BYTE* GetCode() const {
|
|
return(((BYTE*) this) + 4*GetSize());
|
|
}
|
|
|
|
bool More() const {
|
|
// return (GetFlags() & CorILMethod_MoreSects) != 0;
|
|
return (*(BYTE*)this & CorILMethod_MoreSects) != 0;
|
|
}
|
|
|
|
const COR_ILMETHOD_SECT* GetSect() const {
|
|
if (!More()) return (0);
|
|
return(((COR_ILMETHOD_SECT*) (GetCode() + GetCodeSize()))->Align());
|
|
}
|
|
} COR_ILMETHOD_FAT;
|
|
|
|
|
|
extern "C" {
|
|
/************************************/
|
|
// exported functions (impl. Format\Format.cpp)
|
|
unsigned __stdcall IlmethodSize(COR_ILMETHOD_FAT* header, BOOL MoreSections);
|
|
// emit the header (bestFormat) return amount emitted
|
|
unsigned __stdcall IlmethodEmit(unsigned size, COR_ILMETHOD_FAT* header,
|
|
BOOL moreSections, BYTE* outBuff);
|
|
}
|
|
|
|
struct COR_ILMETHOD
|
|
{
|
|
// a COR_ILMETHOD header should not be decoded by hand. Instead us
|
|
// COR_ILMETHOD_DECODER to decode it.
|
|
friend class COR_ILMETHOD_DECODER;
|
|
|
|
// compute the size of the header (best format)
|
|
unsigned static Size(const COR_ILMETHOD_FAT* header, bool MoreSections)
|
|
{
|
|
return IlmethodSize((COR_ILMETHOD_FAT*)header,MoreSections);
|
|
};
|
|
// emit the header (bestFormat) return amount emitted
|
|
unsigned static Emit(unsigned size, const COR_ILMETHOD_FAT* header,
|
|
bool moreSections, BYTE* outBuff)
|
|
{
|
|
return IlmethodEmit(size, (COR_ILMETHOD_FAT*)header, moreSections, outBuff);
|
|
};
|
|
|
|
//private:
|
|
union
|
|
{
|
|
COR_ILMETHOD_TINY Tiny;
|
|
COR_ILMETHOD_FAT Fat;
|
|
};
|
|
// Code follows the Header, then immedately after the code comes
|
|
// any sections (COR_ILMETHOD_SECT).
|
|
};
|
|
|
|
extern "C" {
|
|
/***************************************************************************/
|
|
/* COR_ILMETHOD_DECODER is the only way functions internal to the EE should
|
|
fetch data from a COR_ILMETHOD. This way any dependancy on the file format
|
|
(and the multiple ways of encoding the header) is centralized to the
|
|
COR_ILMETHOD_DECODER constructor) */
|
|
void __stdcall DecoderInit(void * pThis, COR_ILMETHOD* header);
|
|
int __stdcall DecoderGetOnDiskSize(void * pThis, COR_ILMETHOD* header);
|
|
} // extern "C"
|
|
|
|
class COR_ILMETHOD_DECODER : public COR_ILMETHOD_FAT
|
|
{
|
|
public:
|
|
// Typically the ONLY way you should access COR_ILMETHOD is through
|
|
// this constructor so format changes are easier.
|
|
COR_ILMETHOD_DECODER(const COR_ILMETHOD* header)
|
|
{
|
|
DecoderInit(this,(COR_ILMETHOD*)header);
|
|
};
|
|
|
|
// The above variant of the constructor can not do a 'complete' job, because
|
|
// it can not look up the local variable signature meta-data token.
|
|
// This method should be used when you have access to the Meta data API
|
|
// If the construction fails, the 'Code' field is set to 0
|
|
|
|
enum DecoderStatus {SUCCESS, FORMAT_ERROR, VERIFICATION_ERROR};
|
|
|
|
// If we want the decoder to verify the that local signature is OK we
|
|
// will pass a non-NULL value for wbStatus
|
|
//
|
|
// When using LazyInit we want ask that the local signature be verified
|
|
// But if we fail verification we still need access to the 'Code' field
|
|
// Because we may be able to demand SkipVerification and thus it was OK
|
|
// to have had a verification error.
|
|
|
|
COR_ILMETHOD_DECODER(COR_ILMETHOD* header,
|
|
void *pInternalImport,
|
|
DecoderStatus* wbStatus);
|
|
|
|
unsigned EHCount() const
|
|
{
|
|
return (EH != 0) ? EH->EHCount() : 0;
|
|
}
|
|
|
|
unsigned GetHeaderSize() const
|
|
{
|
|
return GetCodeSize() + ((EH != 0) ? EH->DataSize() : 0);
|
|
}
|
|
|
|
// returns total size of method for use in copying
|
|
int GetOnDiskSize(const COR_ILMETHOD* header)
|
|
{
|
|
return DecoderGetOnDiskSize(this,(COR_ILMETHOD*)header);
|
|
}
|
|
|
|
// Flags these are available because we inherit COR_ILMETHOD_FAT
|
|
// MaxStack
|
|
// CodeSize
|
|
const BYTE * Code;
|
|
PCCOR_SIGNATURE LocalVarSig; // pointer to signature blob, or 0 if none
|
|
DWORD cbLocalVarSig; // size of dignature blob, or 0 if none
|
|
const COR_ILMETHOD_SECT_EH * EH; // eh table if any 0 if none
|
|
const COR_ILMETHOD_SECT * Sect; // additional sections 0 if none
|
|
}; // class COR_ILMETHOD_DECODER
|
|
|
|
#if defined(_MSC_VER) && defined(_X86_)
|
|
#pragma optimize("", on) // restore command line default optimizations
|
|
#endif
|
|
|
|
#endif // __CORHLPR_H__
|
|
|