1 // ==++== 2 // 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // 5 // ==--== 6 //////////////////////////////////////////////////////////////////////////////// 7 //////////////////////////////////////////////////////////////////////////////// 8 // <OWNER>Microsoft</OWNER> 9 // 10 11 namespace System.Reflection.Emit { 12 using System; 13 using IList = System.Collections.IList; 14 using System.Collections.Generic; 15 using System.Reflection; 16 using System.Security; 17 using System.Diagnostics; 18 using CultureInfo = System.Globalization.CultureInfo; 19 #if !FEATURE_CORECLR 20 using ResourceWriter = System.Resources.ResourceWriter; 21 #else // FEATURE_CORECLR 22 using IResourceWriter = System.Resources.IResourceWriter; 23 #endif // !FEATURE_CORECLR 24 using System.IO; 25 using System.Runtime.Versioning; 26 using System.Diagnostics.SymbolStore; 27 using System.Diagnostics.Contracts; 28 29 // This is a package private class. This class hold all of the managed 30 // data member for AssemblyBuilder. Note that what ever data members added to 31 // this class cannot be accessed from the EE. 32 internal class AssemblyBuilderData 33 { 34 [SecurityCritical] 35 [ResourceExposure(ResourceScope.Machine)] 36 [ResourceConsumption(ResourceScope.Machine)] AssemblyBuilderData( InternalAssemblyBuilder assembly, String strAssemblyName, AssemblyBuilderAccess access, String dir)37 internal AssemblyBuilderData( 38 InternalAssemblyBuilder assembly, 39 String strAssemblyName, 40 AssemblyBuilderAccess access, 41 String dir) 42 { 43 m_assembly = assembly; 44 m_strAssemblyName = strAssemblyName; 45 m_access = access; 46 m_moduleBuilderList = new List<ModuleBuilder>(); 47 m_resWriterList = new List<ResWriterData>(); 48 49 //Init to null/0 done for you by the CLR. FXCop has spoken 50 51 if (dir == null && access != AssemblyBuilderAccess.Run) 52 m_strDir = Environment.CurrentDirectory; 53 else 54 m_strDir = dir; 55 56 m_peFileKind = PEFileKinds.Dll; 57 } 58 59 // Helper to add a dynamic module into the tracking list 60 [ResourceExposure(ResourceScope.None)] 61 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] AddModule(ModuleBuilder dynModule)62 internal void AddModule(ModuleBuilder dynModule) 63 { 64 m_moduleBuilderList.Add(dynModule); 65 } 66 67 // Helper to add a resource information into the tracking list AddResWriter(ResWriterData resData)68 internal void AddResWriter(ResWriterData resData) 69 { 70 m_resWriterList.Add(resData); 71 } 72 73 74 // Helper to track CAs to persist onto disk AddCustomAttribute(CustomAttributeBuilder customBuilder)75 internal void AddCustomAttribute(CustomAttributeBuilder customBuilder) 76 { 77 78 // make sure we have room for this CA 79 if (m_CABuilders == null) 80 { 81 m_CABuilders = new CustomAttributeBuilder[m_iInitialSize]; 82 } 83 if (m_iCABuilder == m_CABuilders.Length) 84 { 85 CustomAttributeBuilder[] tempCABuilders = new CustomAttributeBuilder[m_iCABuilder * 2]; 86 Array.Copy(m_CABuilders, tempCABuilders, m_iCABuilder); 87 m_CABuilders = tempCABuilders; 88 } 89 m_CABuilders[m_iCABuilder] = customBuilder; 90 91 m_iCABuilder++; 92 } 93 94 // Helper to track CAs to persist onto disk AddCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)95 internal void AddCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) 96 { 97 98 // make sure we have room for this CA 99 if (m_CABytes == null) 100 { 101 m_CABytes = new byte[m_iInitialSize][]; 102 m_CACons = new ConstructorInfo[m_iInitialSize]; 103 } 104 if (m_iCAs == m_CABytes.Length) 105 { 106 // enlarge the arrays 107 byte[][] temp = new byte[m_iCAs * 2][]; 108 ConstructorInfo[] tempCon = new ConstructorInfo[m_iCAs * 2]; 109 for (int i=0; i < m_iCAs; i++) 110 { 111 temp[i] = m_CABytes[i]; 112 tempCon[i] = m_CACons[i]; 113 } 114 m_CABytes = temp; 115 m_CACons = tempCon; 116 } 117 118 byte[] attrs = new byte[binaryAttribute.Length]; 119 Array.Copy(binaryAttribute, attrs, binaryAttribute.Length); 120 m_CABytes[m_iCAs] = attrs; 121 m_CACons[m_iCAs] = con; 122 m_iCAs++; 123 } 124 125 #if !FEATURE_PAL 126 // Helper to calculate unmanaged version info from Assembly's custom attributes. 127 // If DefineUnmanagedVersionInfo is called, the parameter provided will override 128 // the CA's value. 129 // 130 [System.Security.SecurityCritical] // auto-generated FillUnmanagedVersionInfo()131 internal void FillUnmanagedVersionInfo() 132 { 133 // Get the lcid set on the assembly name as default if available 134 // Note that if LCID is not avaible from neither AssemblyName or AssemblyCultureAttribute, 135 // it is default to -1 which is treated as language neutral. 136 // 137 CultureInfo locale = m_assembly.GetLocale(); 138 #if FEATURE_USE_LCID 139 if (locale != null) 140 m_nativeVersion.m_lcid = locale.LCID; 141 #endif 142 143 for (int i = 0; i < m_iCABuilder; i++) 144 { 145 // check for known attributes 146 Type conType = m_CABuilders[i].m_con.DeclaringType; 147 if (m_CABuilders[i].m_constructorArgs.Length == 0 || m_CABuilders[i].m_constructorArgs[0] == null) 148 continue; 149 150 if (conType.Equals(typeof(System.Reflection.AssemblyCopyrightAttribute))) 151 { 152 // assert that we should only have one argument for this CA and the type should 153 // be a string. 154 // 155 if (m_CABuilders[i].m_constructorArgs.Length != 1) 156 { 157 throw new ArgumentException(Environment.GetResourceString( 158 "Argument_BadCAForUnmngRSC", 159 m_CABuilders[i].m_con.ReflectedType.Name)); 160 } 161 if (m_OverrideUnmanagedVersionInfo == false) 162 { 163 m_nativeVersion.m_strCopyright = m_CABuilders[i].m_constructorArgs[0].ToString(); 164 } 165 } 166 else if (conType.Equals(typeof(System.Reflection.AssemblyTrademarkAttribute))) 167 { 168 // assert that we should only have one argument for this CA and the type should 169 // be a string. 170 // 171 if (m_CABuilders[i].m_constructorArgs.Length != 1) 172 { 173 throw new ArgumentException(Environment.GetResourceString( 174 "Argument_BadCAForUnmngRSC", 175 m_CABuilders[i].m_con.ReflectedType.Name)); 176 } 177 if (m_OverrideUnmanagedVersionInfo == false) 178 { 179 m_nativeVersion.m_strTrademark = m_CABuilders[i].m_constructorArgs[0].ToString(); 180 } 181 } 182 else if (conType.Equals(typeof(System.Reflection.AssemblyProductAttribute))) 183 { 184 if (m_OverrideUnmanagedVersionInfo == false) 185 { 186 // assert that we should only have one argument for this CA and the type should 187 // be a string. 188 // 189 m_nativeVersion.m_strProduct = m_CABuilders[i].m_constructorArgs[0].ToString(); 190 } 191 } 192 else if (conType.Equals(typeof(System.Reflection.AssemblyCompanyAttribute))) 193 { 194 if (m_CABuilders[i].m_constructorArgs.Length != 1) 195 { 196 throw new ArgumentException(Environment.GetResourceString( 197 "Argument_BadCAForUnmngRSC", 198 m_CABuilders[i].m_con.ReflectedType.Name)); 199 } 200 if (m_OverrideUnmanagedVersionInfo == false) 201 { 202 // assert that we should only have one argument for this CA and the type should 203 // be a string. 204 // 205 m_nativeVersion.m_strCompany = m_CABuilders[i].m_constructorArgs[0].ToString(); 206 } 207 } 208 else if (conType.Equals(typeof(System.Reflection.AssemblyDescriptionAttribute))) 209 { 210 if (m_CABuilders[i].m_constructorArgs.Length != 1) 211 { 212 throw new ArgumentException(Environment.GetResourceString( 213 "Argument_BadCAForUnmngRSC", 214 m_CABuilders[i].m_con.ReflectedType.Name)); 215 } 216 m_nativeVersion.m_strDescription = m_CABuilders[i].m_constructorArgs[0].ToString(); 217 } 218 else if (conType.Equals(typeof(System.Reflection.AssemblyTitleAttribute))) 219 { 220 if (m_CABuilders[i].m_constructorArgs.Length != 1) 221 { 222 throw new ArgumentException(Environment.GetResourceString( 223 "Argument_BadCAForUnmngRSC", 224 m_CABuilders[i].m_con.ReflectedType.Name)); 225 } 226 m_nativeVersion.m_strTitle = m_CABuilders[i].m_constructorArgs[0].ToString(); 227 } 228 else if (conType.Equals(typeof(System.Reflection.AssemblyInformationalVersionAttribute))) 229 { 230 if (m_CABuilders[i].m_constructorArgs.Length != 1) 231 { 232 throw new ArgumentException(Environment.GetResourceString( 233 "Argument_BadCAForUnmngRSC", 234 m_CABuilders[i].m_con.ReflectedType.Name)); 235 } 236 if (m_OverrideUnmanagedVersionInfo == false) 237 { 238 m_nativeVersion.m_strProductVersion = m_CABuilders[i].m_constructorArgs[0].ToString(); 239 } 240 } 241 else if (conType.Equals(typeof(System.Reflection.AssemblyCultureAttribute))) 242 { 243 // retrieve the LCID 244 if (m_CABuilders[i].m_constructorArgs.Length != 1) 245 { 246 throw new ArgumentException(Environment.GetResourceString( 247 "Argument_BadCAForUnmngRSC", 248 m_CABuilders[i].m_con.ReflectedType.Name)); 249 } 250 // CultureInfo attribute overrides the lcid from AssemblyName. 251 CultureInfo culture = new CultureInfo(m_CABuilders[i].m_constructorArgs[0].ToString()); 252 #if FEATURE_USE_LCID 253 m_nativeVersion.m_lcid = culture.LCID; 254 #endif 255 } 256 else if (conType.Equals(typeof(System.Reflection.AssemblyFileVersionAttribute))) 257 { 258 if (m_CABuilders[i].m_constructorArgs.Length != 1) 259 { 260 throw new ArgumentException(Environment.GetResourceString( 261 "Argument_BadCAForUnmngRSC", 262 m_CABuilders[i].m_con.ReflectedType.Name)); 263 } 264 if (m_OverrideUnmanagedVersionInfo == false) 265 { 266 m_nativeVersion.m_strFileVersion = m_CABuilders[i].m_constructorArgs[0].ToString(); 267 } 268 } 269 } 270 } 271 #endif //!FEATURE_PAL 272 273 // Helper to ensure the resource name is unique underneath assemblyBuilder CheckResNameConflict(String strNewResName)274 internal void CheckResNameConflict(String strNewResName) 275 { 276 int size = m_resWriterList.Count; 277 int i; 278 for (i = 0; i < size; i++) 279 { 280 ResWriterData resWriter = m_resWriterList[i]; 281 if (resWriter.m_strName.Equals(strNewResName)) 282 { 283 // Cannot have two resources with the same name 284 throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateResourceName")); 285 } 286 } 287 } 288 289 290 // Helper to ensure the module name is unique underneath assemblyBuilder 291 [ResourceExposure(ResourceScope.None)] 292 [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.Machine | ResourceScope.Assembly)] CheckNameConflict(String strNewModuleName)293 internal void CheckNameConflict(String strNewModuleName) 294 { 295 int size = m_moduleBuilderList.Count; 296 int i; 297 for (i = 0; i < size; i++) 298 { 299 ModuleBuilder moduleBuilder = m_moduleBuilderList[i]; 300 if (moduleBuilder.m_moduleData.m_strModuleName.Equals(strNewModuleName)) 301 { 302 // Cannot have two dynamic modules with the same name 303 throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateModuleName")); 304 } 305 } 306 307 // Right now dynamic modules can only be added to dynamic assemblies in which 308 // all modules are dynamic. Otherwise we would also need to check the static modules 309 // with this: 310 // if (m_assembly.GetModule(strNewModuleName) != null) 311 // { 312 // // Cannot have two dynamic modules with the same name 313 // throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateModuleName")); 314 // } 315 } 316 317 // Helper to ensure the type name is unique underneath assemblyBuilder CheckTypeNameConflict(String strTypeName, TypeBuilder enclosingType)318 internal void CheckTypeNameConflict(String strTypeName, TypeBuilder enclosingType) 319 { 320 BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.CheckTypeNameConflict( " + strTypeName + " )"); 321 for (int i = 0; i < m_moduleBuilderList.Count; i++) 322 { 323 ModuleBuilder curModule = m_moduleBuilderList[i]; 324 curModule.CheckTypeNameConflict(strTypeName, enclosingType); 325 } 326 327 // Right now dynamic modules can only be added to dynamic assemblies in which 328 // all modules are dynamic. Otherwise we would also need to check loaded types. 329 // We only need to make this test for non-nested types since any 330 // duplicates in nested types will be caught at the top level. 331 // if (enclosingType == null && m_assembly.GetType(strTypeName, false, false) != null) 332 // { 333 // // Cannot have two types with the same name 334 // throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateTypeName")); 335 // } 336 } 337 338 339 // Helper to ensure the file name is unique underneath assemblyBuilder. This includes 340 // modules and resources. 341 // 342 // 343 // CheckFileNameConflict(String strFileName)344 internal void CheckFileNameConflict(String strFileName) 345 { 346 int size = m_moduleBuilderList.Count; 347 int i; 348 for (i = 0; i < size; i++) 349 { 350 ModuleBuilder moduleBuilder = m_moduleBuilderList[i]; 351 if (moduleBuilder.m_moduleData.m_strFileName != null) 352 { 353 if (String.Compare(moduleBuilder.m_moduleData.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0) 354 { 355 // Cannot have two dynamic module with the same name 356 throw new ArgumentException(Environment.GetResourceString("Argument_DuplicatedFileName")); 357 } 358 } 359 } 360 size = m_resWriterList.Count; 361 for (i = 0; i < size; i++) 362 { 363 ResWriterData resWriter = m_resWriterList[i]; 364 if (resWriter.m_strFileName != null) 365 { 366 if (String.Compare(resWriter.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0) 367 { 368 // Cannot have two dynamic module with the same name 369 throw new ArgumentException(Environment.GetResourceString("Argument_DuplicatedFileName")); 370 } 371 } 372 } 373 374 } 375 376 // Helper to look up which module that assembly is supposed to be stored at 377 // 378 // 379 // FindModuleWithFileName(String strFileName)380 internal ModuleBuilder FindModuleWithFileName(String strFileName) 381 { 382 int size = m_moduleBuilderList.Count; 383 int i; 384 for (i = 0; i < size; i++) 385 { 386 ModuleBuilder moduleBuilder = m_moduleBuilderList[i]; 387 if (moduleBuilder.m_moduleData.m_strFileName != null) 388 { 389 if (String.Compare(moduleBuilder.m_moduleData.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0) 390 { 391 return moduleBuilder; 392 } 393 } 394 } 395 return null; 396 } 397 398 // Helper to look up module by name. 399 // 400 // 401 // FindModuleWithName(String strName)402 internal ModuleBuilder FindModuleWithName(String strName) 403 { 404 int size = m_moduleBuilderList.Count; 405 int i; 406 for (i = 0; i < size; i++) 407 { 408 ModuleBuilder moduleBuilder = m_moduleBuilderList[i]; 409 if (moduleBuilder.m_moduleData.m_strModuleName != null) 410 { 411 if (String.Compare(moduleBuilder.m_moduleData.m_strModuleName, strName, StringComparison.OrdinalIgnoreCase) == 0) 412 return moduleBuilder; 413 } 414 } 415 return null; 416 } 417 418 419 // add type to public COMType tracking list AddPublicComType(Type type)420 internal void AddPublicComType(Type type) 421 { 422 BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.AddPublicComType( " + type.FullName + " )"); 423 if (m_isSaved == true) 424 { 425 // assembly has been saved before! 426 throw new InvalidOperationException(Environment.GetResourceString( 427 "InvalidOperation_CannotAlterAssembly")); 428 } 429 EnsurePublicComTypeCapacity(); 430 m_publicComTypeList[m_iPublicComTypeCount] = type; 431 m_iPublicComTypeCount++; 432 } 433 434 // add security permission requests AddPermissionRequests( PermissionSet required, PermissionSet optional, PermissionSet refused)435 internal void AddPermissionRequests( 436 PermissionSet required, 437 PermissionSet optional, 438 PermissionSet refused) 439 { 440 BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.AddPermissionRequests"); 441 if (m_isSaved == true) 442 { 443 // assembly has been saved before! 444 throw new InvalidOperationException(Environment.GetResourceString( 445 "InvalidOperation_CannotAlterAssembly")); 446 } 447 m_RequiredPset = required; 448 m_OptionalPset = optional; 449 m_RefusedPset = refused; 450 } 451 EnsurePublicComTypeCapacity()452 private void EnsurePublicComTypeCapacity() 453 { 454 if (m_publicComTypeList == null) 455 { 456 m_publicComTypeList = new Type[m_iInitialSize]; 457 } 458 if (m_iPublicComTypeCount == m_publicComTypeList.Length) 459 { 460 Type[] tempTypeList = new Type[m_iPublicComTypeCount * 2]; 461 Array.Copy(m_publicComTypeList, tempTypeList, m_iPublicComTypeCount); 462 m_publicComTypeList = tempTypeList; 463 } 464 } 465 466 internal List<ModuleBuilder> m_moduleBuilderList; 467 internal List<ResWriterData> m_resWriterList; 468 internal String m_strAssemblyName; 469 internal AssemblyBuilderAccess m_access; 470 private InternalAssemblyBuilder m_assembly; 471 472 internal Type[] m_publicComTypeList; 473 internal int m_iPublicComTypeCount; 474 475 internal bool m_isSaved; 476 internal const int m_iInitialSize = 16; 477 internal String m_strDir; 478 479 // hard coding the assembly def token 480 internal const int m_tkAssembly = 0x20000001; 481 482 // Security permission requests 483 internal PermissionSet m_RequiredPset; 484 internal PermissionSet m_OptionalPset; 485 internal PermissionSet m_RefusedPset; 486 487 // tracking AssemblyDef's CAs for persistence to disk 488 internal CustomAttributeBuilder[] m_CABuilders; 489 internal int m_iCABuilder; 490 internal byte[][] m_CABytes; 491 internal ConstructorInfo[] m_CACons; 492 internal int m_iCAs; 493 internal PEFileKinds m_peFileKind; // assembly file kind 494 internal MethodInfo m_entryPointMethod; 495 internal Assembly m_ISymWrapperAssembly; 496 497 #if !FEATURE_CORECLR 498 internal ModuleBuilder m_entryPointModule; 499 #endif //!FEATURE_CORECLR 500 501 #if !FEATURE_PAL 502 // For unmanaged resources 503 internal String m_strResourceFileName; 504 internal byte[] m_resourceBytes; 505 internal NativeVersionInfo m_nativeVersion; 506 internal bool m_hasUnmanagedVersionInfo; 507 internal bool m_OverrideUnmanagedVersionInfo; 508 #endif // !FEATURE_PAL 509 510 } 511 512 513 /********************************************** 514 * 515 * Internal structure to track the list of ResourceWriter for 516 * AssemblyBuilder & ModuleBuilder. 517 * 518 **********************************************/ 519 internal class ResWriterData 520 { 521 #if FEATURE_CORECLR ResWriterData( IResourceWriter resWriter, Stream memoryStream, String strName, String strFileName, String strFullFileName, ResourceAttributes attribute)522 internal ResWriterData( 523 IResourceWriter resWriter, 524 Stream memoryStream, 525 String strName, 526 String strFileName, 527 String strFullFileName, 528 ResourceAttributes attribute) 529 { 530 m_resWriter = resWriter; 531 m_memoryStream = memoryStream; 532 m_strName = strName; 533 m_strFileName = strFileName; 534 m_strFullFileName = strFullFileName; 535 m_nextResWriter = null; 536 m_attribute = attribute; 537 } 538 #else 539 internal ResWriterData( 540 ResourceWriter resWriter, 541 Stream memoryStream, 542 String strName, 543 String strFileName, 544 String strFullFileName, 545 ResourceAttributes attribute) 546 { 547 m_resWriter = resWriter; 548 m_memoryStream = memoryStream; 549 m_strName = strName; 550 m_strFileName = strFileName; 551 m_strFullFileName = strFullFileName; 552 m_nextResWriter = null; 553 m_attribute = attribute; 554 } 555 #endif 556 #if !FEATURE_CORECLR 557 internal ResourceWriter m_resWriter; 558 #else // FEATURE_CORECLR 559 internal IResourceWriter m_resWriter; 560 #endif // !FEATURE_CORECLR 561 internal String m_strName; 562 internal String m_strFileName; 563 internal String m_strFullFileName; 564 internal Stream m_memoryStream; 565 internal ResWriterData m_nextResWriter; 566 internal ResourceAttributes m_attribute; 567 } 568 569 #if !FEATURE_PAL 570 internal class NativeVersionInfo 571 { NativeVersionInfo()572 internal NativeVersionInfo() 573 { 574 m_strDescription = null; 575 m_strCompany = null; 576 m_strTitle = null; 577 m_strCopyright = null; 578 m_strTrademark = null; 579 m_strProduct = null; 580 m_strProductVersion = null; 581 m_strFileVersion = null; 582 m_lcid = -1; 583 } 584 585 internal String m_strDescription; 586 internal String m_strCompany; 587 internal String m_strTitle; 588 internal String m_strCopyright; 589 internal String m_strTrademark; 590 internal String m_strProduct; 591 internal String m_strProductVersion; 592 internal String m_strFileVersion; 593 internal int m_lcid; 594 } 595 #endif //!FEATURE_PAL 596 597 } 598