1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*****************************************************************************
6 ** **
7 ** Corhlpr.h - **
8 ** **
9 *****************************************************************************/
10
11
12#ifndef __CORHLPR_H__
13#define __CORHLPR_H__
14
15#if defined(_MSC_VER) && defined(_X86_) && !defined(FPO_ON)
16#pragma optimize("y", on) // Small critical routines, don't put in EBP frame
17#define FPO_ON 1
18#define CORHLPR_TURNED_FPO_ON 1
19#endif
20
21#include "cor.h"
22#include "corhdr.h"
23#include "corerror.h"
24
25// This header is consumed both within the runtime and externally. In the former
26// case we need to wrap memory allocations, in the latter there is no
27// infrastructure to support this. Detect which way we're building and provide a
28// very simple abstraction layer (handles allocating bytes only).
29#ifdef _BLD_CLR
30#include "new.hpp"
31
32
33#define NEW_NOTHROW(_bytes) new (nothrow) BYTE[_bytes]
34#define NEW_THROWS(_bytes) new BYTE[_bytes]
35void DECLSPEC_NORETURN ThrowOutOfMemory();
36inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY()
37{
38 ThrowOutOfMemory();
39}
40#else
41#define NEW_NOTHROW(_bytes) new BYTE[_bytes]
42#define NEW_THROWS(_bytes) __CorHlprNewThrows(_bytes)
43static inline void DECLSPEC_NORETURN __CorHlprThrowOOM()
44{
45 RaiseException(STATUS_NO_MEMORY, 0, 0, NULL);
46}
47static inline BYTE *__CorHlprNewThrows(size_t bytes)
48{
49 BYTE *pbMemory = new BYTE[bytes];
50 if (pbMemory == NULL)
51 __CorHlprThrowOOM();
52 return pbMemory;
53}
54inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY()
55{
56 __CorHlprThrowOOM();
57}
58#endif
59
60
61//*****************************************************************************
62// There are a set of macros commonly used in the helpers which you will want
63// to override to get richer behavior. The following defines what is needed
64// if you chose not to do the extra work.
65//*****************************************************************************
66#ifndef IfFailGoto
67#define IfFailGoto(EXPR, LABEL) \
68do { hr = (EXPR); if(FAILED(hr)) { goto LABEL; } } while (0)
69#endif
70
71#ifndef IfFailGo
72#define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit)
73#endif
74
75#ifndef IfFailRet
76#define IfFailRet(EXPR) do { hr = (EXPR); if(FAILED(hr)) { return (hr); } } while (0)
77#endif
78
79#ifndef IfNullRet
80#define IfNullRet(EXPR) do { if ((EXPR) == NULL){ return (E_OUTOFMEMORY); } } while (0)
81#endif
82
83
84#ifndef _ASSERTE
85#define _ASSERTE(expr)
86#endif
87
88#ifndef COUNTOF
89#define COUNTOF(a) (sizeof(a) / sizeof(*a))
90#endif
91
92#if !BIGENDIAN
93#define VAL16(x) x
94#define VAL32(x) x
95#endif
96
97
98//*****************************************************************************
99//
100//***** Macro to assist with cleaning up local static variables
101//
102//*****************************************************************************
103
104#define CHECK_LOCAL_STATIC_VAR(x) \
105 x \
106
107//*****************************************************************************
108//
109//***** Utility helpers
110//
111//*****************************************************************************
112
113
114#define MAX_CLASSNAME_LENGTH 1024
115
116//*****************************************************************************
117//
118//***** Signature helpers
119//
120//*****************************************************************************
121
122inline bool isCallConv(unsigned sigByte, CorCallingConvention conv)
123{
124 return ((sigByte & IMAGE_CEE_CS_CALLCONV_MASK) == (unsigned) conv);
125}
126
127//*****************************************************************************
128//
129//***** File format helper classes
130//
131//*****************************************************************************
132
133
134
135//*****************************************************************************
136typedef struct tagCOR_ILMETHOD_SECT_SMALL : IMAGE_COR_ILMETHOD_SECT_SMALL {
137 //Data follows
138 const BYTE* Data() const
139 {
140 return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_SMALL));
141 }
142
143 bool IsSmall() const
144 {
145 return (Kind & CorILMethod_Sect_FatFormat) == 0;
146 }
147
148 bool More() const
149 {
150 return (Kind & CorILMethod_Sect_MoreSects) != 0;
151 }
152} COR_ILMETHOD_SECT_SMALL;
153
154
155/************************************/
156/* NOTE this structure must be DWORD aligned!! */
157typedef struct tagCOR_ILMETHOD_SECT_FAT : IMAGE_COR_ILMETHOD_SECT_FAT {
158 //Data follows
159 const BYTE* Data() const
160 {
161 return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_FAT));
162 }
163
164 //Endian-safe wrappers
165 unsigned GetKind() const {
166 /* return Kind; */
167 return *(BYTE*)this;
168 }
169 void SetKind(unsigned kind) {
170 /* Kind = kind; */
171 *(BYTE*)this = (BYTE)kind;
172 }
173
174 unsigned GetDataSize() const {
175 /* return DataSize; */
176 BYTE* p = (BYTE*)this;
177 return ((unsigned)*(p+1)) |
178 (((unsigned)*(p+2)) << 8) |
179 (((unsigned)*(p+3)) << 16);
180 }
181 void SetDataSize(unsigned datasize) {
182 /* DataSize = dataSize; */
183 BYTE* p = (BYTE*)this;
184 *(p+1) = (BYTE)(datasize);
185 *(p+2) = (BYTE)(datasize >> 8);
186 *(p+3) = (BYTE)(datasize >> 16);
187 }
188} COR_ILMETHOD_SECT_FAT;
189
190typedef struct tagCOR_ILMETHOD_SECT_EH_CLAUSE_FAT : public IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT {
191 //Endian-safe wrappers
192 CorExceptionFlag GetFlags() const {
193 return (CorExceptionFlag)VAL32((unsigned)Flags);
194 }
195 void SetFlags(CorExceptionFlag flags) {
196 Flags = (CorExceptionFlag)VAL32((unsigned)flags);
197 }
198
199 DWORD GetTryOffset() const {
200 return VAL32(TryOffset);
201 }
202 void SetTryOffset(DWORD Offset) {
203 TryOffset = VAL32(Offset);
204 }
205
206 DWORD GetTryLength() const {
207 return VAL32(TryLength);
208 }
209 void SetTryLength(DWORD Length) {
210 TryLength = VAL32(Length);
211 }
212
213 DWORD GetHandlerOffset() const {
214 return VAL32(HandlerOffset);
215 }
216 void SetHandlerOffset(DWORD Offset) {
217 HandlerOffset = VAL32(Offset);
218 }
219
220 DWORD GetHandlerLength() const {
221 return VAL32(HandlerLength);
222 }
223 void SetHandlerLength(DWORD Length) {
224 HandlerLength = VAL32(Length);
225 }
226
227 DWORD GetClassToken() const {
228 return VAL32(ClassToken);
229 }
230 void SetClassToken(DWORD tok) {
231 ClassToken = VAL32(tok);
232 }
233
234 DWORD GetFilterOffset() const {
235 return VAL32(FilterOffset);
236 }
237 void SetFilterOffset(DWORD offset) {
238 FilterOffset = VAL32(offset);
239 }
240
241} COR_ILMETHOD_SECT_EH_CLAUSE_FAT;
242
243//*****************************************************************************
244struct COR_ILMETHOD_SECT_EH_FAT : public COR_ILMETHOD_SECT_FAT {
245 static unsigned Size(unsigned ehCount) {
246 return (sizeof(COR_ILMETHOD_SECT_EH_FAT) +
247 sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT) * (ehCount-1));
248 }
249
250 IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT Clauses[1]; // actually variable size
251};
252
253typedef struct tagCOR_ILMETHOD_SECT_EH_CLAUSE_SMALL : public IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL {
254 //Endian-safe wrappers
255 CorExceptionFlag GetFlags() const {
256 return (CorExceptionFlag)VAL16((SHORT)Flags);
257 }
258 void SetFlags(CorExceptionFlag flags) {
259 Flags = (CorExceptionFlag)VAL16((SHORT)flags);
260 }
261
262 DWORD GetTryOffset() const {
263 return VAL16(TryOffset);
264 }
265 void SetTryOffset(DWORD Offset) {
266 _ASSERTE((Offset & ~0xffff) == 0);
267 TryOffset = VAL16(Offset);
268 }
269
270 DWORD GetTryLength() const {
271 return TryLength;
272 }
273 void SetTryLength(DWORD Length) {
274 _ASSERTE((Length & ~0xff) == 0);
275 TryLength = Length;
276 }
277
278 DWORD GetHandlerOffset() const {
279 return VAL16(HandlerOffset);
280 }
281 void SetHandlerOffset(DWORD Offset) {
282 _ASSERTE((Offset & ~0xffff) == 0);
283 HandlerOffset = VAL16(Offset);
284 }
285
286 DWORD GetHandlerLength() const {
287 return HandlerLength;
288 }
289 void SetHandlerLength(DWORD Length) {
290 _ASSERTE((Length & ~0xff) == 0);
291 HandlerLength = Length;
292 }
293
294 DWORD GetClassToken() const {
295 return VAL32(ClassToken);
296 }
297 void SetClassToken(DWORD tok) {
298 ClassToken = VAL32(tok);
299 }
300
301 DWORD GetFilterOffset() const {
302 return VAL32(FilterOffset);
303 }
304 void SetFilterOffset(DWORD offset) {
305 FilterOffset = VAL32(offset);
306 }
307} COR_ILMETHOD_SECT_EH_CLAUSE_SMALL;
308
309//*****************************************************************************
310struct COR_ILMETHOD_SECT_EH_SMALL : public COR_ILMETHOD_SECT_SMALL {
311 static unsigned Size(unsigned ehCount) {
312 return (sizeof(COR_ILMETHOD_SECT_EH_SMALL) +
313 sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL) * (ehCount-1));
314 }
315
316 WORD Reserved; // alignment padding
317 IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL Clauses[1]; // actually variable size
318};
319
320
321/************************************/
322/* NOTE this structure must be DWORD aligned!! */
323struct COR_ILMETHOD_SECT
324{
325 bool More() const
326 {
327 return((AsSmall()->Kind & CorILMethod_Sect_MoreSects) != 0);
328 }
329
330 CorILMethodSect Kind() const
331 {
332 return((CorILMethodSect) (AsSmall()->Kind & CorILMethod_Sect_KindMask));
333 }
334
335 const COR_ILMETHOD_SECT* Next() const
336 {
337 if (!More()) return(0);
338 return ((COR_ILMETHOD_SECT*)(((BYTE *)this) + DataSize()))->Align();
339 }
340
341 const BYTE* Data() const
342 {
343 if (IsFat()) return(AsFat()->Data());
344 return(AsSmall()->Data());
345 }
346
347 unsigned DataSize() const
348 {
349 if (Kind() == CorILMethod_Sect_EHTable)
350 {
351 // VB and MC++ shipped with bug where they have not accounted for size of COR_ILMETHOD_SECT_EH_XXX
352 // in DataSize. To avoid breaking these images, we will align the size of EH sections up. This works
353 // because IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_XXX is bigger than COR_ILMETHOD_SECT_EH_XXX
354 // (see VSWhidbey #99031 and related bugs for details).
355
356 if (IsFat())
357 return Fat.Size(Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
358 else
359 return Small.Size(Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL));
360 }
361 else
362 {
363 if (IsFat()) return(AsFat()->GetDataSize());
364 return(AsSmall()->DataSize);
365 }
366 }
367
368 friend struct COR_ILMETHOD;
369 friend struct tagCOR_ILMETHOD_FAT;
370 friend struct tagCOR_ILMETHOD_TINY;
371 bool IsFat() const
372 {
373 return((AsSmall()->Kind & CorILMethod_Sect_FatFormat) != 0);
374 }
375
376 const COR_ILMETHOD_SECT* Align() const
377 {
378 return((COR_ILMETHOD_SECT*) ((((UINT_PTR) this) + 3) & ~3));
379 }
380
381protected:
382 const COR_ILMETHOD_SECT_FAT* AsFat() const
383 {
384 return((COR_ILMETHOD_SECT_FAT*) this);
385 }
386
387 const COR_ILMETHOD_SECT_SMALL* AsSmall() const
388 {
389 return((COR_ILMETHOD_SECT_SMALL*) this);
390 }
391
392public:
393 // The body is either a COR_ILMETHOD_SECT_SMALL or COR_ILMETHOD_SECT_FAT
394 // (as indicated by the CorILMethod_Sect_FatFormat bit
395 union {
396 COR_ILMETHOD_SECT_EH_SMALL Small;
397 COR_ILMETHOD_SECT_EH_FAT Fat;
398 };
399};
400
401
402/***********************************/
403// exported functions (implementation in Format\Format.cpp:
404extern "C" {
405IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* __stdcall SectEH_EHClause(void *pSectEH, unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff);
406 // compute the size of the section (best format)
407 // codeSize is the size of the method
408 // deprecated
409unsigned __stdcall SectEH_SizeWithCode(unsigned ehCount, unsigned codeSize);
410
411 // will return worse-case size and then Emit will return actual size
412unsigned __stdcall SectEH_SizeWorst(unsigned ehCount);
413
414 // will return exact size which will match the size returned by Emit
415unsigned __stdcall SectEH_SizeExact(unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses);
416
417 // emit the section (best format);
418unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount,
419 IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses,
420 BOOL moreSections, BYTE* outBuff,
421 ULONG* ehTypeOffsets = 0);
422} // extern "C"
423
424
425struct COR_ILMETHOD_SECT_EH : public COR_ILMETHOD_SECT
426{
427 unsigned EHCount() const
428 {
429 return (unsigned)(IsFat() ? (Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)) :
430 (Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL)));
431 }
432
433 // return one clause in its fat form. Use 'buff' if needed
434 const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* EHClause(unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff) const
435 {
436 return SectEH_EHClause((void *)this, idx, buff);
437 };
438 // compute the size of the section (best format)
439 // codeSize is the size of the method
440 // deprecated
441 unsigned static Size(unsigned ehCount, unsigned codeSize)
442 {
443 return SectEH_SizeWithCode(ehCount, codeSize);
444 };
445
446 // will return worse-case size and then Emit will return actual size
447 unsigned static Size(unsigned ehCount)
448 {
449 return SectEH_SizeWorst(ehCount);
450 };
451
452 // will return exact size which will match the size returned by Emit
453 unsigned static Size(unsigned ehCount, const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses)
454 {
455 return SectEH_SizeExact(ehCount, (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses);
456 };
457
458 // emit the section (best format);
459 unsigned static Emit(unsigned size, unsigned ehCount,
460 const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses,
461 bool moreSections, BYTE* outBuff,
462 ULONG* ehTypeOffsets = 0)
463 {
464 return SectEH_Emit(size, ehCount,
465 (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses,
466 moreSections, outBuff, ehTypeOffsets);
467 };
468};
469
470
471/***************************************************************************/
472/* Used when the method is tiny (< 64 bytes), and there are no local vars */
473typedef struct tagCOR_ILMETHOD_TINY : IMAGE_COR_ILMETHOD_TINY
474{
475 bool IsTiny() const
476 {
477 return((Flags_CodeSize & (CorILMethod_FormatMask >> 1)) == CorILMethod_TinyFormat);
478 }
479
480 unsigned GetCodeSize() const
481 {
482 return(((unsigned) Flags_CodeSize) >> (CorILMethod_FormatShift-1));
483 }
484
485 unsigned GetMaxStack() const
486 {
487 return(8);
488 }
489
490 BYTE* GetCode() const
491 {
492 return(((BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_TINY));
493 }
494
495 DWORD GetLocalVarSigTok() const
496 {
497 return(0);
498 }
499
500 COR_ILMETHOD_SECT* GetSect() const
501 {
502 return(0);
503 }
504} COR_ILMETHOD_TINY;
505
506
507/************************************/
508// This strucuture is the 'fat' layout, where no compression is attempted.
509// Note that this structure can be added on at the end, thus making it extensible
510typedef struct tagCOR_ILMETHOD_FAT : IMAGE_COR_ILMETHOD_FAT
511{
512 //Endian-safe wrappers
513 unsigned GetSize() const {
514 /* return Size; */
515 BYTE* p = (BYTE*)this;
516 return *(p+1) >> 4;
517 }
518 void SetSize(unsigned size) {
519 /* Size = size; */
520 BYTE* p = (BYTE*)this;
521 *(p+1) = (BYTE)((*(p+1) & 0x0F) | (size << 4));
522 }
523
524 unsigned GetFlags() const {
525 /* return Flags; */
526 BYTE* p = (BYTE*)this;
527 return ((unsigned)*(p+0)) | (( ((unsigned)*(p+1)) & 0x0F) << 8);
528 }
529 void SetFlags(unsigned flags) {
530 /* flags = Flags; */
531 BYTE* p = (BYTE*)this;
532 *p = (BYTE)flags;
533 *(p+1) = (BYTE)((*(p+1) & 0xF0) | ((flags >> 8) & 0x0F));
534 }
535
536 bool IsFat() const {
537 /* return((IMAGE_COR_ILMETHOD_FAT::GetFlags() & CorILMethod_FormatMask) == CorILMethod_FatFormat); */
538 return (*(BYTE*)this & CorILMethod_FormatMask) == CorILMethod_FatFormat;
539 }
540
541 unsigned GetMaxStack() const {
542 /* return MaxStack; */
543 return VAL16(*(USHORT*)((BYTE*)this+2));
544 }
545 void SetMaxStack(unsigned maxStack) {
546 /* MaxStack = maxStack; */
547 *(USHORT*)((BYTE*)this+2) = VAL16((USHORT)maxStack);
548 }
549
550 unsigned GetCodeSize() const
551 {
552 return VAL32(CodeSize);
553 }
554
555 void SetCodeSize(DWORD Size)
556 {
557 CodeSize = VAL32(Size);
558 }
559
560 mdToken GetLocalVarSigTok() const
561 {
562 return VAL32(LocalVarSigTok);
563 }
564
565 void SetLocalVarSigTok(mdSignature tok)
566 {
567 LocalVarSigTok = VAL32(tok);
568 }
569
570 BYTE* GetCode() const {
571 return(((BYTE*) this) + 4*GetSize());
572 }
573
574 bool More() const {
575 // return (GetFlags() & CorILMethod_MoreSects) != 0;
576 return (*(BYTE*)this & CorILMethod_MoreSects) != 0;
577 }
578
579 const COR_ILMETHOD_SECT* GetSect() const {
580 if (!More()) return (0);
581 return(((COR_ILMETHOD_SECT*) (GetCode() + GetCodeSize()))->Align());
582 }
583} COR_ILMETHOD_FAT;
584
585
586extern "C" {
587/************************************/
588// exported functions (impl. Format\Format.cpp)
589unsigned __stdcall IlmethodSize(COR_ILMETHOD_FAT* header, BOOL MoreSections);
590 // emit the header (bestFormat) return amount emitted
591unsigned __stdcall IlmethodEmit(unsigned size, COR_ILMETHOD_FAT* header,
592 BOOL moreSections, BYTE* outBuff);
593}
594
595struct COR_ILMETHOD
596{
597 // a COR_ILMETHOD header should not be decoded by hand. Instead us
598 // COR_ILMETHOD_DECODER to decode it.
599 friend class COR_ILMETHOD_DECODER;
600
601 // compute the size of the header (best format)
602 unsigned static Size(const COR_ILMETHOD_FAT* header, bool MoreSections)
603 {
604 return IlmethodSize((COR_ILMETHOD_FAT*)header,MoreSections);
605 };
606 // emit the header (bestFormat) return amount emitted
607 unsigned static Emit(unsigned size, const COR_ILMETHOD_FAT* header,
608 bool moreSections, BYTE* outBuff)
609 {
610 return IlmethodEmit(size, (COR_ILMETHOD_FAT*)header, moreSections, outBuff);
611 };
612
613//private:
614 union
615 {
616 COR_ILMETHOD_TINY Tiny;
617 COR_ILMETHOD_FAT Fat;
618 };
619 // Code follows the Header, then immedately after the code comes
620 // any sections (COR_ILMETHOD_SECT).
621};
622
623extern "C" {
624/***************************************************************************/
625/* COR_ILMETHOD_DECODER is the only way functions internal to the EE should
626 fetch data from a COR_ILMETHOD. This way any dependancy on the file format
627 (and the multiple ways of encoding the header) is centralized to the
628 COR_ILMETHOD_DECODER constructor) */
629 void __stdcall DecoderInit(void * pThis, COR_ILMETHOD* header);
630 int __stdcall DecoderGetOnDiskSize(void * pThis, COR_ILMETHOD* header);
631} // extern "C"
632
633class COR_ILMETHOD_DECODER : public COR_ILMETHOD_FAT
634{
635public:
636 // This returns an uninitialized decoder, suitable for placement new but nothing
637 // else. Use with caution.
638 COR_ILMETHOD_DECODER() {}
639
640 // Typically the ONLY way you should access COR_ILMETHOD is through
641 // this constructor so format changes are easier.
642 COR_ILMETHOD_DECODER(const COR_ILMETHOD* header)
643 {
644 DecoderInit(this,(COR_ILMETHOD*)header);
645 };
646
647 // The above variant of the constructor can not do a 'complete' job, because
648 // it can not look up the local variable signature meta-data token.
649 // This method should be used when you have access to the Meta data API
650 // If the construction fails, the 'Code' field is set to 0
651
652 enum DecoderStatus {SUCCESS, FORMAT_ERROR, VERIFICATION_ERROR};
653
654 // If we want the decoder to verify the that local signature is OK we
655 // will pass a non-NULL value for wbStatus
656 //
657 // When using LazyInit we want ask that the local signature be verified
658 // But if we fail verification we still need access to the 'Code' field
659 // Because we may be able to demand SkipVerification and thus it was OK
660 // to have had a verification error.
661
662 COR_ILMETHOD_DECODER(COR_ILMETHOD* header,
663 void *pInternalImport,
664 DecoderStatus* wbStatus);
665
666 unsigned EHCount() const
667 {
668 return (EH != 0) ? EH->EHCount() : 0;
669 }
670
671 unsigned GetHeaderSize() const
672 {
673 return GetCodeSize() + ((EH != 0) ? EH->DataSize() : 0);
674 }
675
676 // returns total size of method for use in copying
677 int GetOnDiskSize(const COR_ILMETHOD* header)
678 {
679 return DecoderGetOnDiskSize(this,(COR_ILMETHOD*)header);
680 }
681
682 // Flags these are available because we inherit COR_ILMETHOD_FAT
683 // MaxStack
684 // CodeSize
685 const BYTE * Code;
686 PCCOR_SIGNATURE LocalVarSig; // pointer to signature blob, or 0 if none
687 DWORD cbLocalVarSig; // size of dignature blob, or 0 if none
688 const COR_ILMETHOD_SECT_EH * EH; // eh table if any 0 if none
689 const COR_ILMETHOD_SECT * Sect; // additional sections 0 if none
690}; // class COR_ILMETHOD_DECODER
691
692#if defined(CORHLPR_TURNED_FPO_ON)
693#pragma optimize("", on) // Go back to command line default optimizations
694#undef CORHLPR_TURNED_FPO_ON
695#undef FPO_ON
696#endif
697
698#endif // __CORHLPR_H__
699