1 // ==++== 2 // 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // 5 // ==--== 6 // <OWNER>Microsoft</OWNER> 7 // 8 9 namespace System.Reflection.Emit 10 { 11 using System.Text; 12 using System; 13 using CultureInfo = System.Globalization.CultureInfo; 14 using System.Diagnostics.SymbolStore; 15 using System.Reflection; 16 using System.Security; 17 using System.Collections; 18 using System.Collections.Generic; 19 using System.Security.Permissions; 20 using System.Runtime.InteropServices; 21 using System.Diagnostics.Contracts; 22 #if !MONO 23 [HostProtection(MayLeakOnAbort = true)] 24 [ClassInterface(ClassInterfaceType.None)] 25 [ComDefaultInterface(typeof(_MethodBuilder))] 26 [System.Runtime.InteropServices.ComVisible(true)] 27 public sealed class MethodBuilder : MethodInfo, _MethodBuilder 28 { 29 #region Private Data Members 30 // Identity 31 internal String m_strName; // The name of the method 32 private MethodToken m_tkMethod; // The token of this method 33 private ModuleBuilder m_module; 34 internal TypeBuilder m_containingType; 35 36 // IL 37 private int[] m_mdMethodFixups; // The location of all of the token fixups. Null means no fixups. 38 private byte[] m_localSignature; // Local signature if set explicitly via DefineBody. Null otherwise. 39 internal LocalSymInfo m_localSymInfo; // keep track debugging local information 40 internal ILGenerator m_ilGenerator; // Null if not used. 41 private byte[] m_ubBody; // The IL for the method 42 private ExceptionHandler[] m_exceptions; // Exception handlers or null if there are none. 43 private const int DefaultMaxStack = 16; 44 private int m_maxStack = DefaultMaxStack; 45 46 // Flags 47 internal bool m_bIsBaked; 48 private bool m_bIsGlobalMethod; 49 private bool m_fInitLocals; // indicating if the method stack frame will be zero initialized or not. 50 51 // Attributes 52 private MethodAttributes m_iAttributes; 53 private CallingConventions m_callingConvention; 54 private MethodImplAttributes m_dwMethodImplFlags; 55 56 // Parameters 57 private SignatureHelper m_signature; 58 internal Type[] m_parameterTypes; 59 private ParameterBuilder m_retParam; 60 private Type m_returnType; 61 private Type[] m_returnTypeRequiredCustomModifiers; 62 private Type[] m_returnTypeOptionalCustomModifiers; 63 private Type[][] m_parameterTypeRequiredCustomModifiers; 64 private Type[][] m_parameterTypeOptionalCustomModifiers; 65 66 // Generics 67 private GenericTypeParameterBuilder[] m_inst; 68 private bool m_bIsGenMethDef; 69 #endregion 70 71 #region Constructor MethodBuilder(String name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, ModuleBuilder mod, TypeBuilder type, bool bIsGlobalMethod)72 internal MethodBuilder(String name, MethodAttributes attributes, CallingConventions callingConvention, 73 Type returnType, Type[] parameterTypes, ModuleBuilder mod, TypeBuilder type, bool bIsGlobalMethod) 74 { 75 Init(name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null, mod, type, bIsGlobalMethod); 76 } 77 MethodBuilder(String name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers, ModuleBuilder mod, TypeBuilder type, bool bIsGlobalMethod)78 internal MethodBuilder(String name, MethodAttributes attributes, CallingConventions callingConvention, 79 Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, 80 Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers, 81 ModuleBuilder mod, TypeBuilder type, bool bIsGlobalMethod) 82 { 83 Init(name, attributes, callingConvention, 84 returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, 85 parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, 86 mod, type, bIsGlobalMethod); 87 } 88 Init(String name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers, ModuleBuilder mod, TypeBuilder type, bool bIsGlobalMethod)89 private void Init(String name, MethodAttributes attributes, CallingConventions callingConvention, 90 Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, 91 Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers, 92 ModuleBuilder mod, TypeBuilder type, bool bIsGlobalMethod) 93 { 94 if (name == null) 95 throw new ArgumentNullException("name"); 96 97 if (name.Length == 0) 98 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); 99 100 if (name[0] == '\0') 101 throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "name"); 102 103 if (mod == null) 104 throw new ArgumentNullException("mod"); 105 Contract.EndContractBlock(); 106 107 if (parameterTypes != null) 108 { 109 foreach(Type t in parameterTypes) 110 { 111 if (t == null) 112 throw new ArgumentNullException("parameterTypes"); 113 } 114 } 115 116 m_strName = name; 117 m_module = mod; 118 m_containingType = type; 119 120 // 121 //if (returnType == null) 122 //{ 123 // m_returnType = typeof(void); 124 //} 125 //else 126 { 127 m_returnType = returnType; 128 } 129 130 if ((attributes & MethodAttributes.Static) == 0) 131 { 132 // turn on the has this calling convention 133 callingConvention = callingConvention | CallingConventions.HasThis; 134 } 135 else if ((attributes & MethodAttributes.Virtual) != 0) 136 { 137 // A method can't be both static and virtual 138 throw new ArgumentException(Environment.GetResourceString("Arg_NoStaticVirtual")); 139 } 140 141 if ((attributes & MethodAttributes.SpecialName) != MethodAttributes.SpecialName) 142 { 143 if ((type.Attributes & TypeAttributes.Interface) == TypeAttributes.Interface) 144 { 145 // methods on interface have to be abstract + virtual except special name methods such as type initializer 146 if ((attributes & (MethodAttributes.Abstract | MethodAttributes.Virtual)) != 147 (MethodAttributes.Abstract | MethodAttributes.Virtual) && 148 (attributes & MethodAttributes.Static) == 0) 149 throw new ArgumentException(Environment.GetResourceString("Argument_BadAttributeOnInterfaceMethod")); 150 } 151 } 152 153 m_callingConvention = callingConvention; 154 155 if (parameterTypes != null) 156 { 157 m_parameterTypes = new Type[parameterTypes.Length]; 158 Array.Copy(parameterTypes, m_parameterTypes, parameterTypes.Length); 159 } 160 else 161 { 162 m_parameterTypes = null; 163 } 164 165 m_returnTypeRequiredCustomModifiers = returnTypeRequiredCustomModifiers; 166 m_returnTypeOptionalCustomModifiers = returnTypeOptionalCustomModifiers; 167 m_parameterTypeRequiredCustomModifiers = parameterTypeRequiredCustomModifiers; 168 m_parameterTypeOptionalCustomModifiers = parameterTypeOptionalCustomModifiers; 169 170 // m_signature = SignatureHelper.GetMethodSigHelper(mod, callingConvention, 171 // returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, 172 // parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers); 173 174 m_iAttributes = attributes; 175 m_bIsGlobalMethod = bIsGlobalMethod; 176 m_bIsBaked = false; 177 m_fInitLocals = true; 178 179 m_localSymInfo = new LocalSymInfo(); 180 m_ubBody = null; 181 m_ilGenerator = null; 182 183 // Default is managed IL. Manged IL has bit flag 0x0020 set off 184 m_dwMethodImplFlags = MethodImplAttributes.IL; 185 } 186 187 #endregion 188 189 #region Internal Members 190 CheckContext(params Type[][] typess)191 internal void CheckContext(params Type[][] typess) 192 { 193 m_module.CheckContext(typess); 194 } 195 CheckContext(params Type[] types)196 internal void CheckContext(params Type[] types) 197 { 198 m_module.CheckContext(types); 199 } 200 201 [System.Security.SecurityCritical] // auto-generated CreateMethodBodyHelper(ILGenerator il)202 internal void CreateMethodBodyHelper(ILGenerator il) 203 { 204 // Sets the IL of the method. An ILGenerator is passed as an argument and the method 205 // queries this instance to get all of the information which it needs. 206 if (il == null) 207 { 208 throw new ArgumentNullException("il"); 209 } 210 Contract.EndContractBlock(); 211 212 __ExceptionInfo[] excp; 213 int counter=0; 214 int[] filterAddrs; 215 int[] catchAddrs; 216 int[] catchEndAddrs; 217 Type[] catchClass; 218 int[] type; 219 int numCatch; 220 int start, end; 221 ModuleBuilder dynMod = (ModuleBuilder) m_module; 222 223 m_containingType.ThrowIfCreated(); 224 225 if (m_bIsBaked) 226 { 227 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodHasBody")); 228 } 229 230 if (il.m_methodBuilder != this && il.m_methodBuilder != null) 231 { 232 // you don't need to call DefineBody when you get your ILGenerator 233 // through MethodBuilder::GetILGenerator. 234 // 235 236 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadILGeneratorUsage")); 237 } 238 239 ThrowIfShouldNotHaveBody(); 240 241 if (il.m_ScopeTree.m_iOpenScopeCount != 0) 242 { 243 // There are still unclosed local scope 244 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_OpenLocalVariableScope")); 245 } 246 247 248 m_ubBody = il.BakeByteArray(); 249 250 m_mdMethodFixups = il.GetTokenFixups(); 251 252 //Okay, now the fun part. Calculate all of the exceptions. 253 excp = il.GetExceptions(); 254 int numExceptions = CalculateNumberOfExceptions(excp); 255 if (numExceptions > 0) 256 { 257 m_exceptions = new ExceptionHandler[numExceptions]; 258 259 for (int i = 0; i < excp.Length; i++) 260 { 261 filterAddrs = excp[i].GetFilterAddresses(); 262 catchAddrs = excp[i].GetCatchAddresses(); 263 catchEndAddrs = excp[i].GetCatchEndAddresses(); 264 catchClass = excp[i].GetCatchClass(); 265 266 numCatch = excp[i].GetNumberOfCatches(); 267 start = excp[i].GetStartAddress(); 268 end = excp[i].GetEndAddress(); 269 type = excp[i].GetExceptionTypes(); 270 for (int j = 0; j < numCatch; j++) 271 { 272 int tkExceptionClass = 0; 273 if (catchClass[j] != null) 274 { 275 tkExceptionClass = dynMod.GetTypeTokenInternal(catchClass[j]).Token; 276 } 277 278 switch (type[j]) 279 { 280 case __ExceptionInfo.None: 281 case __ExceptionInfo.Fault: 282 case __ExceptionInfo.Filter: 283 m_exceptions[counter++] = new ExceptionHandler(start, end, filterAddrs[j], catchAddrs[j], catchEndAddrs[j], type[j], tkExceptionClass); 284 break; 285 286 case __ExceptionInfo.Finally: 287 m_exceptions[counter++] = new ExceptionHandler(start, excp[i].GetFinallyEndAddress(), filterAddrs[j], catchAddrs[j], catchEndAddrs[j], type[j], tkExceptionClass); 288 break; 289 } 290 } 291 292 } 293 } 294 295 296 m_bIsBaked=true; 297 298 if (dynMod.GetSymWriter() != null) 299 { 300 301 // set the debugging information such as scope and line number 302 // if it is in a debug module 303 // 304 SymbolToken tk = new SymbolToken(MetadataTokenInternal); 305 ISymbolWriter symWriter = dynMod.GetSymWriter(); 306 307 // call OpenMethod to make this method the current method 308 symWriter.OpenMethod(tk); 309 310 // call OpenScope because OpenMethod no longer implicitly creating 311 // the top-levelsmethod scope 312 // 313 symWriter.OpenScope(0); 314 315 if (m_symCustomAttrs != null) 316 { 317 foreach(SymCustomAttr symCustomAttr in m_symCustomAttrs) 318 dynMod.GetSymWriter().SetSymAttribute( 319 new SymbolToken (MetadataTokenInternal), 320 symCustomAttr.m_name, 321 symCustomAttr.m_data); 322 } 323 324 if (m_localSymInfo != null) 325 m_localSymInfo.EmitLocalSymInfo(symWriter); 326 il.m_ScopeTree.EmitScopeTree(symWriter); 327 il.m_LineNumberInfo.EmitLineNumberInfo(symWriter); 328 symWriter.CloseScope(il.ILOffset); 329 symWriter.CloseMethod(); 330 } 331 } 332 333 // This is only called from TypeBuilder.CreateType after the method has been created ReleaseBakedStructures()334 internal void ReleaseBakedStructures() 335 { 336 if (!m_bIsBaked) 337 { 338 // We don't need to do anything here if we didn't baked the method body 339 return; 340 } 341 342 m_ubBody = null; 343 m_localSymInfo = null; 344 m_mdMethodFixups = null; 345 m_localSignature = null; 346 m_exceptions = null; 347 } 348 GetParameterTypes()349 internal override Type[] GetParameterTypes() 350 { 351 if (m_parameterTypes == null) 352 m_parameterTypes = EmptyArray<Type>.Value; 353 354 return m_parameterTypes; 355 } 356 GetMethodBaseReturnType(MethodBase method)357 internal static Type GetMethodBaseReturnType(MethodBase method) 358 { 359 MethodInfo mi = null; 360 ConstructorInfo ci = null; 361 362 if ( (mi = method as MethodInfo) != null ) 363 { 364 return mi.ReturnType; 365 } 366 else if ( (ci = method as ConstructorInfo) != null) 367 { 368 return ci.GetReturnType(); 369 } 370 else 371 { 372 Contract.Assert(false, "We should never get here!"); 373 return null; 374 } 375 } 376 SetToken(MethodToken token)377 internal void SetToken(MethodToken token) 378 { 379 m_tkMethod = token; 380 } 381 GetBody()382 internal byte[] GetBody() 383 { 384 // Returns the il bytes of this method. 385 // This il is not valid until somebody has called BakeByteArray 386 return m_ubBody; 387 } 388 GetTokenFixups()389 internal int[] GetTokenFixups() 390 { 391 return m_mdMethodFixups; 392 } 393 394 [System.Security.SecurityCritical] // auto-generated GetMethodSignature()395 internal SignatureHelper GetMethodSignature() 396 { 397 if (m_parameterTypes == null) 398 m_parameterTypes = EmptyArray<Type>.Value; 399 400 m_signature = SignatureHelper.GetMethodSigHelper (m_module, m_callingConvention, m_inst != null ? m_inst.Length : 0, 401 m_returnType == null ? typeof(void) : m_returnType, m_returnTypeRequiredCustomModifiers, m_returnTypeOptionalCustomModifiers, 402 m_parameterTypes, m_parameterTypeRequiredCustomModifiers, m_parameterTypeOptionalCustomModifiers); 403 404 return m_signature; 405 } 406 407 // Returns a buffer whose initial signatureLength bytes contain encoded local signature. GetLocalSignature(out int signatureLength)408 internal byte[] GetLocalSignature(out int signatureLength) 409 { 410 if (m_localSignature != null) 411 { 412 signatureLength = m_localSignature.Length; 413 return m_localSignature; 414 } 415 416 if (m_ilGenerator != null) 417 { 418 if (m_ilGenerator.m_localCount != 0) 419 { 420 // If user is using ILGenerator::DeclareLocal, then get local signaturefrom there. 421 return m_ilGenerator.m_localSignature.InternalGetSignature(out signatureLength); 422 } 423 } 424 425 return SignatureHelper.GetLocalVarSigHelper(m_module).InternalGetSignature(out signatureLength); 426 } 427 GetMaxStack()428 internal int GetMaxStack() 429 { 430 if (m_ilGenerator != null) 431 { 432 return m_ilGenerator.GetMaxStackSize() + ExceptionHandlerCount; 433 } 434 else 435 { 436 // this is the case when client provide an array of IL byte stream rather than going through ILGenerator. 437 return m_maxStack; 438 } 439 } 440 GetExceptionHandlers()441 internal ExceptionHandler[] GetExceptionHandlers() 442 { 443 return m_exceptions; 444 } 445 446 internal int ExceptionHandlerCount 447 { 448 get { return m_exceptions != null ? m_exceptions.Length : 0; } 449 } 450 CalculateNumberOfExceptions(__ExceptionInfo[] excp)451 internal int CalculateNumberOfExceptions(__ExceptionInfo[] excp) 452 { 453 int num=0; 454 455 if (excp==null) 456 { 457 return 0; 458 } 459 460 for (int i=0; i<excp.Length; i++) 461 { 462 num+=excp[i].GetNumberOfCatches(); 463 } 464 465 return num; 466 } 467 IsTypeCreated()468 internal bool IsTypeCreated() 469 { 470 return (m_containingType != null && m_containingType.IsCreated()); 471 } 472 GetTypeBuilder()473 internal TypeBuilder GetTypeBuilder() 474 { 475 return m_containingType; 476 } 477 GetModuleBuilder()478 internal ModuleBuilder GetModuleBuilder() 479 { 480 return m_module; 481 } 482 #endregion 483 484 #region Object Overrides 485 [System.Security.SecuritySafeCritical] // auto-generated Equals(Object obj)486 public override bool Equals(Object obj) { 487 if (!(obj is MethodBuilder)) { 488 return false; 489 } 490 if (!(this.m_strName.Equals(((MethodBuilder)obj).m_strName))) { 491 return false; 492 } 493 494 if (m_iAttributes!=(((MethodBuilder)obj).m_iAttributes)) { 495 return false; 496 } 497 498 SignatureHelper thatSig = ((MethodBuilder)obj).GetMethodSignature(); 499 if (thatSig.Equals(GetMethodSignature())) { 500 return true; 501 } 502 return false; 503 } 504 GetHashCode()505 public override int GetHashCode() 506 { 507 return this.m_strName.GetHashCode(); 508 } 509 510 [System.Security.SecuritySafeCritical] // auto-generated ToString()511 public override String ToString() 512 { 513 StringBuilder sb = new StringBuilder(1000); 514 sb.Append("Name: " + m_strName + " " + Environment.NewLine); 515 sb.Append("Attributes: " + (int)m_iAttributes + Environment.NewLine); 516 sb.Append("Method Signature: " + GetMethodSignature() + Environment.NewLine); 517 sb.Append(Environment.NewLine); 518 return sb.ToString(); 519 } 520 521 #endregion 522 523 #region MemberInfo Overrides 524 public override String Name 525 { 526 get 527 { 528 return m_strName; 529 } 530 } 531 532 internal int MetadataTokenInternal 533 { 534 get 535 { 536 return GetToken().Token; 537 } 538 } 539 540 public override Module Module 541 { 542 get 543 { 544 return m_containingType.Module; 545 } 546 } 547 548 public override Type DeclaringType 549 { 550 get 551 { 552 if (m_containingType.m_isHiddenGlobalType == true) 553 return null; 554 return m_containingType; 555 } 556 } 557 558 public override ICustomAttributeProvider ReturnTypeCustomAttributes 559 { 560 get 561 { 562 return null; 563 } 564 } 565 566 public override Type ReflectedType 567 { 568 get 569 { 570 return DeclaringType; 571 } 572 } 573 574 #endregion 575 576 #region MethodBase Overrides Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)577 public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 578 { 579 throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); 580 } 581 GetMethodImplementationFlags()582 public override MethodImplAttributes GetMethodImplementationFlags() 583 { 584 return m_dwMethodImplFlags; 585 } 586 587 public override MethodAttributes Attributes 588 { 589 get { return m_iAttributes; } 590 } 591 592 public override CallingConventions CallingConvention 593 { 594 get {return m_callingConvention;} 595 } 596 597 public override RuntimeMethodHandle MethodHandle 598 { 599 get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); } 600 } 601 602 public override bool IsSecurityCritical 603 { 604 get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); } 605 } 606 607 public override bool IsSecuritySafeCritical 608 { 609 get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); } 610 } 611 612 public override bool IsSecurityTransparent 613 { 614 get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); } 615 } 616 #endregion 617 618 #region MethodInfo Overrides GetBaseDefinition()619 public override MethodInfo GetBaseDefinition() 620 { 621 return this; 622 } 623 624 public override Type ReturnType 625 { 626 get 627 { 628 return m_returnType; 629 } 630 } 631 632 [Pure] GetParameters()633 public override ParameterInfo[] GetParameters() 634 { 635 if (!m_bIsBaked || m_containingType == null || m_containingType.BakedRuntimeType == null) 636 throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_TypeNotCreated")); 637 638 MethodInfo rmi = m_containingType.GetMethod(m_strName, m_parameterTypes); 639 640 return rmi.GetParameters(); 641 } 642 643 public override ParameterInfo ReturnParameter 644 { 645 get 646 { 647 if (!m_bIsBaked || m_containingType == null || m_containingType.BakedRuntimeType == null) 648 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TypeNotCreated")); 649 650 MethodInfo rmi = m_containingType.GetMethod(m_strName, m_parameterTypes); 651 652 return rmi.ReturnParameter; 653 } 654 } 655 #endregion 656 657 #region ICustomAttributeProvider Implementation GetCustomAttributes(bool inherit)658 public override Object[] GetCustomAttributes(bool inherit) 659 { 660 661 throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); 662 } 663 GetCustomAttributes(Type attributeType, bool inherit)664 public override Object[] GetCustomAttributes(Type attributeType, bool inherit) 665 { 666 667 throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); 668 } 669 IsDefined(Type attributeType, bool inherit)670 public override bool IsDefined(Type attributeType, bool inherit) 671 { 672 673 throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); 674 } 675 676 #endregion 677 678 #region Generic Members 679 public override bool IsGenericMethodDefinition { get { return m_bIsGenMethDef; } } 680 681 public override bool ContainsGenericParameters { get { throw new NotSupportedException(); } } 682 GetGenericMethodDefinition()683 public override MethodInfo GetGenericMethodDefinition() { if (!IsGenericMethod) throw new InvalidOperationException(); return this; } 684 685 public override bool IsGenericMethod { get { return m_inst != null; } } 686 GetGenericArguments()687 public override Type[] GetGenericArguments() { return m_inst; } 688 MakeGenericMethod(params Type[] typeArguments)689 public override MethodInfo MakeGenericMethod(params Type[] typeArguments) 690 { 691 return MethodBuilderInstantiation.MakeGenericMethod(this, typeArguments); 692 } 693 694 DefineGenericParameters(params string[] names)695 public GenericTypeParameterBuilder[] DefineGenericParameters (params string[] names) 696 { 697 if (names == null) 698 throw new ArgumentNullException("names"); 699 700 if (names.Length == 0) 701 throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "names"); 702 Contract.EndContractBlock(); 703 704 if (m_inst != null) 705 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GenericParametersAlreadySet")); 706 707 for (int i = 0; i < names.Length; i ++) 708 if (names[i] == null) 709 throw new ArgumentNullException("names"); 710 711 if (m_tkMethod.Token != 0) 712 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodBuilderBaked")); 713 714 m_bIsGenMethDef = true; 715 m_inst = new GenericTypeParameterBuilder[names.Length]; 716 for (int i = 0; i < names.Length; i ++) 717 m_inst[i] = new GenericTypeParameterBuilder(new TypeBuilder(names[i], i, this)); 718 719 return m_inst; 720 } 721 ThrowIfGeneric()722 internal void ThrowIfGeneric () { if (IsGenericMethod && !IsGenericMethodDefinition) throw new InvalidOperationException (); } 723 #endregion 724 725 #region Public Members 726 [System.Security.SecuritySafeCritical] // auto-generated GetToken()727 public MethodToken GetToken() 728 { 729 // We used to always "tokenize" a MethodBuilder when it is constructed. After change list 709498 730 // we only "tokenize" a method when requested. But the order in which the methods are tokenized 731 // didn't change: the same order the MethodBuilders are constructed. The recursion introduced 732 // will overflow the stack when there are many methods on the same type (10000 in my experiment). 733 // The change also introduced race conditions. Before the code change GetToken is called from 734 // the MethodBuilder .ctor which is protected by lock(ModuleBuilder.SyncRoot). Now it 735 // could be called more than once on the the same method introducing duplicate (invalid) tokens. 736 // I don't fully understand this change. So I will keep the logic and only fix the recursion and 737 // the race condition. 738 739 if (m_tkMethod.Token != 0) 740 { 741 return m_tkMethod; 742 } 743 744 MethodBuilder currentMethod = null; 745 MethodToken currentToken = new MethodToken(0); 746 int i; 747 748 // We need to lock here to prevent a method from being "tokenized" twice. 749 // We don't need to synchronize this with Type.DefineMethod because it only appends newly 750 // constructed MethodBuilders to the end of m_listMethods 751 lock (m_containingType.m_listMethods) 752 { 753 if (m_tkMethod.Token != 0) 754 { 755 return m_tkMethod; 756 } 757 758 // If m_tkMethod is still 0 when we obtain the lock, m_lastTokenizedMethod must be smaller 759 // than the index of the current method. 760 for (i = m_containingType.m_lastTokenizedMethod + 1; i < m_containingType.m_listMethods.Count; ++i) 761 { 762 currentMethod = m_containingType.m_listMethods[i]; 763 currentToken = currentMethod.GetTokenNoLock(); 764 765 if (currentMethod == this) 766 break; 767 } 768 769 m_containingType.m_lastTokenizedMethod = i; 770 } 771 772 Contract.Assert(currentMethod == this, "We should have found this method in m_containingType.m_listMethods"); 773 Contract.Assert(currentToken.Token != 0, "The token should not be 0"); 774 775 return currentToken; 776 } 777 778 [System.Security.SecurityCritical] // auto-generated GetTokenNoLock()779 private MethodToken GetTokenNoLock() 780 { 781 Contract.Assert(m_tkMethod.Token == 0, "m_tkMethod should not have been initialized"); 782 783 int sigLength; 784 byte[] sigBytes = GetMethodSignature().InternalGetSignature(out sigLength); 785 786 int token = TypeBuilder.DefineMethod(m_module.GetNativeHandle(), m_containingType.MetadataTokenInternal, m_strName, sigBytes, sigLength, Attributes); 787 m_tkMethod = new MethodToken(token); 788 789 if (m_inst != null) 790 foreach (GenericTypeParameterBuilder tb in m_inst) 791 if (!tb.m_type.IsCreated()) tb.m_type.CreateType(); 792 793 TypeBuilder.SetMethodImpl(m_module.GetNativeHandle(), token, m_dwMethodImplFlags); 794 795 return m_tkMethod; 796 } 797 SetParameters(params Type[] parameterTypes)798 public void SetParameters (params Type[] parameterTypes) 799 { 800 CheckContext(parameterTypes); 801 802 SetSignature (null, null, null, parameterTypes, null, null); 803 } 804 SetReturnType(Type returnType)805 public void SetReturnType (Type returnType) 806 { 807 CheckContext(returnType); 808 809 SetSignature (returnType, null, null, null, null, null); 810 } 811 SetSignature( Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)812 public void SetSignature( 813 Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, 814 Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) 815 { 816 // We should throw InvalidOperation_MethodBuilderBaked here if the method signature has been baked. 817 // But we cannot because that would be a breaking change from V2. 818 if (m_tkMethod.Token != 0) 819 return; 820 821 CheckContext(returnType); 822 CheckContext(returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes); 823 CheckContext(parameterTypeRequiredCustomModifiers); 824 CheckContext(parameterTypeOptionalCustomModifiers); 825 826 ThrowIfGeneric(); 827 828 if (returnType != null) 829 { 830 m_returnType = returnType; 831 } 832 833 if (parameterTypes != null) 834 { 835 m_parameterTypes = new Type[parameterTypes.Length]; 836 Array.Copy (parameterTypes, m_parameterTypes, parameterTypes.Length); 837 } 838 839 m_returnTypeRequiredCustomModifiers = returnTypeRequiredCustomModifiers; 840 m_returnTypeOptionalCustomModifiers = returnTypeOptionalCustomModifiers; 841 m_parameterTypeRequiredCustomModifiers = parameterTypeRequiredCustomModifiers; 842 m_parameterTypeOptionalCustomModifiers = parameterTypeOptionalCustomModifiers; 843 } 844 845 846 [System.Security.SecuritySafeCritical] // auto-generated DefineParameter(int position, ParameterAttributes attributes, String strParamName)847 public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, String strParamName) 848 { 849 if (position < 0) 850 throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_ParamSequence")); 851 Contract.EndContractBlock(); 852 853 ThrowIfGeneric(); 854 m_containingType.ThrowIfCreated (); 855 856 if (position > 0 && (m_parameterTypes == null || position > m_parameterTypes.Length)) 857 throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_ParamSequence")); 858 859 attributes = attributes & ~ParameterAttributes.ReservedMask; 860 return new ParameterBuilder(this, position, attributes, strParamName); 861 } 862 863 [System.Security.SecuritySafeCritical] // auto-generated 864 [Obsolete("An alternate API is available: Emit the MarshalAs custom attribute instead. http://go.microsoft.com/fwlink/?linkid=14202")] SetMarshal(UnmanagedMarshal unmanagedMarshal)865 public void SetMarshal(UnmanagedMarshal unmanagedMarshal) 866 { 867 ThrowIfGeneric (); 868 869 // set Marshal info for the return type 870 871 m_containingType.ThrowIfCreated(); 872 873 if (m_retParam == null) 874 { 875 m_retParam = new ParameterBuilder(this, 0, 0, null); 876 } 877 878 m_retParam.SetMarshal(unmanagedMarshal); 879 } 880 881 private List<SymCustomAttr> m_symCustomAttrs; 882 private struct SymCustomAttr 883 { SymCustomAttrSystem.Reflection.Emit.MethodBuilder.SymCustomAttr884 public SymCustomAttr(String name, byte[] data) 885 { 886 m_name = name; 887 m_data = data; 888 } 889 public String m_name; 890 public byte[] m_data; 891 } 892 SetSymCustomAttribute(String name, byte[] data)893 public void SetSymCustomAttribute(String name, byte[] data) 894 { 895 // Note that this API is rarely used. Support for custom attributes in PDB files was added in 896 // Whidbey and as of 8/2007 the only known user is the C# compiler. There seems to be little 897 // value to this for Reflection.Emit users since they can always use metadata custom attributes. 898 // Some versions of the symbol writer used in the CLR will ignore these entirely. This API has 899 // been removed from the Silverlight API surface area, but we should also consider removing it 900 // from future desktop product versions as well. 901 902 ThrowIfGeneric (); 903 904 // This is different from CustomAttribute. This is stored into the SymWriter. 905 m_containingType.ThrowIfCreated(); 906 907 ModuleBuilder dynMod = (ModuleBuilder) m_module; 908 if ( dynMod.GetSymWriter() == null) 909 { 910 // Cannot SetSymCustomAttribute when it is not a debug module 911 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule")); 912 } 913 914 if (m_symCustomAttrs == null) 915 m_symCustomAttrs = new List<SymCustomAttr>(); 916 917 m_symCustomAttrs.Add(new SymCustomAttr(name, data)); 918 } 919 920 #if FEATURE_CAS_POLICY 921 [System.Security.SecuritySafeCritical] // auto-generated AddDeclarativeSecurity(SecurityAction action, PermissionSet pset)922 public void AddDeclarativeSecurity(SecurityAction action, PermissionSet pset) 923 { 924 if (pset == null) 925 throw new ArgumentNullException("pset"); 926 Contract.EndContractBlock(); 927 928 ThrowIfGeneric (); 929 930 #pragma warning disable 618 931 if (!Enum.IsDefined(typeof(SecurityAction), action) || 932 action == SecurityAction.RequestMinimum || 933 action == SecurityAction.RequestOptional || 934 action == SecurityAction.RequestRefuse) 935 { 936 throw new ArgumentOutOfRangeException("action"); 937 } 938 #pragma warning restore 618 939 940 // cannot declarative security after type is created 941 m_containingType.ThrowIfCreated(); 942 943 // Translate permission set into serialized format (uses standard binary serialization format). 944 byte[] blob = null; 945 int length = 0; 946 if (!pset.IsEmpty()) 947 { 948 blob = pset.EncodeXml(); 949 length = blob.Length; 950 } 951 952 // Write the blob into the metadata. 953 TypeBuilder.AddDeclarativeSecurity(m_module.GetNativeHandle(), MetadataTokenInternal, action, blob, length); 954 } 955 #endif // FEATURE_CAS_POLICY 956 957 #if FEATURE_CORECLR 958 [System.Security.SecurityCritical] // auto-generated 959 #endif SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable<ExceptionHandler> exceptionHandlers, IEnumerable<int> tokenFixups)960 public void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable<ExceptionHandler> exceptionHandlers, IEnumerable<int> tokenFixups) 961 { 962 if (il == null) 963 { 964 throw new ArgumentNullException("il", Environment.GetResourceString("ArgumentNull_Array")); 965 } 966 if (maxStack < 0) 967 { 968 throw new ArgumentOutOfRangeException("maxStack", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 969 } 970 Contract.EndContractBlock(); 971 972 if (m_bIsBaked) 973 { 974 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodBaked")); 975 } 976 977 m_containingType.ThrowIfCreated(); 978 ThrowIfGeneric(); 979 980 byte[] newLocalSignature = null; 981 ExceptionHandler[] newHandlers = null; 982 int[] newTokenFixups = null; 983 984 byte[] newIL = (byte[])il.Clone(); 985 986 if (localSignature != null) 987 { 988 newLocalSignature = (byte[])localSignature.Clone(); 989 } 990 991 if (exceptionHandlers != null) 992 { 993 newHandlers = ToArray(exceptionHandlers); 994 CheckExceptionHandlerRanges(newHandlers, newIL.Length); 995 996 // Note: Fixup entries for type tokens stored in ExceptionHandlers are added by the method body emitter. 997 } 998 999 if (tokenFixups != null) 1000 { 1001 newTokenFixups = ToArray(tokenFixups); 1002 int maxTokenOffset = newIL.Length - 4; 1003 1004 for (int i = 0; i < newTokenFixups.Length; i++) 1005 { 1006 // Check that fixups are within the range of this method's IL, otherwise some random memory might get "fixed up". 1007 if (newTokenFixups[i] < 0 || newTokenFixups[i] > maxTokenOffset) 1008 { 1009 throw new ArgumentOutOfRangeException("tokenFixups[" + i + "]", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, maxTokenOffset)); 1010 } 1011 } 1012 } 1013 1014 m_ubBody = newIL; 1015 m_localSignature = newLocalSignature; 1016 m_exceptions = newHandlers; 1017 m_mdMethodFixups = newTokenFixups; 1018 m_maxStack = maxStack; 1019 1020 // discard IL generator, all information stored in it is now irrelevant 1021 m_ilGenerator = null; 1022 m_bIsBaked = true; 1023 } 1024 ToArray(IEnumerable<T> sequence)1025 private static T[] ToArray<T>(IEnumerable<T> sequence) 1026 { 1027 T[] array = sequence as T[]; 1028 if (array != null) 1029 { 1030 return (T[])array.Clone(); 1031 } 1032 1033 return new List<T>(sequence).ToArray(); 1034 } 1035 CheckExceptionHandlerRanges(ExceptionHandler[] exceptionHandlers, int maxOffset)1036 private static void CheckExceptionHandlerRanges(ExceptionHandler[] exceptionHandlers, int maxOffset) 1037 { 1038 // Basic checks that the handler ranges are within the method body (ranges are end-exclusive). 1039 // Doesn't verify that the ranges are otherwise correct - it is very well possible to emit invalid IL. 1040 for (int i = 0; i < exceptionHandlers.Length; i++) 1041 { 1042 var handler = exceptionHandlers[i]; 1043 if (handler.m_filterOffset > maxOffset || handler.m_tryEndOffset > maxOffset || handler.m_handlerEndOffset > maxOffset) 1044 { 1045 throw new ArgumentOutOfRangeException("exceptionHandlers[" + i + "]", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, maxOffset)); 1046 } 1047 1048 // Type token might be 0 if the ExceptionHandler was created via a default constructor. 1049 // Other tokens migth also be invalid. We only check nil tokens as the implementation (SectEH_Emit in corhlpr.cpp) requires it, 1050 // and we can't check for valid tokens until the module is baked. 1051 if (handler.Kind == ExceptionHandlingClauseOptions.Clause && handler.ExceptionTypeToken == 0) 1052 { 1053 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeToken", handler.ExceptionTypeToken), "exceptionHandlers[" + i + "]"); 1054 } 1055 } 1056 } 1057 1058 /// <summary> 1059 /// Obsolete. 1060 /// </summary> 1061 #if FEATURE_CORECLR 1062 [System.Security.SecurityCritical] // auto-generated 1063 #endif CreateMethodBody(byte[] il, int count)1064 public void CreateMethodBody(byte[] il, int count) 1065 { 1066 ThrowIfGeneric(); 1067 1068 // Note that when user calls this function, there are a few information that client is 1069 // not able to supply: local signature, exception handlers, max stack size, a list of Token fixup, a list of RVA fixup 1070 1071 if (m_bIsBaked) 1072 { 1073 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodBaked")); 1074 } 1075 1076 m_containingType.ThrowIfCreated(); 1077 1078 if (il != null && (count < 0 || count > il.Length)) 1079 { 1080 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Index")); 1081 } 1082 1083 if (il == null) 1084 { 1085 m_ubBody = null; 1086 return; 1087 } 1088 1089 m_ubBody = new byte[count]; 1090 Array.Copy(il,m_ubBody,count); 1091 1092 m_localSignature = null; 1093 m_exceptions = null; 1094 m_mdMethodFixups = null; 1095 m_maxStack = DefaultMaxStack; 1096 1097 m_bIsBaked = true; 1098 } 1099 1100 [System.Security.SecuritySafeCritical] // auto-generated SetImplementationFlags(MethodImplAttributes attributes)1101 public void SetImplementationFlags(MethodImplAttributes attributes) 1102 { 1103 ThrowIfGeneric (); 1104 1105 m_containingType.ThrowIfCreated (); 1106 1107 m_dwMethodImplFlags = attributes; 1108 1109 m_canBeRuntimeImpl = true; 1110 1111 TypeBuilder.SetMethodImpl(m_module.GetNativeHandle(), MetadataTokenInternal, attributes); 1112 } 1113 GetILGenerator()1114 public ILGenerator GetILGenerator() { 1115 Contract.Ensures(Contract.Result<ILGenerator>() != null); 1116 1117 ThrowIfGeneric(); 1118 ThrowIfShouldNotHaveBody(); 1119 1120 if (m_ilGenerator == null) 1121 m_ilGenerator = new ILGenerator(this); 1122 return m_ilGenerator; 1123 } 1124 GetILGenerator(int size)1125 public ILGenerator GetILGenerator(int size) { 1126 Contract.Ensures(Contract.Result<ILGenerator>() != null); 1127 1128 ThrowIfGeneric (); 1129 ThrowIfShouldNotHaveBody(); 1130 1131 if (m_ilGenerator == null) 1132 m_ilGenerator = new ILGenerator(this, size); 1133 return m_ilGenerator; 1134 } 1135 ThrowIfShouldNotHaveBody()1136 private void ThrowIfShouldNotHaveBody() { 1137 if ((m_dwMethodImplFlags & MethodImplAttributes.CodeTypeMask) != MethodImplAttributes.IL || 1138 (m_dwMethodImplFlags & MethodImplAttributes.Unmanaged) != 0 || 1139 (m_iAttributes & MethodAttributes.PinvokeImpl) != 0 || 1140 m_isDllImport) 1141 { 1142 // cannot attach method body if methodimpl is marked not marked as managed IL 1143 // 1144 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ShouldNotHaveMethodBody")); 1145 } 1146 } 1147 1148 1149 public bool InitLocals 1150 { 1151 // Property is set to true if user wishes to have zero initialized stack frame for this method. Default to false. 1152 get { ThrowIfGeneric (); return m_fInitLocals; } 1153 set { ThrowIfGeneric (); m_fInitLocals = value; } 1154 } 1155 GetModule()1156 public Module GetModule() 1157 { 1158 return GetModuleBuilder(); 1159 } 1160 1161 public String Signature 1162 { 1163 [System.Security.SecuritySafeCritical] // auto-generated 1164 get 1165 { 1166 return GetMethodSignature().ToString(); 1167 } 1168 } 1169 1170 1171 #if FEATURE_CORECLR 1172 [System.Security.SecurityCritical] // auto-generated 1173 #else 1174 [System.Security.SecuritySafeCritical] 1175 #endif 1176 [System.Runtime.InteropServices.ComVisible(true)] SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)1177 public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) 1178 { 1179 if (con == null) 1180 throw new ArgumentNullException("con"); 1181 if (binaryAttribute == null) 1182 throw new ArgumentNullException("binaryAttribute"); 1183 Contract.EndContractBlock(); 1184 1185 ThrowIfGeneric(); 1186 1187 TypeBuilder.DefineCustomAttribute(m_module, MetadataTokenInternal, 1188 ((ModuleBuilder)m_module).GetConstructorToken(con).Token, 1189 binaryAttribute, 1190 false, false); 1191 1192 if (IsKnownCA(con)) 1193 ParseCA(con, binaryAttribute); 1194 } 1195 1196 [System.Security.SecuritySafeCritical] // auto-generated SetCustomAttribute(CustomAttributeBuilder customBuilder)1197 public void SetCustomAttribute(CustomAttributeBuilder customBuilder) 1198 { 1199 if (customBuilder == null) 1200 throw new ArgumentNullException("customBuilder"); 1201 Contract.EndContractBlock(); 1202 1203 ThrowIfGeneric(); 1204 1205 customBuilder.CreateCustomAttribute((ModuleBuilder)m_module, MetadataTokenInternal); 1206 1207 if (IsKnownCA(customBuilder.m_con)) 1208 ParseCA(customBuilder.m_con, customBuilder.m_blob); 1209 } 1210 1211 // this method should return true for any and every ca that requires more work 1212 // than just setting the ca IsKnownCA(ConstructorInfo con)1213 private bool IsKnownCA(ConstructorInfo con) 1214 { 1215 Type caType = con.DeclaringType; 1216 if (caType == typeof(System.Runtime.CompilerServices.MethodImplAttribute)) return true; 1217 else if (caType == typeof(DllImportAttribute)) return true; 1218 else return false; 1219 } 1220 ParseCA(ConstructorInfo con, byte[] blob)1221 private void ParseCA(ConstructorInfo con, byte[] blob) 1222 { 1223 Type caType = con.DeclaringType; 1224 if (caType == typeof(System.Runtime.CompilerServices.MethodImplAttribute)) 1225 { 1226 // dig through the blob looking for the MethodImplAttributes flag 1227 // that must be in the MethodCodeType field 1228 1229 // for now we simply set a flag that relaxes the check when saving and 1230 // allows this method to have no body when any kind of MethodImplAttribute is present 1231 m_canBeRuntimeImpl = true; 1232 } 1233 else if (caType == typeof(DllImportAttribute)) { 1234 m_canBeRuntimeImpl = true; 1235 m_isDllImport = true; 1236 } 1237 1238 } 1239 1240 internal bool m_canBeRuntimeImpl = false; 1241 internal bool m_isDllImport = false; 1242 1243 #endregion 1244 1245 #if !FEATURE_CORECLR _MethodBuilder.GetTypeInfoCount(out uint pcTInfo)1246 void _MethodBuilder.GetTypeInfoCount(out uint pcTInfo) 1247 { 1248 throw new NotImplementedException(); 1249 } 1250 _MethodBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)1251 void _MethodBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) 1252 { 1253 throw new NotImplementedException(); 1254 } 1255 _MethodBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)1256 void _MethodBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) 1257 { 1258 throw new NotImplementedException(); 1259 } 1260 _MethodBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)1261 void _MethodBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) 1262 { 1263 throw new NotImplementedException(); 1264 } 1265 #endif 1266 1267 } 1268 1269 internal class LocalSymInfo 1270 { 1271 // This class tracks the local variable's debugging information 1272 // and namespace information with a given active lexical scope. 1273 1274 #region Internal Data Members 1275 internal String[] m_strName; 1276 internal byte[][] m_ubSignature; 1277 internal int[] m_iLocalSlot; 1278 internal int[] m_iStartOffset; 1279 internal int[] m_iEndOffset; 1280 internal int m_iLocalSymCount; // how many entries in the arrays are occupied 1281 internal String[] m_namespace; 1282 internal int m_iNameSpaceCount; 1283 internal const int InitialSize = 16; 1284 #endregion 1285 1286 #region Constructor LocalSymInfo()1287 internal LocalSymInfo() 1288 { 1289 // initialize data variables 1290 m_iLocalSymCount = 0; 1291 m_iNameSpaceCount = 0; 1292 } 1293 #endregion 1294 1295 #region Private Members EnsureCapacityNamespace()1296 private void EnsureCapacityNamespace() 1297 { 1298 if (m_iNameSpaceCount == 0) 1299 { 1300 m_namespace = new String[InitialSize]; 1301 } 1302 else if (m_iNameSpaceCount == m_namespace.Length) 1303 { 1304 String [] strTemp = new String [checked(m_iNameSpaceCount * 2)]; 1305 Array.Copy(m_namespace, strTemp, m_iNameSpaceCount); 1306 m_namespace = strTemp; 1307 } 1308 } 1309 EnsureCapacity()1310 private void EnsureCapacity() 1311 { 1312 if (m_iLocalSymCount == 0) 1313 { 1314 // First time. Allocate the arrays. 1315 m_strName = new String[InitialSize]; 1316 m_ubSignature = new byte[InitialSize][]; 1317 m_iLocalSlot = new int[InitialSize]; 1318 m_iStartOffset = new int[InitialSize]; 1319 m_iEndOffset = new int[InitialSize]; 1320 } 1321 else if (m_iLocalSymCount == m_strName.Length) 1322 { 1323 // the arrays are full. Enlarge the arrays 1324 // why aren't we just using lists here? 1325 int newSize = checked(m_iLocalSymCount * 2); 1326 int[] temp = new int [newSize]; 1327 Array.Copy(m_iLocalSlot, temp, m_iLocalSymCount); 1328 m_iLocalSlot = temp; 1329 1330 temp = new int [newSize]; 1331 Array.Copy(m_iStartOffset, temp, m_iLocalSymCount); 1332 m_iStartOffset = temp; 1333 1334 temp = new int [newSize]; 1335 Array.Copy(m_iEndOffset, temp, m_iLocalSymCount); 1336 m_iEndOffset = temp; 1337 1338 String [] strTemp = new String [newSize]; 1339 Array.Copy(m_strName, strTemp, m_iLocalSymCount); 1340 m_strName = strTemp; 1341 1342 byte[][] ubTemp = new byte[newSize][]; 1343 Array.Copy(m_ubSignature, ubTemp, m_iLocalSymCount); 1344 m_ubSignature = ubTemp; 1345 1346 } 1347 } 1348 1349 #endregion 1350 1351 #region Internal Members AddLocalSymInfo(String strName,byte[] signature,int slot,int startOffset,int endOffset)1352 internal void AddLocalSymInfo(String strName,byte[] signature,int slot,int startOffset,int endOffset) 1353 { 1354 // make sure that arrays are large enough to hold addition info 1355 EnsureCapacity(); 1356 m_iStartOffset[m_iLocalSymCount] = startOffset; 1357 m_iEndOffset[m_iLocalSymCount] = endOffset; 1358 m_iLocalSlot[m_iLocalSymCount] = slot; 1359 m_strName[m_iLocalSymCount] = strName; 1360 m_ubSignature[m_iLocalSymCount] = signature; 1361 checked {m_iLocalSymCount++; } 1362 } 1363 AddUsingNamespace(String strNamespace)1364 internal void AddUsingNamespace(String strNamespace) 1365 { 1366 EnsureCapacityNamespace(); 1367 m_namespace[m_iNameSpaceCount] = strNamespace; 1368 checked { m_iNameSpaceCount++; } 1369 } 1370 1371 #if FEATURE_CORECLR 1372 [System.Security.SecurityCritical] // auto-generated 1373 #endif EmitLocalSymInfo(ISymbolWriter symWriter)1374 internal virtual void EmitLocalSymInfo(ISymbolWriter symWriter) 1375 { 1376 int i; 1377 1378 for (i = 0; i < m_iLocalSymCount; i ++) 1379 { 1380 symWriter.DefineLocalVariable( 1381 m_strName[i], 1382 FieldAttributes.PrivateScope, 1383 m_ubSignature[i], 1384 SymAddressKind.ILOffset, 1385 m_iLocalSlot[i], 1386 0, // addr2 is not used yet 1387 0, // addr3 is not used 1388 m_iStartOffset[i], 1389 m_iEndOffset[i]); 1390 } 1391 for (i = 0; i < m_iNameSpaceCount; i ++) 1392 { 1393 symWriter.UsingNamespace(m_namespace[i]); 1394 } 1395 } 1396 1397 #endregion 1398 } 1399 #endif 1400 1401 /// <summary> 1402 /// Describes exception handler in a method body. 1403 /// </summary> 1404 [StructLayout(LayoutKind.Sequential)] 1405 [ComVisible(false)] 1406 public struct ExceptionHandler : IEquatable<ExceptionHandler> 1407 { 1408 // Keep in sync with unmanged structure. 1409 internal readonly int m_exceptionClass; 1410 internal readonly int m_tryStartOffset; 1411 internal readonly int m_tryEndOffset; 1412 internal readonly int m_filterOffset; 1413 internal readonly int m_handlerStartOffset; 1414 internal readonly int m_handlerEndOffset; 1415 internal readonly ExceptionHandlingClauseOptions m_kind; 1416 1417 public int ExceptionTypeToken 1418 { 1419 get { return m_exceptionClass; } 1420 } 1421 1422 public int TryOffset 1423 { 1424 get { return m_tryStartOffset; } 1425 } 1426 1427 public int TryLength 1428 { 1429 get { return m_tryEndOffset - m_tryStartOffset; } 1430 } 1431 1432 public int FilterOffset 1433 { 1434 get { return m_filterOffset; } 1435 } 1436 1437 public int HandlerOffset 1438 { 1439 get { return m_handlerStartOffset; } 1440 } 1441 1442 public int HandlerLength 1443 { 1444 get { return m_handlerEndOffset - m_handlerStartOffset; } 1445 } 1446 1447 public ExceptionHandlingClauseOptions Kind 1448 { 1449 get { return m_kind; } 1450 } 1451 1452 #region Constructors 1453 1454 /// <summary> 1455 /// Creates a description of an exception handler. 1456 /// </summary> 1457 /// <param name="tryOffset">The offset of the first instruction protected by this handler.</param> 1458 /// <param name="tryLength">The number of bytes protected by this handler.</param> 1459 /// <param name="filterOffset">The filter code begins at the specified offset and ends at the first instruction of the handler block. Specify 0 if not applicable (this is not a filter handler).</param> 1460 /// <param name="handlerOffset">The offset of the first instruction of this handler.</param> 1461 /// <param name="handlerLength">The number of bytes of the handler.</param> 1462 /// <param name="kind">The kind of handler, the handler might be a catch handler, filter handler, fault handler, or finally handler.</param> 1463 /// <param name="exceptionTypeToken">The token of the exception type handled by this handler. Specify 0 if not applicable (this is finally handler).</param> 1464 /// <exception cref="ArgumentOutOfRangeException"> 1465 /// Some of the instruction offset is negative, 1466 /// the end offset of specified range is less than its start offset, 1467 /// or <paramref name="kind"/> has an invalid value. 1468 /// </exception> ExceptionHandlerSystem.Reflection.Emit.ExceptionHandler1469 public ExceptionHandler(int tryOffset, int tryLength, int filterOffset, int handlerOffset, int handlerLength, 1470 ExceptionHandlingClauseOptions kind, int exceptionTypeToken) 1471 { 1472 if (tryOffset < 0) 1473 { 1474 throw new ArgumentOutOfRangeException("tryOffset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 1475 } 1476 1477 if (tryLength < 0) 1478 { 1479 throw new ArgumentOutOfRangeException("tryLength", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 1480 } 1481 1482 if (filterOffset < 0) 1483 { 1484 throw new ArgumentOutOfRangeException("filterOffset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 1485 } 1486 1487 if (handlerOffset < 0) 1488 { 1489 throw new ArgumentOutOfRangeException("handlerOffset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 1490 } 1491 1492 if (handlerLength < 0) 1493 { 1494 throw new ArgumentOutOfRangeException("handlerLength", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 1495 } 1496 1497 if ((long)tryOffset + tryLength > Int32.MaxValue) 1498 { 1499 throw new ArgumentOutOfRangeException("tryLength", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, Int32.MaxValue - tryOffset)); 1500 } 1501 1502 if ((long)handlerOffset + handlerLength > Int32.MaxValue) 1503 { 1504 throw new ArgumentOutOfRangeException("handlerLength", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, Int32.MaxValue - handlerOffset)); 1505 } 1506 1507 // Other tokens migth also be invalid. We only check nil tokens as the implementation (SectEH_Emit in corhlpr.cpp) requires it, 1508 // and we can't check for valid tokens until the module is baked. 1509 if (kind == ExceptionHandlingClauseOptions.Clause && (exceptionTypeToken & 0x00FFFFFF) == 0) 1510 { 1511 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeToken", exceptionTypeToken), "exceptionTypeToken"); 1512 } 1513 1514 Contract.EndContractBlock(); 1515 1516 if (!IsValidKind(kind)) 1517 { 1518 throw new ArgumentOutOfRangeException("kind", Environment.GetResourceString("ArgumentOutOfRange_Enum")); 1519 } 1520 1521 m_tryStartOffset = tryOffset; 1522 m_tryEndOffset = tryOffset + tryLength; 1523 m_filterOffset = filterOffset; 1524 m_handlerStartOffset = handlerOffset; 1525 m_handlerEndOffset = handlerOffset + handlerLength; 1526 m_kind = kind; 1527 m_exceptionClass = exceptionTypeToken; 1528 } 1529 ExceptionHandlerSystem.Reflection.Emit.ExceptionHandler1530 internal ExceptionHandler(int tryStartOffset, int tryEndOffset, int filterOffset, int handlerStartOffset, int handlerEndOffset, 1531 int kind, int exceptionTypeToken) 1532 { 1533 Contract.Assert(tryStartOffset >= 0); 1534 Contract.Assert(tryEndOffset >= 0); 1535 Contract.Assert(filterOffset >= 0); 1536 Contract.Assert(handlerStartOffset >= 0); 1537 Contract.Assert(handlerEndOffset >= 0); 1538 Contract.Assert(IsValidKind((ExceptionHandlingClauseOptions)kind)); 1539 Contract.Assert(kind != (int)ExceptionHandlingClauseOptions.Clause || (exceptionTypeToken & 0x00FFFFFF) != 0); 1540 1541 m_tryStartOffset = tryStartOffset; 1542 m_tryEndOffset = tryEndOffset; 1543 m_filterOffset = filterOffset; 1544 m_handlerStartOffset = handlerStartOffset; 1545 m_handlerEndOffset = handlerEndOffset; 1546 m_kind = (ExceptionHandlingClauseOptions)kind; 1547 m_exceptionClass = exceptionTypeToken; 1548 } 1549 IsValidKindSystem.Reflection.Emit.ExceptionHandler1550 private static bool IsValidKind(ExceptionHandlingClauseOptions kind) 1551 { 1552 switch (kind) 1553 { 1554 case ExceptionHandlingClauseOptions.Clause: 1555 case ExceptionHandlingClauseOptions.Filter: 1556 case ExceptionHandlingClauseOptions.Finally: 1557 case ExceptionHandlingClauseOptions.Fault: 1558 return true; 1559 1560 default: 1561 return false; 1562 } 1563 } 1564 1565 #endregion 1566 1567 #region Equality 1568 GetHashCodeSystem.Reflection.Emit.ExceptionHandler1569 public override int GetHashCode() 1570 { 1571 return m_exceptionClass ^ m_tryStartOffset ^ m_tryEndOffset ^ m_filterOffset ^ m_handlerStartOffset ^ m_handlerEndOffset ^ (int)m_kind; 1572 } 1573 EqualsSystem.Reflection.Emit.ExceptionHandler1574 public override bool Equals(Object obj) 1575 { 1576 return obj is ExceptionHandler && Equals((ExceptionHandler)obj); 1577 } 1578 EqualsSystem.Reflection.Emit.ExceptionHandler1579 public bool Equals(ExceptionHandler other) 1580 { 1581 return 1582 other.m_exceptionClass == m_exceptionClass && 1583 other.m_tryStartOffset == m_tryStartOffset && 1584 other.m_tryEndOffset == m_tryEndOffset && 1585 other.m_filterOffset == m_filterOffset && 1586 other.m_handlerStartOffset == m_handlerStartOffset && 1587 other.m_handlerEndOffset == m_handlerEndOffset && 1588 other.m_kind == m_kind; 1589 } 1590 operator ==System.Reflection.Emit.ExceptionHandler1591 public static bool operator ==(ExceptionHandler left, ExceptionHandler right) 1592 { 1593 return left.Equals(right); 1594 } 1595 operator !=System.Reflection.Emit.ExceptionHandler1596 public static bool operator !=(ExceptionHandler left, ExceptionHandler right) 1597 { 1598 return !left.Equals(right); 1599 } 1600 1601 #endregion 1602 } 1603 } 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614