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/* Assembler.h */
6/************************************************************************/
7
8#ifndef Assember_h
9#define Assember_h
10
11#define NEW_INLINE_NAMES
12
13#include "binstr.h"
14
15#include "specstrings.h"
16
17#include "asmenum.h"
18#include "asmtemplates.h"
19
20// Disable the "initialization of static local vars is no thread safe" error
21#ifdef _MSC_VER
22#pragma warning(disable : 4640)
23#endif
24
25#ifdef ResetEvent
26#undef ResetEvent
27#endif
28
29#define OUTPUT_BUFFER_SIZE 8192 // initial size of asm code for a single method
30#define OUTPUT_BUFFER_INCREMENT 1024 // size of code buffer increment when it's full
31#define MAX_FILENAME_LENGTH 2048 //256
32#define MAX_SIGNATURE_LENGTH 256 // unused
33#define MAX_LABEL_SIZE 256 //64
34#define MAX_CALL_SIG_SIZE 32 // unused
35#define MAX_SCOPE_LENGTH _MAX_PATH // follow the RegMeta::SetModuleProps limitation
36
37#define MAX_NAMESPACE_LENGTH 1024 //256 //64
38#define MAX_MEMBER_NAME_LENGTH 1024 //256 //64
39
40#define MAX_INTERFACES_IMPLEMENTED 16 // initial number; extended by 16 when needed
41#define GLOBAL_DATA_SIZE 8192 // initial size of global data buffer
42#define GLOBAL_DATA_INCREMENT 1024 // size of global data buffer increment when it's full
43#define MAX_METHODS 1024 // unused
44#define MAX_INPUT_LINE_LEN 1024 // unused
45#define MAX_TYPAR 8
46#define BASE_OBJECT_CLASSNAME "System.Object"
47#define MAX_MANIFEST_RESOURCES 1024
48
49// Fully-qualified class name separators:
50#define NESTING_SEP ((char)0xF8)
51
52#define dwUniBuf 16384
53
54#ifdef FEATURE_PAL
55#include "coreclrloader.h"
56extern CoreCLRLoader *g_loader;
57extern char *g_pszExeFile;
58#endif
59typedef int(STDAPICALLTYPE *MetaDataGetDispenserFunc) (
60 REFCLSID rclsid, // The class to desired.
61 REFIID riid, // Interface wanted on class factory.
62 LPVOID FAR *ppv); // Return interface pointer here.
63
64extern MetaDataGetDispenserFunc metaDataGetDispenser;
65
66extern WCHAR wzUniBuf[]; // Unicode conversion global buffer (assem.cpp)
67
68class Class;
69class Method;
70class PermissionDecl;
71class PermissionSetDecl;
72
73unsigned hash( // defined in assem.cpp
74 __in_ecount(length) const BYTE *k, /* the key */
75 unsigned length, /* the length of the key */
76 unsigned initval); /* the previous hash, or an arbitrary value */
77
78struct MemberRefDescriptor
79{
80 mdToken m_tdClass;
81 Class* m_pClass;
82 char* m_szName;
83 DWORD m_dwName;
84 BinStr* m_pSigBinStr;
85 mdToken m_tkResolved;
86};
87typedef FIFO<MemberRefDescriptor> MemberRefDList;
88
89
90struct MethodImplDescriptor
91{
92 mdToken m_tkImplementedMethod;
93 mdToken m_tkImplementingMethod;
94 mdToken m_tkDefiningClass;
95 BOOL m_fNew;
96};
97typedef FIFO<MethodImplDescriptor> MethodImplDList;
98
99struct LocalMemberRefFixup
100{
101 mdToken tk;
102 size_t offset;
103 BOOL m_fNew;
104 LocalMemberRefFixup(mdToken TK, size_t Offset)
105 {
106 tk = TK;
107 offset = Offset;
108 m_fNew = TRUE;
109 }
110};
111typedef FIFO<LocalMemberRefFixup> LocalMemberRefFixupList;
112
113struct CustomDescr
114{
115 mdToken tkType;
116 mdToken tkOwner;
117 mdToken tkInterfacePair; // Needed for InterfaceImpl CA's
118 BinStr* pBlob;
119 CustomDescr(mdToken tko, mdToken tk, BinStr* pblob) { tkType = tk; pBlob = pblob; tkOwner = tko; tkInterfacePair = 0; };
120 CustomDescr(mdToken tk, BinStr* pblob) { tkType = tk; pBlob = pblob; tkOwner = 0; tkInterfacePair = 0;};
121 CustomDescr(CustomDescr* pOrig) { tkType = pOrig->tkType; pBlob = new BinStr(); pBlob->append(pOrig->pBlob); tkOwner = pOrig->tkOwner; tkInterfacePair = pOrig->tkInterfacePair; };
122 ~CustomDescr() { if(pBlob) delete pBlob; };
123};
124typedef FIFO<CustomDescr> CustomDescrList;
125typedef LIFO<CustomDescrList> CustomDescrListStack;
126/**************************************************************************/
127#include "typar.hpp"
128#include "method.hpp"
129#include "iceefilegen.h"
130#include "asmman.hpp"
131
132#include "nvpair.h"
133
134
135typedef enum
136{
137 STATE_OK,
138 STATE_FAIL,
139 STATE_ENDMETHOD,
140 STATE_ENDFILE
141} state_t;
142
143
144class GlobalLabel
145{
146public:
147 LPCUTF8 m_szName;
148 DWORD m_GlobalOffset;
149 HCEESECTION m_Section;
150 unsigned m_Hash;
151
152 GlobalLabel(LPCUTF8 pszName, DWORD GlobalOffset, HCEESECTION section)
153 {
154 m_GlobalOffset = GlobalOffset;
155 m_Section = section;
156 m_szName = pszName;
157 m_Hash = hash((const BYTE*)pszName, (unsigned)strlen(pszName),10);
158 }
159
160 ~GlobalLabel(){ delete [] m_szName; }
161
162 int ComparedTo(GlobalLabel* L)
163 {
164 return (m_Hash == L->m_Hash) ? strcmp(m_szName, L->m_szName)
165 : ((m_Hash > L->m_Hash) ? 1 : -1);
166 }
167
168 //int ComparedTo(GlobalLabel* L) { return strcmp(m_szName,L->m_szName); };
169 //int Compare(char* L) { return strcmp(L, m_szNam); };
170 //char* NameOf() { return m_szName; };
171};
172//typedef SORTEDARRAY<GlobalLabel> GlobalLabelList;
173typedef RBTREE<GlobalLabel> GlobalLabelList;
174//typedef FIFO_INDEXED<GlobalLabel> GlobalLabelList;
175
176class CeeFileGenWriter;
177class CeeSection;
178
179class BinStr;
180
181/************************************************************************/
182/* represents an object that knows how to report errors back to the user */
183
184class ErrorReporter
185{
186public:
187 virtual void error(const char* fmt, ...) = 0;
188 virtual void warn(const char* fmt, ...) = 0;
189 virtual void msg(const char* fmt, ...) = 0;
190};
191
192/**************************************************************************/
193/* represents a switch table before the lables are bound */
194
195struct Labels {
196 Labels(__in __nullterminated char* aLabel, Labels* aNext, bool aIsLabel) : Label(aLabel), Next(aNext), isLabel(aIsLabel) {}
197 ~Labels() { if(isLabel && Label) delete [] Label; delete Next; }
198
199 char* Label;
200 Labels* Next;
201 bool isLabel;
202};
203
204/**************************************************************************/
205/* descriptor of the structured exception handling construct */
206struct SEH_Descriptor
207{
208 DWORD sehClause; // catch/filter/finally
209 DWORD tryFrom; // start of try block
210 DWORD tryTo; // end of try block
211 DWORD sehHandler; // start of exception handler
212 DWORD sehHandlerTo; // end of exception handler
213 union {
214 DWORD sehFilter; // start of filter block
215 mdTypeRef cException; // what to catch
216 };
217
218 SEH_Descriptor()
219 {
220 memset(this, 0, sizeof(*this));
221 }
222};
223
224
225typedef LIFO<char> StringStack;
226typedef LIFO<SEH_Descriptor> SEHD_Stack;
227
228typedef FIFO<Method> MethodList;
229//typedef SORTEDARRAY<Method> MethodSortedList;
230typedef FIFO<mdToken> TokenList;
231/**************************************************************************/
232/* The field, event and property descriptor structures */
233
234struct FieldDescriptor
235{
236 mdTypeDef m_tdClass;
237 char* m_szName;
238 DWORD m_dwName;
239 mdFieldDef m_fdFieldTok;
240 ULONG m_ulOffset;
241 char* m_rvaLabel; // if field has RVA associated with it, label for it goes here.
242 BinStr* m_pbsSig;
243 Class* m_pClass;
244 BinStr* m_pbsValue;
245 BinStr* m_pbsMarshal;
246 PInvokeDescriptor* m_pPInvoke;
247 CustomDescrList m_CustomDescrList;
248 DWORD m_dwAttr;
249 BOOL m_fNew;
250 // Security attributes
251 PermissionDecl* m_pPermissions;
252 PermissionSetDecl* m_pPermissionSets;
253 FieldDescriptor() { m_szName = NULL; m_pbsSig = NULL; m_fNew = TRUE; };
254 ~FieldDescriptor() { if(m_szName) delete [] m_szName; if(m_pbsSig) delete m_pbsSig; };
255};
256typedef FIFO<FieldDescriptor> FieldDList;
257
258struct EventDescriptor
259{
260 mdTypeDef m_tdClass;
261 char* m_szName;
262 DWORD m_dwAttr;
263 mdToken m_tkEventType;
264 mdToken m_tkAddOn;
265 mdToken m_tkRemoveOn;
266 mdToken m_tkFire;
267 TokenList m_tklOthers;
268 mdEvent m_edEventTok;
269 BOOL m_fNew;
270 CustomDescrList m_CustomDescrList;
271 ~EventDescriptor() { m_tklOthers.RESET(false); };
272};
273typedef FIFO<EventDescriptor> EventDList;
274
275struct PropDescriptor
276{
277 mdTypeDef m_tdClass;
278 char* m_szName;
279 DWORD m_dwAttr;
280 COR_SIGNATURE* m_pSig;
281 DWORD m_dwCSig;
282 DWORD m_dwCPlusTypeFlag;
283 PVOID m_pValue;
284 DWORD m_cbValue;
285 mdToken m_tkSet;
286 mdToken m_tkGet;
287 TokenList m_tklOthers;
288 mdProperty m_pdPropTok;
289 BOOL m_fNew;
290 CustomDescrList m_CustomDescrList;
291 ~PropDescriptor() { m_tklOthers.RESET(false); };
292};
293typedef FIFO<PropDescriptor> PropDList;
294
295struct ImportDescriptor
296{
297 char* szDllName;
298// char szDllName[MAX_FILENAME_LENGTH];
299 DWORD dwDllName;
300 mdModuleRef mrDll;
301 ImportDescriptor(__in __nullterminated char* sz, DWORD l)
302 {
303 if((sz != NULL)&&(l > 0))
304 {
305 szDllName = new char[l+1];
306 if(szDllName != NULL)
307 {
308 memcpy(szDllName,sz,l);
309 szDllName[l] = 0;
310 dwDllName = l;
311 }
312 }
313 else
314 {
315 szDllName = NULL;
316 dwDllName = 0;
317 }
318 };
319 ~ImportDescriptor() { delete [] szDllName; };
320};
321typedef FIFO<ImportDescriptor> ImportList;
322
323
324/**************************************************************************/
325#include "class.hpp"
326typedef LIFO<Class> ClassStack;
327typedef FIFO<Class> ClassList;
328//typedef SORTEDARRAY<Class> ClassHash;
329typedef RBTREE<Class> ClassHash;
330//typedef FIFO_INDEXED<Class> ClassHash;
331
332/**************************************************************************/
333/* Classes to hold lists of security permissions and permission sets. We build
334 these lists as we find security directives in the input stream and drain
335 them every time we see a class or method declaration (to which the
336 security info is attached). */
337
338class PermissionDecl
339{
340public:
341 PermissionDecl(CorDeclSecurity action, mdToken type, NVPair *pairs)
342 {
343 m_Action = action;
344 m_TypeSpec = type;
345 m_pbsBlob = NULL;
346 BuildConstructorBlob(action, pairs);
347 m_Next = NULL;
348 }
349
350 PermissionDecl(CorDeclSecurity action, mdToken type, BinStr* pbsPairs)
351 {
352 m_Action = action;
353 m_TypeSpec = type;
354
355 m_pbsBlob = new BinStr();
356 m_pbsBlob->appendInt16(VAL16(1)); // prolog 0x01 0x00
357 m_pbsBlob->appendInt32((int)action); // 4-byte action
358 if(pbsPairs) // name-value pairs if any
359 {
360 if(pbsPairs->length() > 2)
361 m_pbsBlob->appendFrom(pbsPairs,2);
362 delete pbsPairs;
363 }
364 if(m_pbsBlob->length() == 6) // no pairs added
365 m_pbsBlob->appendInt16(0);
366 m_Blob = m_pbsBlob->ptr();
367 m_BlobLength = m_pbsBlob->length();
368 m_Next = NULL;
369 }
370
371 ~PermissionDecl()
372 {
373 if(m_pbsBlob) delete m_pbsBlob;
374 else delete [] m_Blob;
375 }
376
377 CorDeclSecurity m_Action;
378 mdToken m_TypeSpec;
379 BYTE *m_Blob;
380 BinStr *m_pbsBlob;
381 long m_BlobLength;
382 PermissionDecl *m_Next;
383
384private:
385 void BuildConstructorBlob(CorDeclSecurity action, NVPair *pairs)
386 {
387 NVPair *p = pairs;
388 int count = 0;
389 int bytes = 8;
390 int length;
391 int i;
392 BYTE *pBlob;
393
394 // Calculate number of name/value pairs and the memory required for the
395 // custom attribute blob.
396 while (p) {
397 BYTE *pVal = (BYTE*)p->Value()->ptr();
398 count++;
399 bytes += 2; // One byte field/property specifier, one byte type code
400
401 length = (int)strlen((const char *)p->Name()->ptr());
402 bytes += CPackedLen::Size(length) + length;
403
404 switch (pVal[0]) {
405 case SERIALIZATION_TYPE_BOOLEAN:
406 bytes += 1;
407 break;
408 case SERIALIZATION_TYPE_I4:
409 bytes += 4;
410 break;
411 case SERIALIZATION_TYPE_STRING:
412 length = (int)strlen((const char *)&pVal[1]);
413 bytes += CPackedLen::Size(length) + length;
414 break;
415 case SERIALIZATION_TYPE_ENUM:
416 length = (int)strlen((const char *)&pVal[1]);
417 bytes += CPackedLen::Size((ULONG)length) + length;
418 bytes += 4;
419 break;
420 }
421 p = p->Next();
422 }
423
424 m_Blob = new BYTE[bytes];
425 if(m_Blob==NULL)
426 {
427 fprintf(stderr,"\nOut of memory!\n");
428 return;
429 }
430
431 m_Blob[0] = 0x01; // Version
432 m_Blob[1] = 0x00;
433 m_Blob[2] = (BYTE)action; // Constructor arg (security action code)
434 m_Blob[3] = 0x00;
435 m_Blob[4] = 0x00;
436 m_Blob[5] = 0x00;
437 m_Blob[6] = (BYTE)count; // Property/field count
438 m_Blob[7] = (BYTE)(count >> 8);
439
440 for (i = 0, pBlob = &m_Blob[8], p = pairs; i < count; i++, p = p->Next()) {
441 BYTE *pVal = (BYTE*)p->Value()->ptr();
442 char *szType;
443
444 // Set field/property setter type.
445 *pBlob++ = SERIALIZATION_TYPE_PROPERTY;
446
447 // Set type code. There's additional info for enums (the enum class
448 // name).
449 *pBlob++ = pVal[0];
450 if (pVal[0] == SERIALIZATION_TYPE_ENUM) {
451 szType = (char *)&pVal[1];
452 length = (int)strlen(szType);
453 pBlob = (BYTE*)CPackedLen::PutLength(pBlob, length);
454 strcpy_s((char *)pBlob, bytes, szType);
455 pBlob += length;
456 }
457
458 // Record the field/property name.
459 length = (int)strlen((const char *)p->Name()->ptr());
460 pBlob = (BYTE*)CPackedLen::PutLength(pBlob, length);
461 strcpy_s((char *)pBlob, bytes-(pBlob-m_Blob), (const char *)p->Name()->ptr());
462 pBlob += length;
463
464 // Record the serialized value.
465 switch (pVal[0]) {
466 case SERIALIZATION_TYPE_BOOLEAN:
467 *pBlob++ = pVal[1];
468 break;
469 case SERIALIZATION_TYPE_I4:
470 *(__int32*)pBlob = *(__int32*)&pVal[1];
471 pBlob += 4;
472 break;
473 case SERIALIZATION_TYPE_STRING:
474 length = (int)strlen((const char *)&pVal[1]);
475 pBlob = (BYTE*)CPackedLen::PutLength(pBlob, length);
476 strcpy_s((char *)pBlob, bytes-(pBlob-m_Blob), (const char *)&pVal[1]);
477 pBlob += length;
478 break;
479 case SERIALIZATION_TYPE_ENUM:
480 length = (int)strlen((const char *)&pVal[1]);
481 // We can have enums with base type of I1, I2 and I4.
482 switch (pVal[1 + length + 1]) {
483 case 1:
484 *(__int8*)pBlob = *(__int8*)&pVal[1 + length + 2];
485 pBlob += 1;
486 break;
487 case 2:
488 *(__int16*)pBlob = *(__int16*)&pVal[1 + length + 2];
489 pBlob += 2;
490 break;
491 case 4:
492 *(__int32*)pBlob = *(__int32*)&pVal[1 + length + 2];
493 pBlob += 4;
494 break;
495 default:
496 _ASSERTE(!"Invalid enum size");
497 }
498 break;
499 }
500
501 }
502
503 _ASSERTE((pBlob - m_Blob) == bytes);
504
505 m_BlobLength = (long)bytes;
506 }
507};
508
509class PermissionSetDecl
510{
511public:
512 PermissionSetDecl(CorDeclSecurity action, BinStr *value)
513 {
514 m_Action = action;
515 m_Value = value;
516 m_Next = NULL;
517 }
518
519 ~PermissionSetDecl()
520 {
521 delete m_Value;
522 }
523
524 CorDeclSecurity m_Action;
525 BinStr *m_Value;
526 PermissionSetDecl *m_Next;
527};
528
529struct VTFEntry
530{
531 char* m_szLabel;
532 WORD m_wCount;
533 WORD m_wType;
534 VTFEntry(WORD wCount, WORD wType, __in __nullterminated char* szLabel) { m_wCount = wCount; m_wType = wType; m_szLabel = szLabel; }
535 ~VTFEntry() { delete m_szLabel; }
536};
537typedef FIFO<VTFEntry> VTFList;
538
539struct EATEntry
540{
541 DWORD dwStubRVA;
542 DWORD dwOrdinal;
543 char* szAlias;
544};
545typedef FIFO<EATEntry> EATList;
546
547struct DocWriter
548{
549 char* Name;
550 ISymUnmanagedDocumentWriter* pWriter;
551 DocWriter() { Name=NULL; pWriter=NULL; };
552 ~DocWriter() { delete [] Name; if(pWriter) pWriter->Release();};
553};
554typedef FIFO<DocWriter> DocWriterList;
555/**************************************************************************/
556/* The assembler object does all the code generation (dealing with meta-data)
557 writing a PE file etc etc. But does NOT deal with syntax (that is what
558 AsmParse is for). Thus the API below is how AsmParse 'controls' the
559 Assember. Note that the Assembler object does know about the
560 AsmParse object (that is Assember is more fundamental than AsmParse) */
561struct Instr
562{
563 int opcode;
564 unsigned linenum;
565 unsigned column;
566 unsigned linenum_end;
567 unsigned column_end;
568 unsigned pc;
569 ISymUnmanagedDocumentWriter* pWriter;
570};
571#define INSTR_POOL_SIZE 16
572
573// For code folding:
574struct MethodBody
575{
576 BinStr* pbsBody;
577 unsigned RVA;
578 BYTE* pCode;
579};
580typedef FIFO<MethodBody> MethodBodyList;
581
582struct Clockwork
583{
584 DWORD cBegin;
585 DWORD cEnd;
586 DWORD cParsBegin;
587 DWORD cParsEnd;
588 DWORD cMDInitBegin;
589 DWORD cMDInitEnd;
590 DWORD cMDEmitBegin;
591 DWORD cMDEmitEnd;
592 DWORD cMDEmit1;
593 DWORD cMDEmit2;
594 DWORD cMDEmit3;
595 DWORD cMDEmit4;
596 DWORD cRef2DefBegin;
597 DWORD cRef2DefEnd;
598 DWORD cFilegenBegin;
599 DWORD cFilegenEnd;
600};
601
602struct TypeDefDescr
603{
604 char* m_szName;
605 union
606 {
607 BinStr* m_pbsTypeSpec;
608 CustomDescr* m_pCA;
609 };
610 mdToken m_tkTypeSpec;
611 TypeDefDescr(__in_opt __nullterminated char *pszName, BinStr* pbsTypeSpec, mdToken tkTypeSpec)
612 {
613 m_szName = pszName;
614 m_pbsTypeSpec = pbsTypeSpec;
615 m_tkTypeSpec = tkTypeSpec;
616 };
617 ~TypeDefDescr() { delete [] m_szName; delete m_pbsTypeSpec; };
618 int ComparedTo(TypeDefDescr* T) { return strcmp(m_szName,T->m_szName); };
619 //int Compare(char* T) { return strcmp(T,m_szName); };
620};
621typedef SORTEDARRAY<TypeDefDescr> TypeDefDList;
622
623struct Indx
624{
625 void* table[128];
626 Indx() { memset(table,0,sizeof(table)); };
627 ~Indx()
628 {
629 for(int i = 1; i < 128; i++) delete ((Indx*)(table[i]));
630 };
631 void IndexString(__in_z __in char* psz, void* pkywd)
632 {
633 int i = (int) *psz;
634 if(i == 0)
635 table[0] = pkywd;
636 else
637 {
638 _ASSERTE((i > 0)&&(i <= 127));
639 Indx* pInd = (Indx*)(table[i]);
640 if(pInd == NULL)
641 {
642 pInd = new Indx;
643 _ASSERTE(pInd);
644 table[i] = pInd;
645 }
646 pInd->IndexString(psz+1,pkywd);
647 }
648 }
649 void* FindString(__in __nullterminated char* psz)
650 {
651 if(*psz > 0)
652 {
653 unsigned char uch = (unsigned char) *psz;
654 if(table[uch] != NULL)
655 return ((Indx*)(table[uch]))->FindString(psz+1);
656 }
657 else if(*psz == 0) return table[0];
658 return NULL;
659 }
660};
661
662class Assembler {
663public:
664 Assembler();
665 ~Assembler();
666 //--------------------------------------------------------
667 GlobalLabelList m_lstGlobalLabel;
668 GlobalFixupList m_lstGlobalFixup;
669
670 LabelList m_lstLabel;
671
672 Class * m_pModuleClass;
673 ClassList m_lstClass;
674 ClassHash m_hshClass;
675
676 Indx indxKeywords;
677
678 BYTE * m_pOutputBuffer;
679 BYTE * m_pCurOutputPos;
680 BYTE * m_pEndOutputPos;
681
682
683 DWORD m_CurPC;
684 BOOL m_fStdMapping;
685 BOOL m_fDisplayTraceOutput;
686 BOOL m_fInitialisedMetaData;
687 BOOL m_fAutoInheritFromObject;
688 BOOL m_fReportProgress;
689 BOOL m_fIsMscorlib;
690 BOOL m_fTolerateDupMethods;
691 BOOL m_fENCMode;
692 BOOL m_fOptimize;
693 mdToken m_tkSysObject;
694 mdToken m_tkSysString;
695 mdToken m_tkSysValue;
696 mdToken m_tkSysEnum;
697 BOOL m_fDidCoInitialise;
698
699 IMetaDataDispenserEx *m_pDisp;
700 IMetaDataEmit2 *m_pEmitter;
701 ICeeFileGen *m_pCeeFileGen;
702 IMetaDataImport2 *m_pImporter; // Import interface.
703 HCEEFILE m_pCeeFile;
704 HCEESECTION m_pGlobalDataSection;
705 HCEESECTION m_pILSection;
706 HCEESECTION m_pTLSSection;
707 HCEESECTION m_pCurSection; // The section EmitData* things go to
708
709 AsmMan* m_pManifest;
710
711 char m_szScopeName[MAX_SCOPE_LENGTH];
712 char *m_szNamespace; //[MAX_NAMESPACE_LENGTH];
713 char *m_szFullNS; //[MAX_NAMESPACE_LENGTH];
714 unsigned m_ulFullNSLen;
715
716 WCHAR *m_wzMetadataVersion;
717
718 StringStack m_NSstack;
719 mdTypeSpec m_crExtends;
720
721 // char m_szExtendsClause[MAX_CLASSNAME_LENGTH];
722
723 // The (resizable) array of "implements" types
724 mdToken *m_crImplList;
725 int m_nImplList;
726 int m_nImplListSize;
727
728 TyParList *m_TyParList;
729
730 Method *m_pCurMethod;
731 Class *m_pCurClass;
732 ClassStack m_ClassStack; // for nested classes
733 Class *dummyClass; // for FindCreateClass
734
735 // moved to Class
736 //MethodList m_MethodList;
737
738 BOOL m_fCPlusPlus;
739 BOOL m_fWindowsCE;
740 BOOL m_fDLL;
741 BOOL m_fOBJ;
742 BOOL m_fEntryPointPresent;
743 BOOL m_fHaveFieldsWithRvas;
744 BOOL m_fFoldCode;
745 DWORD m_dwMethodsFolded;
746
747 state_t m_State;
748
749 BinStr* m_pbsMD;
750
751 Instr m_Instr[INSTR_POOL_SIZE]; // 16
752 inline Instr* GetInstr()
753 {
754 int i;
755 for(i=0; (i<INSTR_POOL_SIZE)&&(m_Instr[i].opcode != -1); i++);
756 if(i<INSTR_POOL_SIZE) return &m_Instr[i];
757 report->error("Instruction pool exhausted: source contains invalid instructions\n");
758 return NULL;
759 }
760 // Labels, fixups and IL fixups are defined in Method.hpp,.cpp
761 void AddLabel(DWORD CurPC, __in __nullterminated char *pszName);
762 void AddDeferredFixup(__in __nullterminated char *pszLabel, BYTE *pBytes, DWORD RelativeToPC, BYTE FixupSize);
763 void AddDeferredILFixup(ILFixupType Kind);
764 void AddDeferredILFixup(ILFixupType Kind, GlobalFixup *GFixup);
765 void DoDeferredILFixups(Method* pMethod);
766 BOOL DoFixups(Method* pMethod);
767 //--------------------------------------------------------------------------------
768 void ClearImplList(void);
769 void AddToImplList(mdToken);
770 void ClearBoundList(void);
771 //--------------------------------------------------------------------------------
772 BOOL Init();
773 void ProcessLabel(__in_z __in char *pszName);
774 GlobalLabel *FindGlobalLabel(LPCUTF8 pszName);
775 GlobalFixup *AddDeferredGlobalFixup(__in __nullterminated char *pszLabel, BYTE* reference);
776 //void AddDeferredDescrFixup(__in __nullterminated char *pszLabel);
777 BOOL DoGlobalFixups();
778 BOOL DoDescrFixups();
779 OPCODE DecodeOpcode(const BYTE *pCode, DWORD *pdwLen);
780 BOOL AddMethod(Method *pMethod);
781 void SetTLSSection() { m_pCurSection = m_pTLSSection; }
782 void SetILSection() { m_pCurSection = m_pILSection; }
783 void SetDataSection() { m_pCurSection = m_pGlobalDataSection; }
784 BOOL EmitMethod(Method *pMethod);
785 BOOL EmitMethodBody(Method* pMethod, BinStr* pbsOut);
786 BOOL EmitClass(Class *pClass);
787 HRESULT CreatePEFile(__in __nullterminated WCHAR *pwzOutputFilename);
788 HRESULT CreateTLSDirectory();
789 HRESULT CreateDebugDirectory();
790 HRESULT InitMetaData();
791 Class *FindCreateClass(__in __nullterminated const char *pszFQN);
792 BOOL EmitFieldRef(__in_z __in char *pszArg, int opcode);
793 BOOL EmitSwitchData(__in_z __in char *pszArg);
794 mdToken ResolveClassRef(mdToken tkResScope, __in __nullterminated const char *pszClassName, Class** ppClass);
795 mdToken ResolveTypeSpec(BinStr* typeSpec);
796 mdToken GetBaseAsmRef();
797 mdToken GetAsmRef(__in __nullterminated const char* szName);
798 mdToken GetModRef(__in __nullterminated char* szName);
799 mdToken GetInterfaceImpl(mdToken tsClass, mdToken tsInterface);
800 char* ReflectionNotation(mdToken tk);
801 HRESULT ConvLocalSig(__in char* localsSig, CQuickBytes* corSig, DWORD* corSigLen, BYTE*& localTypes);
802 DWORD GetCurrentILSectionOffset();
803 BOOL EmitCALLISig(__in char *p);
804 void AddException(DWORD pcStart, DWORD pcEnd, DWORD pcHandler, DWORD pcHandlerTo, mdTypeRef crException, BOOL isFilter, BOOL isFault, BOOL isFinally);
805 state_t CheckLocalTypeConsistancy(int instr, unsigned arg);
806 state_t AddGlobalLabel(__in __nullterminated char *pszName, HCEESECTION section);
807 void SetDLL(BOOL);
808 void SetOBJ(BOOL);
809 void ResetForNextMethod();
810 void ResetLineNumbers();
811 void SetStdMapping(BOOL val = TRUE) { m_fStdMapping = val; };
812
813 //--------------------------------------------------------------------------------
814 BOOL isShort(unsigned instr) { return ((OpcodeInfo[instr].Type & 16) != 0); };
815 unsigned ShortOf(unsigned opcode);
816 void SetErrorReporter(ErrorReporter* aReport) { report = aReport; if(m_pManifest) m_pManifest->SetErrorReporter(aReport); }
817
818 void StartNameSpace(__in __nullterminated char* name);
819 void EndNameSpace();
820 void StartClass(__in __nullterminated char* name, DWORD attr, TyParList *typars);
821 DWORD CheckClassFlagsIfNested(Class* pEncloser, DWORD attr);
822 void AddClass();
823 void EndClass();
824 void StartMethod(__in __nullterminated char* name, BinStr* sig, CorMethodAttr flags, BinStr* retMarshal, DWORD retAttr, TyParList *typars = NULL);
825 void EndMethod();
826
827 void AddField(__inout_z __inout char* name, BinStr* sig, CorFieldAttr flags, __in __nullterminated char* rvaLabel, BinStr* pVal, ULONG ulOffset);
828 BOOL EmitField(FieldDescriptor* pFD);
829 void EmitByte(int val);
830 //void EmitTry(enum CorExceptionFlag kind, char* beginLabel, char* endLabel, char* handleLabel, char* filterOrClass);
831 void EmitMaxStack(unsigned val);
832 void EmitLocals(BinStr* sig);
833 void EmitEntryPoint();
834 void EmitZeroInit();
835 void SetImplAttr(unsigned short attrval);
836
837 // Emits zeros if the buffer parameter is NULL.
838 void EmitData(__in_opt void *buffer, unsigned len);
839
840 void EmitDD(__in __nullterminated char *str);
841 void EmitDataString(BinStr* str);
842
843 void EmitInstrVar(Instr* instr, int var);
844 void EmitInstrVarByName(Instr* instr, __in __nullterminated char* label);
845 void EmitInstrI(Instr* instr, int val);
846 void EmitInstrI8(Instr* instr, __int64* val);
847 void EmitInstrR(Instr* instr, double* val);
848 void EmitInstrBrOffset(Instr* instr, int offset);
849 void EmitInstrBrTarget(Instr* instr, __in __nullterminated char* label);
850 mdToken MakeMemberRef(mdToken typeSpec, __in __nullterminated char* name, BinStr* sig);
851 mdToken MakeMethodSpec(mdToken tkParent, BinStr* sig);
852 void SetMemberRefFixup(mdToken tk, unsigned opcode_len);
853 mdToken MakeTypeRef(mdToken tkResScope, LPCUTF8 szFullName);
854 void EmitInstrStringLiteral(Instr* instr, BinStr* literal, BOOL ConvertToUnicode, BOOL Swap = FALSE);
855 void EmitInstrSig(Instr* instr, BinStr* sig);
856 void EmitInstrSwitch(Instr* instr, Labels* targets);
857 void EmitLabel(__in __nullterminated char* label);
858 void EmitDataLabel(__in __nullterminated char* label);
859
860 unsigned OpcodeLen(Instr* instr); //returns opcode length
861 // Emit just the opcode (no parameters to the instruction stream.
862 void EmitOpcode(Instr* instr);
863
864 // Emit primitive types to the instruction stream.
865 void EmitBytes(BYTE*, unsigned len);
866
867 ErrorReporter* report;
868
869 BOOL EmitFieldsMethods(Class* pClass);
870 BOOL EmitEventsProps(Class* pClass);
871
872 // named args/vars paraphernalia:
873public:
874 void addArgName(__in_opt __nullterminated char *szNewName, BinStr* pbSig, BinStr* pbMarsh, DWORD dwAttr)
875 {
876 if(pbSig && (*(pbSig->ptr()) == ELEMENT_TYPE_VOID))
877 report->error("Illegal use of type 'void'\n");
878 if(m_lastArgName)
879 {
880 m_lastArgName->pNext = new ARG_NAME_LIST(m_lastArgName->nNum+1,szNewName,pbSig,pbMarsh,dwAttr);
881 m_lastArgName = m_lastArgName->pNext;
882 }
883 else
884 {
885 m_lastArgName = new ARG_NAME_LIST(0,szNewName,pbSig,pbMarsh,dwAttr);
886 m_firstArgName = m_lastArgName;
887 }
888 };
889 ARG_NAME_LIST *getArgNameList(void)
890 { ARG_NAME_LIST *pRet = m_firstArgName; m_firstArgName=NULL; m_lastArgName=NULL; return pRet;};
891 // Added because recursive destructor of ARG_NAME_LIST may overflow the system stack
892 void delArgNameList(ARG_NAME_LIST *pFirst)
893 {
894 ARG_NAME_LIST *pArgList=pFirst, *pArgListNext;
895 for(; pArgList; pArgListNext=pArgList->pNext,
896 delete pArgList,
897 pArgList=pArgListNext);
898 };
899
900 ARG_NAME_LIST *findArg(ARG_NAME_LIST *pFirst, int num)
901 {
902 ARG_NAME_LIST *pAN;
903 for(pAN=pFirst; pAN; pAN = pAN->pNext)
904 {
905 if(pAN->nNum == num) return pAN;
906 }
907 return NULL;
908 };
909 ARG_NAME_LIST *m_firstArgName;
910 ARG_NAME_LIST *m_lastArgName;
911 void ResetArgNameList();
912
913 // Structured exception handling paraphernalia:
914public:
915 SEH_Descriptor *m_SEHD; // current descriptor ptr
916 void NewSEHDescriptor(void); //sets m_SEHD
917 void SetTryLabels(__in __nullterminated char * szFrom, __in __nullterminated char *szTo);
918 void SetFilterLabel(__in __nullterminated char *szFilter);
919 void SetCatchClass(mdToken catchClass);
920 void SetHandlerLabels(__in __nullterminated char *szHandlerFrom, __in __nullterminated char *szHandlerTo);
921 void EmitTry(void); //uses m_SEHD
922
923//private:
924 SEHD_Stack m_SEHDstack;
925
926 // Events and Properties paraphernalia:
927public:
928 void EndEvent(void); //emits event definition
929 void EndProp(void); //emits property definition
930 void ResetEvent(__inout_z __inout char * szName, mdToken typeSpec, DWORD dwAttr);
931 void ResetProp(__inout_z __inout char * szName, BinStr* bsType, DWORD dwAttr, BinStr* bsValue);
932 void SetEventMethod(int MethodCode, mdToken tk);
933 void SetPropMethod(int MethodCode, mdToken tk);
934 BOOL EmitEvent(EventDescriptor* pED); // impl. in ASSEM.CPP
935 BOOL EmitProp(PropDescriptor* pPD); // impl. in ASSEM.CPP
936 EventDescriptor* m_pCurEvent;
937 PropDescriptor* m_pCurProp;
938
939private:
940 MemberRefDList m_LocalMethodRefDList;
941 MemberRefDList m_LocalFieldRefDList;
942 LocalMemberRefFixupList m_LocalMemberRefFixupList;
943 MethodBodyList m_MethodBodyList;
944 MemberRefDList m_MethodSpecList;
945public:
946 HRESULT ResolveLocalMemberRefs();
947 HRESULT DoLocalMemberRefFixups();
948 mdToken ResolveLocalMemberRef(mdToken tok);
949
950 // PInvoke paraphernalia
951public:
952 PInvokeDescriptor* m_pPInvoke;
953 ImportList m_ImportList;
954 void SetPinvoke(BinStr* DllName, int Ordinal, BinStr* Alias, int Attrs);
955 HRESULT EmitPinvokeMap(mdToken tk, PInvokeDescriptor* pDescr);
956 ImportDescriptor* EmitImport(BinStr* DllName);
957 void EmitImports();
958
959 // Debug metadata paraphernalia
960public:
961 ISymUnmanagedWriter* m_pSymWriter;
962 ISymUnmanagedDocumentWriter* m_pSymDocument;
963 DocWriterList m_DocWriterList;
964 ULONG m_ulCurLine; // set by Parser
965 ULONG m_ulCurColumn; // set by Parser
966 ULONG m_ulLastDebugLine;
967 ULONG m_ulLastDebugColumn;
968 ULONG m_ulLastDebugLineEnd;
969 ULONG m_ulLastDebugColumnEnd;
970 DWORD m_dwIncludeDebugInfo;
971 BOOL m_fGeneratePDB;
972 char m_szSourceFileName[MAX_FILENAME_LENGTH*3+1];
973 WCHAR m_wzOutputFileName[MAX_FILENAME_LENGTH];
974 WCHAR m_wzSourceFileName[MAX_FILENAME_LENGTH];
975 GUID m_guidLang;
976 GUID m_guidLangVendor;
977 GUID m_guidDoc;
978
979 // Security paraphernalia
980public:
981 void AddPermissionDecl(CorDeclSecurity action, mdToken type, NVPair *pairs)
982 {
983 PermissionDecl *decl = new PermissionDecl(action, type, pairs);
984 if(decl==NULL)
985 {
986 report->error("\nOut of memory!\n");
987 return;
988 }
989 if (m_pCurMethod) {
990 decl->m_Next = m_pCurMethod->m_pPermissions;
991 m_pCurMethod->m_pPermissions = decl;
992 } else if (m_pCurClass) {
993 decl->m_Next = m_pCurClass->m_pPermissions;
994 m_pCurClass->m_pPermissions = decl;
995 } else if (m_pManifest && m_pManifest->m_pAssembly) {
996 decl->m_Next = m_pManifest->m_pAssembly->m_pPermissions;
997 m_pManifest->m_pAssembly->m_pPermissions = decl;
998 } else {
999 report->error("Cannot declare security permissions without the owner\n");
1000 delete decl;
1001 }
1002 };
1003
1004 void AddPermissionDecl(CorDeclSecurity action, mdToken type, BinStr *pbsPairs)
1005 {
1006 PermissionDecl *decl = new PermissionDecl(action, type, pbsPairs);
1007 if(decl==NULL)
1008 {
1009 report->error("\nOut of memory!\n");
1010 return;
1011 }
1012 if (m_pCurMethod) {
1013 decl->m_Next = m_pCurMethod->m_pPermissions;
1014 m_pCurMethod->m_pPermissions = decl;
1015 } else if (m_pCurClass) {
1016 decl->m_Next = m_pCurClass->m_pPermissions;
1017 m_pCurClass->m_pPermissions = decl;
1018 } else if (m_pManifest && m_pManifest->m_pAssembly) {
1019 decl->m_Next = m_pManifest->m_pAssembly->m_pPermissions;
1020 m_pManifest->m_pAssembly->m_pPermissions = decl;
1021 } else {
1022 report->error("Cannot declare security permissions without the owner\n");
1023 delete decl;
1024 }
1025 };
1026
1027 void AddPermissionSetDecl(CorDeclSecurity action, BinStr *value)
1028 {
1029 PermissionSetDecl *decl = new PermissionSetDecl(action, value);
1030 if(decl==NULL)
1031 {
1032 report->error("\nOut of memory!\n");
1033 return;
1034 }
1035 if (m_pCurMethod) {
1036 decl->m_Next = m_pCurMethod->m_pPermissionSets;
1037 m_pCurMethod->m_pPermissionSets = decl;
1038 } else if (m_pCurClass) {
1039 decl->m_Next = m_pCurClass->m_pPermissionSets;
1040 m_pCurClass->m_pPermissionSets = decl;
1041 } else if (m_pManifest && m_pManifest->m_pAssembly) {
1042 decl->m_Next = m_pManifest->m_pAssembly->m_pPermissionSets;
1043 m_pManifest->m_pAssembly->m_pPermissionSets = decl;
1044 } else {
1045 report->error("Cannot declare security permission sets without the owner\n");
1046 delete decl;
1047 }
1048 };
1049 void EmitSecurityInfo(mdToken token,
1050 PermissionDecl* pPermissions,
1051 PermissionSetDecl*pPermissionSets);
1052 BinStr* EncodeSecAttr(__in __nullterminated char* szReflName, BinStr* pbsSecAttrBlob, unsigned nProps);
1053
1054 HRESULT AllocateStrongNameSignature();
1055
1056 // Custom values paraphernalia:
1057public:
1058 mdToken m_tkCurrentCVOwner;
1059 CustomDescrList* m_pCustomDescrList;
1060 CustomDescrListStack m_CustomDescrListStack;
1061 CustomDescrList m_CustomDescrList;
1062
1063 void DefineCV(CustomDescr* pCD)
1064 {
1065 if(pCD)
1066 {
1067 ULONG cTemp = 0;
1068 void * pBlobBody = NULL;
1069 mdToken cv;
1070 mdToken tkOwnerType, tkTypeType = TypeFromToken(pCD->tkType);
1071
1072 if((tkTypeType != 0x99000000)&&(tkTypeType != 0x98000000))
1073 {
1074 tkOwnerType = TypeFromToken(pCD->tkOwner);
1075 if((tkOwnerType != 0x99000000)&&(tkOwnerType != 0x98000000))
1076 {
1077 if(pCD->pBlob)
1078 {
1079 pBlobBody = (void *)(pCD->pBlob->ptr());
1080 cTemp = pCD->pBlob->length();
1081 }
1082 if (pCD->tkInterfacePair)
1083 {
1084 pCD->tkOwner = GetInterfaceImpl(pCD->tkOwner, pCD->tkInterfacePair);
1085 }
1086 m_pEmitter->DefineCustomAttribute(pCD->tkOwner,pCD->tkType,pBlobBody,cTemp,&cv);
1087
1088 delete pCD;
1089 return;
1090 }
1091 }
1092 m_CustomDescrList.PUSH(pCD);
1093 }
1094 };
1095 void EmitCustomAttributes(mdToken tok, CustomDescrList* pCDL)
1096 {
1097 CustomDescr *pCD;
1098 if(pCDL == NULL || RidFromToken(tok)==0) return;
1099 while((pCD = pCDL->POP()))
1100 {
1101 pCD->tkOwner = tok;
1102 DefineCV(pCD);
1103 }
1104 };
1105
1106 void EmitUnresolvedCustomAttributes(); // implementation: writer.cpp
1107 // VTable blob (if any)
1108public:
1109 BinStr *m_pVTable;
1110 // Field marshaling
1111 BinStr *m_pMarshal;
1112 // VTable fixup list
1113 VTFList m_VTFList;
1114 // Export Address Table entries list
1115 EATList m_EATList;
1116 HRESULT CreateExportDirectory();
1117 DWORD EmitExportStub(DWORD dwVTFSlotRVA);
1118
1119 // Method implementation paraphernalia:
1120private:
1121 MethodImplDList m_MethodImplDList;
1122public:
1123 void AddMethodImpl(mdToken tkImplementedTypeSpec, __in __nullterminated char* szImplementedName, BinStr* pImplementedSig,
1124 mdToken tkImplementingTypeSpec, __in_opt __nullterminated char* szImplementingName, BinStr* pImplementingSig);
1125 BOOL EmitMethodImpls();
1126 // lexical scope handling paraphernalia:
1127 void EmitScope(Scope* pSCroot); // struct Scope - see Method.hpp
1128 // source file name paraphernalia
1129 BOOL m_fSourceFileSet;
1130 void SetSourceFileName(__in __nullterminated char* szName);
1131 void SetSourceFileName(BinStr* pbsName);
1132 // header flags
1133 DWORD m_dwSubsystem;
1134 WORD m_wSSVersionMajor;
1135 WORD m_wSSVersionMinor;
1136 DWORD m_dwComImageFlags;
1137 DWORD m_dwFileAlignment;
1138 ULONGLONG m_stBaseAddress;
1139 size_t m_stSizeOfStackReserve;
1140 DWORD m_dwCeeFileFlags;
1141 WORD m_wMSVmajor;
1142 WORD m_wMSVminor;
1143 BOOL m_fAppContainer;
1144 BOOL m_fHighEntropyVA;
1145
1146 // Former globals
1147 WCHAR *m_wzResourceFile;
1148 WCHAR *m_wzKeySourceName;
1149 bool OnErrGo;
1150 void SetCodePage(unsigned val) { g_uCodePage = val; };
1151 Clockwork* bClock;
1152 void SetClock(Clockwork* val) { bClock = val; };
1153 // ENC paraphernalia
1154 HRESULT InitMetaDataForENC(__in __nullterminated WCHAR* wzOrigFileName);
1155 BOOL EmitFieldsMethodsENC(Class* pClass);
1156 BOOL EmitEventsPropsENC(Class* pClass);
1157 HRESULT CreateDeltaFiles(__in __nullterminated WCHAR *pwzOutputFilename);
1158
1159 // Syntactic sugar paraphernalia
1160private:
1161 TypeDefDList m_TypeDefDList;
1162public:
1163 void AddTypeDef(BinStr* pbsTypeSpec, __in_z __in char* szName)
1164 {
1165 m_TypeDefDList.PUSH(new TypeDefDescr(szName, pbsTypeSpec, ResolveTypeSpec(pbsTypeSpec)));
1166 };
1167 void AddTypeDef(mdToken tkTypeSpec, __in_z __in char* szName)
1168 {
1169 m_TypeDefDList.PUSH(new TypeDefDescr(szName, NULL, tkTypeSpec));
1170 };
1171 void AddTypeDef(CustomDescr* pCA, __in_z __in char* szName)
1172 {
1173 TypeDefDescr* pNew = new TypeDefDescr(szName,NULL,mdtCustomAttribute);
1174 pNew->m_pCA = pCA;
1175 m_TypeDefDList.PUSH(pNew);
1176 };
1177 TypeDefDescr* FindTypeDef(__in_z __in char* szName)
1178 {
1179 CHECK_LOCAL_STATIC_VAR(static TypeDefDescr X(NULL, NULL, 0));
1180
1181 X.m_szName = szName;
1182 TypeDefDescr* Y = m_TypeDefDList.FIND(&X);
1183 X.m_szName = NULL; // to avoid deletion when X goes out of scope
1184 return Y;
1185 //return m_TypeDefDList.FIND(szName);
1186 };
1187 unsigned NumTypeDefs() {return m_TypeDefDList.COUNT();};
1188private:
1189 HRESULT GetCAName(mdToken tkCA, __out LPWSTR *ppszName);
1190};
1191
1192#endif // Assember_h
1193
1194#ifdef _MSC_VER
1195#pragma warning(default : 4640)
1196#endif
1197
1198
1199