| 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" |
| 56 | extern CoreCLRLoader *g_loader; |
| 57 | extern char *g_pszExeFile; |
| 58 | #endif |
| 59 | typedef 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 | |
| 64 | extern MetaDataGetDispenserFunc metaDataGetDispenser; |
| 65 | |
| 66 | extern WCHAR wzUniBuf[]; // Unicode conversion global buffer (assem.cpp) |
| 67 | |
| 68 | class Class; |
| 69 | class Method; |
| 70 | class PermissionDecl; |
| 71 | class PermissionSetDecl; |
| 72 | |
| 73 | unsigned 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 | |
| 78 | struct 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 | }; |
| 87 | typedef FIFO<MemberRefDescriptor> MemberRefDList; |
| 88 | |
| 89 | |
| 90 | struct MethodImplDescriptor |
| 91 | { |
| 92 | mdToken m_tkImplementedMethod; |
| 93 | mdToken m_tkImplementingMethod; |
| 94 | mdToken m_tkDefiningClass; |
| 95 | BOOL m_fNew; |
| 96 | }; |
| 97 | typedef FIFO<MethodImplDescriptor> MethodImplDList; |
| 98 | |
| 99 | struct 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 | }; |
| 111 | typedef FIFO<LocalMemberRefFixup> LocalMemberRefFixupList; |
| 112 | |
| 113 | struct 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 | }; |
| 124 | typedef FIFO<CustomDescr> CustomDescrList; |
| 125 | typedef 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 | |
| 135 | typedef enum |
| 136 | { |
| 137 | STATE_OK, |
| 138 | STATE_FAIL, |
| 139 | STATE_ENDMETHOD, |
| 140 | STATE_ENDFILE |
| 141 | } state_t; |
| 142 | |
| 143 | |
| 144 | class GlobalLabel |
| 145 | { |
| 146 | public: |
| 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; |
| 173 | typedef RBTREE<GlobalLabel> GlobalLabelList; |
| 174 | //typedef FIFO_INDEXED<GlobalLabel> GlobalLabelList; |
| 175 | |
| 176 | class CeeFileGenWriter; |
| 177 | class CeeSection; |
| 178 | |
| 179 | class BinStr; |
| 180 | |
| 181 | /************************************************************************/ |
| 182 | /* represents an object that knows how to report errors back to the user */ |
| 183 | |
| 184 | class ErrorReporter |
| 185 | { |
| 186 | public: |
| 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 | |
| 195 | struct 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 */ |
| 206 | struct 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 | |
| 225 | typedef LIFO<char> StringStack; |
| 226 | typedef LIFO<SEH_Descriptor> SEHD_Stack; |
| 227 | |
| 228 | typedef FIFO<Method> MethodList; |
| 229 | //typedef SORTEDARRAY<Method> MethodSortedList; |
| 230 | typedef FIFO<mdToken> TokenList; |
| 231 | /**************************************************************************/ |
| 232 | /* The field, event and property descriptor structures */ |
| 233 | |
| 234 | struct 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 | }; |
| 256 | typedef FIFO<FieldDescriptor> FieldDList; |
| 257 | |
| 258 | struct 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 | }; |
| 273 | typedef FIFO<EventDescriptor> EventDList; |
| 274 | |
| 275 | struct 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 | }; |
| 293 | typedef FIFO<PropDescriptor> PropDList; |
| 294 | |
| 295 | struct 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 | }; |
| 321 | typedef FIFO<ImportDescriptor> ImportList; |
| 322 | |
| 323 | |
| 324 | /**************************************************************************/ |
| 325 | #include "class.hpp" |
| 326 | typedef LIFO<Class> ClassStack; |
| 327 | typedef FIFO<Class> ClassList; |
| 328 | //typedef SORTEDARRAY<Class> ClassHash; |
| 329 | typedef 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 | |
| 338 | class PermissionDecl |
| 339 | { |
| 340 | public: |
| 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 | |
| 384 | private: |
| 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 | |
| 509 | class PermissionSetDecl |
| 510 | { |
| 511 | public: |
| 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 | |
| 529 | struct 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 | }; |
| 537 | typedef FIFO<VTFEntry> VTFList; |
| 538 | |
| 539 | struct EATEntry |
| 540 | { |
| 541 | DWORD dwStubRVA; |
| 542 | DWORD dwOrdinal; |
| 543 | char* szAlias; |
| 544 | }; |
| 545 | typedef FIFO<EATEntry> EATList; |
| 546 | |
| 547 | struct DocWriter |
| 548 | { |
| 549 | char* Name; |
| 550 | ISymUnmanagedDocumentWriter* pWriter; |
| 551 | DocWriter() { Name=NULL; pWriter=NULL; }; |
| 552 | ~DocWriter() { delete [] Name; if(pWriter) pWriter->Release();}; |
| 553 | }; |
| 554 | typedef 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) */ |
| 561 | struct 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: |
| 574 | struct MethodBody |
| 575 | { |
| 576 | BinStr* pbsBody; |
| 577 | unsigned RVA; |
| 578 | BYTE* pCode; |
| 579 | }; |
| 580 | typedef FIFO<MethodBody> MethodBodyList; |
| 581 | |
| 582 | struct 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 | |
| 602 | struct 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 | }; |
| 621 | typedef SORTEDARRAY<TypeDefDescr> TypeDefDList; |
| 622 | |
| 623 | struct 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 | |
| 662 | class Assembler { |
| 663 | public: |
| 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: |
| 873 | public: |
| 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: |
| 914 | public: |
| 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: |
| 927 | public: |
| 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 | |
| 939 | private: |
| 940 | MemberRefDList m_LocalMethodRefDList; |
| 941 | MemberRefDList m_LocalFieldRefDList; |
| 942 | LocalMemberRefFixupList m_LocalMemberRefFixupList; |
| 943 | MethodBodyList m_MethodBodyList; |
| 944 | MemberRefDList m_MethodSpecList; |
| 945 | public: |
| 946 | HRESULT ResolveLocalMemberRefs(); |
| 947 | HRESULT DoLocalMemberRefFixups(); |
| 948 | mdToken ResolveLocalMemberRef(mdToken tok); |
| 949 | |
| 950 | // PInvoke paraphernalia |
| 951 | public: |
| 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 |
| 960 | public: |
| 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 |
| 980 | public: |
| 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: |
| 1057 | public: |
| 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) |
| 1108 | public: |
| 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: |
| 1120 | private: |
| 1121 | MethodImplDList m_MethodImplDList; |
| 1122 | public: |
| 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 |
| 1160 | private: |
| 1161 | TypeDefDList m_TypeDefDList; |
| 1162 | public: |
| 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();}; |
| 1188 | private: |
| 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 | |