コード例 #1
0
ファイル: CILAssemblyLoader.cs プロジェクト: PlumpMath/CAM
        private FrameworkMonikerInfo GetMonikerInfoFor(String path, EmittingArguments eArgs)
        {
            FrameworkMonikerInfo fwInfo = null;
            Boolean callbackFailed      = false;

            if (eArgs.FrameworkName == null || eArgs.FrameworkVersion == null)
            {
                // Part of the target framework most likely
                String fwName, fwVersion, fwProfile;
                if (this._callbacks.TryGetFrameworkInfo(path, out fwName, out fwVersion, out fwProfile))
                {
                    callbackFailed = !this._callbacks.TryGetFrameworkMoniker(fwName, fwVersion, fwProfile, out fwInfo);
                }
            }
            else
            {
                callbackFailed = !this._callbacks.TryGetFrameworkMoniker(eArgs.FrameworkName, eArgs.FrameworkVersion, eArgs.FrameworkProfile, out fwInfo);
            }

            if (fwInfo == null)
            {
                // TODO event or something
                throw new Exception("Failed to deduce target framework for " + path + ".");
            }

            return(fwInfo);
        }
コード例 #2
0
ファイル: CILAssemblyLoader.cs プロジェクト: PlumpMath/CAM
        /// <summary>
        /// Loads a <see cref="CILModule"/> from given resource.
        /// If module from that resource is already loaded, returns that module.
        /// </summary>
        /// <param name="resource">The resource to load module from, e.g. file path.</param>
        /// <returns>A <see cref="CILModule"/> loaded from given resource.</returns>
        /// <remarks>
        /// This throws whatever exceptions the <see cref="CILAssemblyLoaderCallbacks.OpenStream"/> and <see cref="E_CIL.LoadModule(CILReflectionContext, Stream, EmittingArguments)"/> methods throw.
        /// </remarks>
        /// <exception cref="ArgumentNullException">If <paramref name="resource"/> is <c>null</c>.</exception>
        public CILModule LoadModuleFrom(String resource)
        {
            ArgumentValidator.ValidateNotNull("Resource", resource);

            resource = this._callbacks.CleanResource(resource);
            CILModule retVal;

            if (!this._allModules.TryGetValue(resource, out retVal))
            {
                Boolean           created = false;
                EmittingArguments eArgs   = null;
                lock (this._modulesLock)
                {
                    if (!this._allModules.TryGetValue(resource, out retVal))
                    {
                        retVal = this.LoadModuleAndArgs(resource, out eArgs);
                        this._allModules.Add(resource, retVal);
                        this._loadingArgs.Add(retVal, eArgs);
                        this._moduleResources.Add(retVal, resource);
                        created = true;
                    }
                }

                if (created)
                {
                    this.ModuleLoadedEvent.InvokeEventIfNotNull(evt => evt(this, new ModuleLoadedEventArgs(this, retVal, resource, eArgs)));
                }
            }
            return(retVal);
        }
コード例 #3
0
ファイル: CILAssemblyLoader.cs プロジェクト: PlumpMath/CAM
        internal ModuleLoadedEventArgs(CILAssemblyLoader loader, CILModule module, String resource, EmittingArguments eArgs)
        {
            ArgumentValidator.ValidateNotNull("Assembly loader", loader);
            ArgumentValidator.ValidateNotNull("Module", module);
            ArgumentValidator.ValidateNotEmpty("Resource", resource);
            ArgumentValidator.ValidateNotNull("Emitting arguments", eArgs);

            this._loader   = loader;
            this._module   = module;
            this._resource = resource;
            this._eArgs    = eArgs;
        }
コード例 #4
0
        internal AssemblyLoaderFromBasePath(CILReflectionContext ctx, String fwLibDirectory, Func <String, Stream> streamOpener, String corLibName)
        {
            ArgumentValidator.ValidateNotNull("Reflection context", ctx);
            ArgumentValidator.ValidateNotNull("Assembly directory", fwLibDirectory);
            ArgumentValidator.ValidateNotNull("Stream opener callback", streamOpener);

            if (corLibName == null)
            {
                corLibName = Consts.MSCORLIB_NAME;
            }

            this._ctx = ctx;
            this._loadedAssemblies     = new ConcurrentDictionary <String, CILAssembly>();
            this._portableLibDirectory = fwLibDirectory; // fwLibDirectory.EndsWith( "\\" ) ? fwLibDirectory : ( fwLibDirectory + "\\" );
            this._streamOpener         = streamOpener;
            this._loadArgs             = EmittingArguments.CreateForLoadingModule(this.LoadFunction);
            this._loadArgs.CorLibName  = corLibName;
        }
コード例 #5
0
 private static void CheckEmittingArgs(
     EmittingArguments eArgs,
     out Boolean isPE64,
     out Boolean hasRelocations,
     out UInt32 numSections,
     out UInt16 peOptionalHeaderSize,
     out UInt32 iatSize
     )
 {
     if (eArgs.FileAlignment < MIN_FILE_ALIGNMENT)
     {
         eArgs.FileAlignment = MIN_FILE_ALIGNMENT;
     }
     else
     {
         eArgs.FileAlignment = FLP2(eArgs.FileAlignment);
     }
     if (eArgs.ImageBase < IMAGE_BASE_MULTIPLE)
     {
         eArgs.ImageBase = IMAGE_BASE_MULTIPLE;
     }
     else
     {
         eArgs.ImageBase -= eArgs.ImageBase % IMAGE_BASE_MULTIPLE;
     }
     if (eArgs.SectionAlignment <= eArgs.FileAlignment)
     {
         throw new ArgumentException("Section alignment " + eArgs.SectionAlignment + " must be greater than file alignment " + eArgs.FileAlignment + ".");
     }
     isPE64               = eArgs.Machine.RequiresPE64();
     hasRelocations       = eArgs.Machine.RequiresRelocations();
     numSections          = isPE64 ? 1u : 2u;                                            // TODO resource-section
     peOptionalHeaderSize = isPE64 ? HeaderFieldOffsetsAndLengths.PE_OPTIONAL_HEADER_SIZE_64 : HeaderFieldOffsetsAndLengths.PE_OPTIONAL_HEADER_SIZE_32;
     iatSize              = hasRelocations ? HeaderFieldOffsetsAndLengths.IAT_SIZE : 0u; // No Import tables if no relocations
     if (!isPE64)
     {
         eArgs.ImageBase    = CheckValueFor32PE(eArgs.ImageBase);
         eArgs.StackReserve = CheckValueFor32PE(eArgs.StackReserve);
         eArgs.StackCommit  = CheckValueFor32PE(eArgs.StackCommit);
         eArgs.HeapReserve  = CheckValueFor32PE(eArgs.HeapReserve);
         eArgs.HeapCommit   = CheckValueFor32PE(eArgs.HeapCommit);
     }
 }
コード例 #6
0
ファイル: CILAssemblyLoader.cs プロジェクト: PlumpMath/CAM
        private CILModule LoadModuleAndArgs(String path, out EmittingArguments eArgs)
        {
            eArgs          = EmittingArguments.CreateForLoadingModule(this.LoadLibAssembly);
            eArgs.LazyLoad = true; // Just to make sure - it is important to be set as true, otherwise we load things too soon.

            CILModule module;

            using (var fs = this._callbacks.OpenStream(path))
            {
                module = this._ctx.LoadModule(fs, eArgs);
            }

            var fwInfo = this.GetMonikerInfoFor(path, eArgs);

            eArgs.CorLibName = fwInfo.MsCorLibAssembly;
            var corLibVersion = fwInfo.Assemblies[eArgs.CorLibName].Item1;

            eArgs.CorLibMajor    = (UInt16)corLibVersion.Major;
            eArgs.CorLibMinor    = (UInt16)corLibVersion.Minor;
            eArgs.CorLibBuild    = (UInt16)corLibVersion.Build;
            eArgs.CorLibRevision = (UInt16)corLibVersion.Revision;

            return(module);
        }
コード例 #7
0
    /// <summary>
    /// Loads a new instance of <see cref="CILModule"/> with a contents from <paramref name="stream"/>.
    /// Useful for multi-module assemblies when one doesn't want to load whole assembly.
    /// </summary>
    /// <param name="ctx">The current <see cref="CILReflectionContext"/>.</param>
    /// <param name="stream">The stream to load module from.</param>
    /// <param name="eArgs">The <see cref="EmittingArguments"/> during loading. After successful module load, the additional information about the module will be available in this object.</param>
    /// <returns>A new instance of <see cref="CILModule"/> form the contents of the <paramref name="stream"/>.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="ctx"/> or <paramref name="stream"/> or <paramref name="eArgs"/> is <c>null</c>.</exception>
    /// <exception cref="BadImageFormatException">If the headers or metadata section of the stream has invalid values, or stream contents are otherwise malformed.</exception>
    /// <remarks>
    /// If the module returned by this method is main module, that is, its <c>Assembly</c> table has exactly one row, then the <see cref="EmittingArguments.ModuleAssemblyLoader"/> callback of <paramref name="eArgs"/> will never be used.
    /// Therefore it is ok to pass <c>null</c> as the callback to <paramref name="eArgs"/> if the caller is certain the module will always be the main module.
    /// However, when the module is not the main module, the callback will be used.
    /// If in that situation the callback is <c>null</c>, <see cref="InvalidOperationException"/> is thrown.
    /// The callback may be invoked only by accessing the <see cref="CILModule.Assembly"/> property of the returned <see cref="CILModule"/>.
    /// </remarks>
    public static CILModule LoadModule(this CILReflectionContext ctx, Stream stream, EmittingArguments eArgs)
    {
        ModuleReader mr = null; MetaDataReader md = null;
        var          ownerAssembly = eArgs.ModuleAssemblyLoader;
        var          result        = LoadModule((CILReflectionContextImpl)ctx, stream, eArgs, mod =>
        {
            CILAssemblyImpl ass;
            if (md.assembly.Length == 1)
            {
                ass = LoadAssembly((CILReflectionContextImpl)ctx, null, eArgs, mr, md, mod);
            }
            else
            {
                if (ownerAssembly == null)
                {
                    throw new InvalidOperationException("The callback to get assembly of this module was not provided.");
                }
                ass      = (CILAssemblyImpl)ownerAssembly(mod);
                var mods = ass.InternalModules;
                lock (mods.Lock)
                {
                    if (!mods.Value.CQ.Contains(mod))
                    {
                        mods.Value.Add(mod);
                    }
                }
            }
            return(ass);
        }, out mr, out md);

        if (!eArgs.LazyLoad)
        {
            ForceLoadModule(result);
        }
        return(result);
    }
コード例 #8
0
 /// <summary>
 /// Performs the emitting of the associated <see cref="CILModule"/> to <paramref name="stream"/>. See ECMA specification for more information about various PE and CLR header fields.
 /// </summary>
 /// <param name="module">The module to emit.</param>
 /// <param name="stream">The stream to emit the associated <see cref="CILModule"/> to.</param>
 /// <param name="emittingArgs">The <see cref="EmittingArguments"/>.</param>
 /// <exception cref="ArgumentNullException">
 /// If <paramref name="module"/>, <paramref name="stream"/> or <see cref="EmittingArguments.MetaDataVersion"/> of <paramref name="emittingArgs"/> is <c>null</c>.
 /// Also if any of <see cref="EmittingArguments.CorLibName"/>, <see cref="EmittingArguments.ImportHintName"/> or <see cref="EmittingArguments.ImportDirectoryName"/> of <paramref name="emittingArgs"/> is used and is <c>null</c>.
 /// </exception>
 public static void EmitModule(this CILModule module, Stream stream, EmittingArguments emittingArgs)
 {
     new ModuleWriter(module)
     .PerformEmitting(stream, emittingArgs);
 }
コード例 #9
0
 private static EmittingArguments CreateDefaultEmittingArguments()
 {
     return(EmittingArguments.CreateForEmittingDLL(null, ImageFileMachine.I386, TargetRuntime.Net_4_0));
 }
コード例 #10
0
        public void PerformEmitting(
            Stream sink,
            EmittingArguments eArgs
            )
        {
            ArgumentValidator.ValidateNotNull("Stream", sink);
            ArgumentValidator.ValidateNotNull("Emitting arguments", eArgs);

            Boolean isPE64, hasRelocations;
            UInt16  peOptionalHeaderSize;
            UInt32  numSections, iatSize;

            CheckEmittingArgs(eArgs, out isPE64, out hasRelocations, out numSections, out peOptionalHeaderSize, out iatSize);

            var fAlign         = eArgs.FileAlignment;
            var sAlign         = eArgs.SectionAlignment;
            var importHintName = eArgs.ImportHintName;
            var imageBase      = eArgs.ImageBase;
            var moduleKind     = eArgs.ModuleKind;
            var strongName     = eArgs.StrongName;

            IList <CILMethodBase> allMethodDefs;
            CILAssemblyName       an;

            using (var md = new MetaDataWriter(eArgs, this._context, this._module, eArgs.AssemblyMapper, out allMethodDefs, out an))
            {
                var clrEntryPointToken = 0;
                if (eArgs.CLREntryPoint != null)
                {
                    var listIdx = allMethodDefs.IndexOf(eArgs.CLREntryPoint);
                    if (listIdx < 0)
                    {
                        throw new ArgumentException("Entry point method " + eArgs.CLREntryPoint + " is not from this module (" + this._module.Name + ").");
                    }
                    clrEntryPointToken = TokenUtils.EncodeToken(Tables.MethodDef, listIdx + 1);
                }

                // Start emitting headers
                // MS-DOS header
                var currentArray = new Byte[HeaderFieldOffsetsAndLengths.DOS_HEADER_AND_PE_SIG.Length];
                Array.Copy(HeaderFieldOffsetsAndLengths.DOS_HEADER_AND_PE_SIG, currentArray, HeaderFieldOffsetsAndLengths.DOS_HEADER_AND_PE_SIG.Length);
                sink.Write(currentArray);

                // PE file header
                currentArray = new Byte[HeaderFieldOffsetsAndLengths.PE_FILE_HEADER_SIZE];
                var characteristics = HeaderFieldPossibleValues.IMAGE_FILE_EXECUTABLE_IMAGE | (isPE64 ? HeaderFieldPossibleValues.IMAGE_FILE_LARGE_ADDRESS_AWARE : HeaderFieldPossibleValues.IMAGE_FILE_32BIT_MACHINE);
                if (moduleKind.IsDLL())
                {
                    characteristics |= HeaderFieldPossibleValues.IMAGE_FILE_DLL;
                }
                var idx = 0;
                currentArray
                .WriteUInt16LEToBytes(ref idx, (UInt16)eArgs.Machine)
                .WriteUInt16LEToBytes(ref idx, (UInt16)numSections)
                .WriteInt32LEToBytes(ref idx, Convert.ToInt32(DateTime.Now.Subtract(PE_HEADER_START_TIME).TotalSeconds))
                .Skip(ref idx, 8)
                .WriteUInt16LEToBytes(ref idx, peOptionalHeaderSize)
                .WriteInt16LEToBytes(ref idx, (Int16)characteristics);
                sink.Write(currentArray);

                // PE optional header + section headers + padding + IAT + CLI header + Strong signature
                var codeSectionVirtualOffset = sAlign;
                // Strong name signature

                var           useStrongName = strongName != null;
                var           snSize        = 0u;
                var           snRVA         = 0u;
                var           snPadding     = 0u;
                var           delaySign     = eArgs.DelaySign || (!useStrongName && !an.PublicKey.IsNullOrEmpty());
                RSAParameters rParams;
                var           signingAlgorithm = AssemblyHashAlgorithm.SHA1;
                if (useStrongName || delaySign)
                {
                    // Set appropriate module flags
                    eArgs.ModuleFlags |= ModuleFlags.StrongNameSigned;

                    // Check algorithm override
                    var algoOverride           = eArgs.SigningAlgorithm;
                    var algoOverrideWasInvalid = algoOverride.HasValue && (algoOverride.Value == AssemblyHashAlgorithm.MD5 || algoOverride.Value == AssemblyHashAlgorithm.None);
                    if (algoOverrideWasInvalid)
                    {
                        algoOverride = AssemblyHashAlgorithm.SHA1;
                    }

                    Byte[] pkToProcess;
                    if ((useStrongName && strongName.ContainerName != null) || (!useStrongName && delaySign))
                    {
                        if (an.PublicKey.IsNullOrEmpty())
                        {
                            an.PublicKey = this._context.ExtractPublicKeyFromCSP(strongName.ContainerName);
                        }
                        pkToProcess = an.PublicKey;
                    }
                    else
                    {
                        // Get public key from BLOB
                        pkToProcess = strongName.KeyPair.ToArray();
                    }

                    // Create RSA parameters and process public key so that it will have proper, full format.
                    Byte[] pk;
                    rParams      = CryptoUtils.CreateSigningInformationFromKeyBLOB(pkToProcess, algoOverride, out pk, out signingAlgorithm);
                    an.PublicKey = pk;
                    snSize       = (UInt32)rParams.Modulus.Length;
                }
                else
                {
                    rParams = default(RSAParameters);
                }

                if (useStrongName || delaySign)
                {
                    snRVA = codeSectionVirtualOffset + iatSize + HeaderFieldOffsetsAndLengths.CLI_HEADER_SIZE;
                    if (snSize <= 32)
                    {
                        // The "Standard Public Key", ECMA-335 p. 116
                        // It is replaced by the runtime with 128 bytes key
                        snSize = 128;
                    }
                    snPadding = BitUtils.MultipleOf4(snSize) - snSize;
                }

                var revisitableOffset    = HeaderFieldOffsetsAndLengths.DOS_HEADER_AND_PE_SIG.Length + currentArray.Length;
                var revisitableArraySize = fAlign + iatSize + HeaderFieldOffsetsAndLengths.CLI_HEADER_SIZE - revisitableOffset;
                // Cheat a bit - skip now, and re-visit it after all other emitting is done
                sink.Seek(revisitableArraySize + snSize + snPadding, SeekOrigin.Current);

                // First section
                // Start with method ILs
                // Current offset within section
                var currentOffset = iatSize + snSize + snPadding + HeaderFieldOffsetsAndLengths.CLI_HEADER_SIZE;
                var methodRVAs    = new Dictionary <CILMethodBase, UInt32>(allMethodDefs.Count);


                foreach (var method in allMethodDefs)
                {
                    if (method.HasILMethodBody())
                    {
                        Boolean isTiny;
                        var     array = new MethodILWriter(this._context, md, method, eArgs.AssemblyMapper)
                                        .PerformEmitting(currentOffset, out isTiny);
                        if (!isTiny)
                        {
                            sink.SkipToNextAlignment(ref currentOffset, 4);
                        }
                        methodRVAs.Add(method, codeSectionVirtualOffset + currentOffset);
                        sink.Write(array);
                        currentOffset += (UInt32)array.Length;
                    }
                }

                // Write padding
                sink.SkipToNextAlignment(ref currentOffset, isPE64 ? 0x10u : 0x04u);

                // Write manifest resources here
                var mRes     = this._module.ManifestResources;
                var mResInfo = new Dictionary <String, UInt32>();
                var mResRVA  = mRes.Values.Any(mr => mr is EmbeddedManifestResource) ?
                               codeSectionVirtualOffset + currentOffset :
                               0u;
                var mResSize = 0u;
                if (mResRVA > 0u)
                {
                    var tmpArray = new Byte[4];
                    foreach (var kvp in mRes)
                    {
                        if (kvp.Value is EmbeddedManifestResource)
                        {
                            var data = ((EmbeddedManifestResource)kvp.Value).Data;
                            if (data != null && data.Length > 0)
                            {
                                mResInfo.Add(kvp.Key, mResSize);
                                tmpArray.WriteInt32LEToBytesNoRef(0, data.Length);
                                sink.Write(tmpArray);
                                sink.Write(data);
                                mResSize += 4 + (UInt32)data.Length;
                            }
                        }
                    }

                    // Write padding
                    currentOffset += mResSize;
                    sink.SkipToNextAlignment(ref currentOffset, isPE64 ? 0x10u : 0x04u);
                }
                // Finalize & write metadata
                var    mdRVA = codeSectionVirtualOffset + currentOffset;
                UInt32 addedToOffsetBeforeMD;
                var    mdSize = md.WriteMetaData(sink, mdRVA, eArgs, methodRVAs, mResInfo, out addedToOffsetBeforeMD);
                mdRVA         += addedToOffsetBeforeMD;
                currentOffset += mdSize + addedToOffsetBeforeMD;

                // Pad
                sink.SkipToNextAlignment(ref currentOffset, 0x4);

                // Write debug header if present
                var dbgInfo = eArgs.DebugInformation;
                var dbgRVA  = 0u;
                if (dbgInfo != null)
                {
                    dbgRVA = codeSectionVirtualOffset + currentOffset;
                    var dbgData = dbgInfo.DebugData;
                    currentArray = new Byte[MetaDataConstants.DEBUG_DD_SIZE + dbgData.Length];
                    idx          = 0;
                    currentArray
                    .WriteInt32LEToBytes(ref idx, dbgInfo.Characteristics)
                    .WriteInt32LEToBytes(ref idx, dbgInfo.Timestamp)
                    .WriteInt16LEToBytes(ref idx, dbgInfo.VersionMajor)
                    .WriteInt16LEToBytes(ref idx, dbgInfo.VersionMinor)
                    .WriteInt32LEToBytes(ref idx, MetaDataConstants.CODE_VIEW_DEBUG_TYPE)
                    .WriteInt32LEToBytes(ref idx, dbgData.Length)
                    .WriteUInt32LEToBytes(ref idx, dbgRVA + MetaDataConstants.DEBUG_DD_SIZE)
                    .WriteUInt32LEToBytes(ref idx, fAlign + currentOffset + (UInt32)idx + 4)  // Pointer to data, end Debug Data Directory
                    .BlockCopyFrom(ref idx, dbgData);
                    sink.Write(currentArray);
                    currentOffset += (UInt32)currentArray.Length;
                    sink.SkipToNextAlignment(ref currentOffset, 0x4);
                }


                var entryPointCodeRVA   = 0u;
                var importDirectoryRVA  = 0u;
                var importDirectorySize = 0u;
                var hnRVA = 0u;
                if (hasRelocations)
                {
                    // TODO write all of these in a single array
                    // Import Directory
                    // First, the table
                    importDirectoryRVA  = codeSectionVirtualOffset + currentOffset;
                    importDirectorySize = HeaderFieldOffsetsAndLengths.IMPORT_DIRECTORY_SIZE;
                    currentArray        = new Byte[importDirectorySize];
                    idx = 0;
                    currentArray
                    .WriteUInt32LEToBytes(ref idx, codeSectionVirtualOffset + currentOffset + (UInt32)currentArray.Length)                                                                                                                               // RVA of the ILT
                    .WriteInt32LEToBytes(ref idx, 0)                                                                                                                                                                                                     // DateTimeStamp
                    .WriteInt32LEToBytes(ref idx, 0)                                                                                                                                                                                                     // ForwarderChain
                    .WriteUInt32LEToBytes(ref idx, codeSectionVirtualOffset + currentOffset + (UInt32)currentArray.Length + HeaderFieldOffsetsAndLengths.ILT_SIZE + HeaderFieldOffsetsAndLengths.HINT_NAME_MIN_SIZE + (UInt32)importHintName.Length + 1) // RVA of Import Directory name (mscoree.dll)
                    .WriteUInt32LEToBytes(ref idx, codeSectionVirtualOffset);                                                                                                                                                                            // RVA of Import Address Table
                    // The rest are zeroes
                    sink.Write(currentArray);
                    currentOffset += (UInt32)currentArray.Length;

                    // ILT
                    currentArray = new Byte[HeaderFieldOffsetsAndLengths.ILT_SIZE];
                    idx          = 0;
                    currentArray
                    .WriteUInt32LEToBytes(ref idx, codeSectionVirtualOffset + currentOffset + (UInt32)currentArray.Length);  // RVA of the hint/name table
                    // The rest are zeroes
                    sink.Write(currentArray);
                    currentOffset += (UInt32)currentArray.Length;

                    // Hint/Name table
                    currentArray = new Byte[HeaderFieldOffsetsAndLengths.HINT_NAME_MIN_SIZE + importHintName.Length + 1];
                    hnRVA        = currentOffset + codeSectionVirtualOffset;
                    // Skip first two bytes
                    idx = HeaderFieldOffsetsAndLengths.HINT_NAME_MIN_SIZE;
                    currentArray.WriteASCIIString(ref idx, importHintName, true);
                    sink.Write(currentArray);
                    currentOffset += (UInt32)currentArray.Length;

                    // Import DirectoryName
                    foreach (var chr in eArgs.ImportDirectoryName)
                    {
                        sink.WriteByte((Byte)chr); // TODO properly ASCII-encoded string
                        ++currentOffset;
                    }
                    sink.WriteByte(0); // String-terminating null
                    ++currentOffset;

                    // Then, a zero int
                    // TODO investigate if this is really needed...
                    sink.SeekFromCurrent(sizeof(Int32));
                    currentOffset += sizeof(Int32);

                    // Then, a PE entrypoint
                    entryPointCodeRVA = currentOffset + codeSectionVirtualOffset;
                    currentArray      = new Byte[sizeof(Int16) + sizeof(Int32)];
                    idx = 0;
                    currentArray
                    .WriteInt16LEToBytes(ref idx, eArgs.EntryPointInstruction)
                    .WriteUInt32LEToBytes(ref idx, (UInt32)imageBase + codeSectionVirtualOffset);
                    sink.Write(currentArray);
                    currentOffset += (UInt32)currentArray.Length;
                }

                // TODO Win32 resources section
                var hasResourceSection = false;

                var textSectionInfo = new SectionInfo(sink, null, currentOffset, sAlign, fAlign, !hasRelocations && !hasResourceSection);
                var prevSectionInfo = textSectionInfo;

                // TODO Win32 resources section
                var rsrcSectionInfo = new SectionInfo();

                // Final section - relocation section
                var relocSectionInfo = new SectionInfo();
                if (hasRelocations)
                {
                    // Need to build relocation fixup for the argument of the entry point
                    currentOffset = 0;
                    var relocRVA = entryPointCodeRVA + 2;
                    var pageRVA  = relocRVA & ~(RELOCATION_PAGE_SIZE - 1);

                    currentArray = new Byte[HeaderFieldOffsetsAndLengths.RELOC_ARRAY_BASE_SIZE];
                    idx          = 0;
                    currentArray
                    .WriteUInt32LEToBytes(ref idx, pageRVA)
                    .WriteUInt32LEToBytes(ref idx, HeaderFieldOffsetsAndLengths.RELOC_ARRAY_BASE_SIZE)  // Block size
                    .WriteUInt32LEToBytes(ref idx, (RELOCATION_FIXUP_TYPE << 12) + relocRVA - pageRVA); // Type (high 4 bits) + Offset (lower 12 bits) + dummy entry (16 bits)
                    sink.Write(currentArray);
                    currentOffset += (UInt32)currentArray.Length;

                    relocSectionInfo = new SectionInfo(sink, prevSectionInfo, currentOffset, sAlign, fAlign, true);
                    prevSectionInfo  = relocSectionInfo;
                }

                // Revisit PE optional header + section headers + padding + IAT + CLI header
                currentArray = new Byte[revisitableArraySize];
                idx          = 0;
                // PE optional header, ECMA-335 pp. 279-281
                // Standard fields
                currentArray
                .WriteInt16LEToBytes(ref idx, isPE64 ? HeaderFieldPossibleValues.PE64 : HeaderFieldPossibleValues.PE32) // Magic
                .WriteByteToBytes(ref idx, eArgs.LinkerMajor)                                                           // Linker major version
                .WriteByteToBytes(ref idx, eArgs.LinkerMinor)                                                           // Linker minor version
                .WriteUInt32LEToBytes(ref idx, textSectionInfo.rawSize)                                                 // Code size
                .WriteUInt32LEToBytes(ref idx, relocSectionInfo.rawSize + rsrcSectionInfo.rawSize)                      // Initialized data size
                .WriteUInt32LEToBytes(ref idx, 0)                                                                       // Unitialized data size
                .WriteUInt32LEToBytes(ref idx, entryPointCodeRVA)                                                       // Entry point RVA
                .WriteUInt32LEToBytes(ref idx, textSectionInfo.virtualAddress);                                         // Base of code
                if (!isPE64)
                {
                    currentArray.WriteUInt32LEToBytes(ref idx, hasResourceSection ? rsrcSectionInfo.virtualAddress : relocSectionInfo.virtualAddress); // Base of data
                }
                // WinNT-specific fields
                var dllFlags = DLLFlags.TerminalServerAware | DLLFlags.NXCompatible | DLLFlags.NoSEH | DLLFlags.DynamicBase;
                if (eArgs.HighEntropyVA)
                {
                    dllFlags |= DLLFlags.HighEntropyVA;
                }
                (isPE64 ? currentArray.WriteUInt64LEToBytes(ref idx, imageBase) : currentArray.WriteUInt32LEToBytes(ref idx, (UInt32)imageBase))
                .WriteUInt32LEToBytes(ref idx, sAlign)                                                                                    // Section alignment
                .WriteUInt32LEToBytes(ref idx, fAlign)                                                                                    // File alignment
                .WriteUInt16LEToBytes(ref idx, eArgs.OSMajor)                                                                             // OS Major
                .WriteUInt16LEToBytes(ref idx, eArgs.OSMinor)                                                                             // OS Minor
                .WriteUInt16LEToBytes(ref idx, eArgs.UserMajor)                                                                           // User Major
                .WriteUInt16LEToBytes(ref idx, eArgs.UserMinor)                                                                           // User Minor
                .WriteUInt16LEToBytes(ref idx, eArgs.SubSysMajor)                                                                         // SubSys Major
                .WriteUInt16LEToBytes(ref idx, eArgs.SubSysMinor)                                                                         // SubSys Minor
                .WriteUInt32LEToBytes(ref idx, 0)                                                                                         // Reserved
                .WriteUInt32LEToBytes(ref idx, prevSectionInfo.virtualAddress + BitUtils.MultipleOf(sAlign, prevSectionInfo.virtualSize)) // Image Size
                .WriteUInt32LEToBytes(ref idx, textSectionInfo.rawPointer)                                                                // Header Size
                .WriteUInt32LEToBytes(ref idx, 0)                                                                                         // File Checksum
                .WriteUInt16LEToBytes(ref idx, GetSubSystem(moduleKind))                                                                  // SubSystem
                .WriteUInt16LEToBytes(ref idx, (UInt16)dllFlags);                                                                         // DLL Characteristics
                if (isPE64)
                {
                    currentArray
                    .WriteUInt64LEToBytes(ref idx, eArgs.StackReserve) // Stack Reserve Size
                    .WriteUInt64LEToBytes(ref idx, eArgs.StackCommit)  // Stack Commit Size
                    .WriteUInt64LEToBytes(ref idx, eArgs.HeapReserve)  // Heap Reserve Size
                    .WriteUInt64LEToBytes(ref idx, eArgs.HeapCommit);  // Heap Commit Size
                }
                else
                {
                    currentArray
                    .WriteUInt32LEToBytes(ref idx, (UInt32)eArgs.StackReserve) // Stack Reserve Size
                    .WriteUInt32LEToBytes(ref idx, (UInt32)eArgs.StackCommit)  // Stack Commit Size
                    .WriteUInt32LEToBytes(ref idx, (UInt32)eArgs.HeapReserve)  // Heap Reserve Size
                    .WriteUInt32LEToBytes(ref idx, (UInt32)eArgs.HeapCommit);  // Heap Commit Size
                }
                currentArray
                .WriteUInt32LEToBytes(ref idx, 0)  // Loader Flags
                .WriteUInt32LEToBytes(ref idx, HeaderFieldOffsetsAndLengths.NUMBER_OF_DATA_DIRS)
                // Data Directories
                .WriteZeroDataDirectory(ref idx)                                                                               // Export Table
                .WriteDataDirectory(ref idx, importDirectoryRVA, importDirectorySize)                                          // Import Table
                .WriteDataDirectory(ref idx, rsrcSectionInfo.virtualAddress, rsrcSectionInfo.virtualSize)                      // Resource Table
                .WriteZeroDataDirectory(ref idx)                                                                               // Exception Table
                .WriteZeroDataDirectory(ref idx)                                                                               // Certificate Table
                .WriteDataDirectory(ref idx, relocSectionInfo.virtualAddress, relocSectionInfo.virtualSize)                    // BaseRelocationTable
                .WriteDataDirectory(ref idx, dbgRVA > 0u ? dbgRVA : 0u, dbgRVA > 0u ? MetaDataConstants.DEBUG_DD_SIZE : 0u)    // Debug Table
                .WriteZeroDataDirectory(ref idx)                                                                               // Copyright Table
                .WriteZeroDataDirectory(ref idx)                                                                               // Global Ptr
                .WriteZeroDataDirectory(ref idx)                                                                               // TLS Table
                .WriteZeroDataDirectory(ref idx)                                                                               // Load Config Table
                .WriteZeroDataDirectory(ref idx)                                                                               // Bound Import
                .WriteDataDirectory(ref idx, iatSize == 0 ? 0 : codeSectionVirtualOffset, iatSize == 0 ? 0 : iatSize)          // IAT
                .WriteZeroDataDirectory(ref idx)                                                                               // Delay Import Descriptor
                .WriteDataDirectory(ref idx, codeSectionVirtualOffset + iatSize, HeaderFieldOffsetsAndLengths.CLI_HEADER_SIZE) // CLI Header
                .WriteZeroDataDirectory(ref idx)                                                                               // Reserved
                // Section headers
                .WriteSectionInfo(ref idx, textSectionInfo, CODE_SECTION_NAME, HeaderFieldPossibleValues.MEM_READ | HeaderFieldPossibleValues.MEM_EXECUTE | HeaderFieldPossibleValues.CONTAINS_CODE)
                .WriteSectionInfo(ref idx, rsrcSectionInfo, RESOURCE_SECTION_NAME, HeaderFieldPossibleValues.MEM_READ | HeaderFieldPossibleValues.CONTAINS_INITIALIZED_DATA)
                .WriteSectionInfo(ref idx, relocSectionInfo, RELOCATION_SECTION_NAME, HeaderFieldPossibleValues.MEM_READ | HeaderFieldPossibleValues.MEM_DISCARDABLE | HeaderFieldPossibleValues.CONTAINS_INITIALIZED_DATA);
                var headersSize = (UInt32)(revisitableOffset + idx);

                // Skip to beginning of .text section
                currentArray.Skip(ref idx, (Int32)(fAlign - (UInt32)revisitableOffset - idx));

                // Write IAT if needed
                if (hasRelocations)
                {
                    currentArray
                    .WriteUInt32LEToBytes(ref idx, hnRVA)
                    .WriteUInt32LEToBytes(ref idx, 0);
                }
                // CLI Header, ECMA-335, p. 283
                // At the moment, the 32BitRequired flag must be specified as well, if 32BitPreferred flag is specified.
                // This is for backwards compatibility.
                // Actually, since CorFlags lets specify Preferred32Bit separately, allow this to do too.
                var moduleFlags = eArgs.ModuleFlags;
                //if ( moduleFlags.HasFlag( ModuleFlags.Preferred32Bit ) )
                //{
                //   moduleFlags |= ModuleFlags.Required32Bit;
                //}
                currentArray
                .WriteUInt32LEToBytes(ref idx, HeaderFieldOffsetsAndLengths.CLI_HEADER_SIZE) // Cb
                .WriteUInt16LEToBytes(ref idx, eArgs.CLIMajor)                               // MajorRuntimeVersion
                .WriteUInt16LEToBytes(ref idx, eArgs.CLIMinor)                               // MinorRuntimeVersion
                .WriteDataDirectory(ref idx, mdRVA, mdSize)                                  // MetaData
                .WriteInt32LEToBytes(ref idx, (Int32)moduleFlags)                            // Flags
                .WriteInt32LEToBytes(ref idx, clrEntryPointToken)                            // EntryPointToken
                .WriteDataDirectory(ref idx, mResRVA, mResSize);                             // Resources
                var snDataDirOffset = revisitableOffset + idx;
                currentArray
                .WriteDataDirectory(ref idx, snRVA, snSize) // StrongNameSignature
                .WriteZeroDataDirectory(ref idx)            // CodeManagerTable
                .WriteZeroDataDirectory(ref idx)            // VTableFixups
                .WriteZeroDataDirectory(ref idx)            // ExportAddressTableJumps
                .WriteZeroDataDirectory(ref idx);           // ManagedNativeHeader
#if DEBUG
                if (idx != currentArray.Length)
                {
                    throw new Exception("Something went wrong when emitting file headers. Emitted " + idx + " bytes, but was supposed to emit " + currentArray.Length + " bytes.");
                }
#endif
                sink.Seek(revisitableOffset, SeekOrigin.Begin);
                sink.Write(currentArray);

                if (useStrongName || delaySign)
                {
                    if (!delaySign)
                    {
                        // Try create RSA first
                        var rsaArgs = strongName.ContainerName == null ? new RSACreationEventArgs(rParams) : new RSACreationEventArgs(strongName.ContainerName);
                        this._context.LaunchRSACreationEvent(rsaArgs);
                        using (var rsa = rsaArgs.RSA)
                        {
                            var           buffer = new Byte[MetaDataConstants.STREAM_COPY_BUFFER_SIZE];
                            Func <Stream> hashStream; Func <Byte[]> hashGetter; IDisposable transform;
                            this._context.LaunchHashStreamEvent(signingAlgorithm, out hashStream, out hashGetter, out transform);

                            RSASignatureCreationEventArgs sigArgs;
                            using (var tf = transform)
                            {
                                using (var cryptoStream = hashStream())
                                {
                                    // Calculate hash of required parts of file (ECMA-335, p.117)
                                    sink.Seek(0, SeekOrigin.Begin);
                                    sink.CopyStreamPart(cryptoStream, buffer, headersSize);

                                    sink.Seek(fAlign, SeekOrigin.Begin);
                                    sink.CopyStreamPart(cryptoStream, buffer, snRVA - codeSectionVirtualOffset);

                                    sink.Seek(snSize + snPadding, SeekOrigin.Current);
                                    sink.CopyStream(cryptoStream, buffer);
                                }
                                sigArgs = new RSASignatureCreationEventArgs(rsa, signingAlgorithm, hashGetter());
                            }


                            this._context.LaunchRSASignatureCreationEvent(sigArgs);
                            var strongNameArray = sigArgs.Signature;
                            if (snSize != strongNameArray.Length)
                            {
                                throw new CryptographicException("Calculated and actual strong name size differ (calculated: " + snSize + ", actual: " + strongNameArray.Length + ").");
                            }
                            Array.Reverse(strongNameArray);

                            // Write strong name
                            sink.Seek(snRVA - codeSectionVirtualOffset + fAlign, SeekOrigin.Begin);
                            sink.Write(strongNameArray);
                        }
                    }

                    currentArray = new Byte[8];
                    idx          = 0;
                    currentArray.WriteDataDirectory(ref idx, snRVA, snSize);
                    sink.Seek(snDataDirOffset, SeekOrigin.Begin);
                    sink.Write(currentArray);
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// This method will generate the Qi4CS assemblies.
        /// </summary>
        /// <param name="projectDir">The project directory.</param>
        /// <param name="targetFWID">The target framework identifier.</param>
        /// <param name="targetFWVersion">The target framework version.</param>
        /// <param name="targetFWProfile">The target framework profile.</param>
        /// <param name="referenceAssembliesDir">The base directory where target framework assemblies reside. Should be the directory where target framework assemblies are found under subdirectory <c>&lt;framework-id&gt;\&lt;framework-version&gt;</c>, e.g. <c>".NETFramework\v4.0"</c>.</param>
        /// <param name="targetPlatform">The textual name of target platform.</param>
        /// <param name="path">The path where to store assemblies.</param>
        /// <param name="assemblySNInfo">The file containing strongname information about the assemblies to be emitted.</param>
        /// <param name="qi4CSDir">The directory where Qi4CS assemblies actually used by the application reside.</param>
        /// <param name="verify">Whether to run PEVerify on generated Qi4CS assemblies.</param>
        /// <param name="winSDKDir">The directory where the Windows SDK resides, needed to detect PEVerify executable.</param>
        public IDictionary <String, String> GenerateAssemblies(String projectDir, String targetFWID, String targetFWVersion, String targetFWProfile, String referenceAssembliesDir, String targetPlatform, String path, String assemblySNInfo, String qi4CSDir, Boolean verify, String winSDKDir)
        {
            qi4CSDir = Path.GetFullPath(qi4CSDir);
            path     = Path.GetFullPath(path);

            XElement assemblyInfo = null;

            if (!String.IsNullOrEmpty(assemblySNInfo))
            {
                try
                {
                    assemblyInfo = XElement.Load(new StringReader(assemblySNInfo));
                }
                catch (Exception exc)
                {
                    throw new Qi4CSBuildException("Invalid assembly info element " + assemblySNInfo + ".\n" + exc);
                }
            }
            Func <String, Stream> streamOpener = str => File.Open(str, FileMode.Open, FileAccess.Read, FileShare.Read);

            referenceAssembliesDir = Path.Combine(referenceAssembliesDir, targetFWID, targetFWVersion);
            if (!String.IsNullOrEmpty(targetFWProfile))
            {
                referenceAssembliesDir = Path.Combine(referenceAssembliesDir, "Profile", targetFWProfile);
            }

            String msCorLibName; String fwDisplayName; String targetFWDir;
            var    thisFWMoniker = new FrameworkMonikerInfo(targetFWID, targetFWVersion, targetFWProfile, DotNETReflectionContext.ReadAssemblyInformationFromRedistXMLFile(Path.Combine(referenceAssembliesDir, "RedistList", "FrameworkList.xml"), out msCorLibName, out fwDisplayName, out targetFWDir), msCorLibName, fwDisplayName);

            if (!String.IsNullOrEmpty(targetFWDir))
            {
                referenceAssembliesDir = targetFWDir;
            }

            if (!Directory.Exists(referenceAssembliesDir))
            {
                throw new Qi4CSBuildException("The reference assemblies directory " + referenceAssembliesDir + " does not exist.");
            }

            referenceAssembliesDir += Path.DirectorySeparatorChar;

            var isX86         = X86.Equals(targetPlatform, StringComparison.InvariantCultureIgnoreCase);
            var targetMachine = String.IsNullOrEmpty(targetPlatform) || ANYCPU.Equals(targetPlatform, StringComparison.InvariantCultureIgnoreCase) || isX86 ?
                                ImageFileMachine.I386 :
                                ImageFileMachine.AMD64; // TODO more machines
            var mFlags = ModuleFlags.ILOnly;

            if (isX86)
            {
                mFlags |= ModuleFlags.Required32Bit;
            }

            var snDic = new ConcurrentDictionary <String, Tuple <StrongNameKeyPair, AssemblyHashAlgorithm> >();

            if (assemblyInfo != null)
            {
                foreach (var elem in assemblyInfo.XPathSelectElements("assembly"))
                {
                    snDic[elem.Attribute("name").Value] = Tuple.Create(
                        SubElementTextOrFallback(elem, "sn", (XElement snElem, out StrongNameKeyPair sn) =>
                    {
                        var type = snElem.Attribute("type");
                        sn       = "container".Equals(type.Value, StringComparison.InvariantCultureIgnoreCase) ?
                                   new StrongNameKeyPair(snElem.Value) :
                                   new StrongNameKeyPair("inline".Equals(type.Value, StringComparison.InvariantCultureIgnoreCase) ? StringConversions.HexStr2ByteArray(snElem.Value) : ReadAllBytes(projectDir, snElem.Value));
                        return(true);
                    }, null),
                        SubElementAttributeOrFallback(elem, "hashAlgorithm", (String algoStr, out AssemblyHashAlgorithm algo) =>
                    {
                        return(Enum.TryParse <AssemblyHashAlgorithm>(algoStr, out algo));
                    }, AssemblyHashAlgorithm.SHA1));
                }
            }

            var runtimeRootDir = Path.GetDirectoryName(new Uri(typeof(Object).Assembly.CodeBase).LocalPath);


            var actualPath = path;
            var needToMove = verify && !String.Equals(actualPath, qi4CSDir);

            if (needToMove)
            {
                // When verifying strong-named assemblies in different location than application's out dir, the .dll.config file
                // should hold recursively all non-.NET references, which is quite complicated and maybe not even enough.
                // Instead, emit Qi4CS assemblies into out dir and move them after verifying
                actualPath = qi4CSDir;
            }

            IDictionary <System.Reflection.Assembly, String> genAssFilenames;

            try
            {
                genAssFilenames = this._modelFactory.Model.GenerateAndSaveAssemblies(
                    actualPath,
                    this.IsSilverlight,
                    (nAss, gAss) =>
                {
                    Tuple <StrongNameKeyPair, AssemblyHashAlgorithm> snTuple;
                    snDic.TryGetValue(nAss.GetName().Name, out snTuple);
                    var sn    = snTuple == null ? null : snTuple.Item1;
                    var eArgs = EmittingArguments.CreateForEmittingWithMoniker(gAss.ReflectionContext, targetMachine, TargetRuntime.Net_4_0, ModuleKind.Dll, null, runtimeRootDir, referenceAssembliesDir, streamOpener, sn, thisFWMoniker, String.Equals(thisFWMoniker.FrameworkName, PCL_FW_NAME), mFlags);

                    gAss.AddTargetFrameworkAttributeWithMonikerInfo(thisFWMoniker, eArgs.AssemblyMapper);
                    if (snTuple != null)
                    {
                        eArgs.SigningAlgorithm = snTuple.Item2;
                    }
                    return(eArgs);
                });
            }
            catch (InvalidApplicationModelException apme)
            {
                throw new Qi4CSBuildException("The Qi4CS model was not valid:\n" + apme.ValidationResult, apme);
            }

            if (verify)
            {
                try
                {
                    winSDKDir = FindWinSDKBinPath(winSDKDir);
                    foreach (var fn in genAssFilenames)
                    {
                        Verify(winSDKDir, fn.Value, snDic != null && snDic.ContainsKey(fn.Key.GetName().Name));
                    }
                }
                finally
                {
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }

                    foreach (var kvp in genAssFilenames.ToArray())
                    {
                        var fn = kvp.Value;
                        try
                        {
                            var targetFn = Path.Combine(path, Path.GetFileName(fn));
                            if (!String.Equals(fn, targetFn))
                            {
                                if (File.Exists(targetFn))
                                {
                                    try
                                    {
                                        File.Delete(targetFn);
                                    }
                                    catch
                                    {
                                        // Ignore
                                    }
                                }
                                File.Move(fn, targetFn);
                                genAssFilenames.Remove(kvp.Key);
                                genAssFilenames.Add(kvp.Key, targetFn);
                            }
                        }
                        catch
                        {
                            // Ignore
                        }
                    }
                }
            }

            return(genAssFilenames.ToDictionary(
                       kvp => kvp.Key.CodeBase,
                       kvp => kvp.Value
                       ));
        }
コード例 #12
0
ファイル: FrameworkMonikerInfo.cs プロジェクト: PlumpMath/CAM
        /// <summary>
        /// This method reads assembly information from the <c>FrameworkList.xml</c> located in reference assemblies sud-directory <c>RedistList</c>.
        /// </summary>
        /// <param name="defaultTargetFWDir">This will be the default target framework directory if XML file does not define <c>TargetFrameworkDirectory</c> attribute.</param>
        /// <param name="stream">The opened file to <c>FrameworkList.xml</c>.</param>
        /// <param name="assemblyFilenameEnumerator">The callback to enumerate all assembly files in the directory. Will be used only if assembly file list is not present in XML file.</param>
        /// <param name="ctxFactory">The callback to create a new <see cref="CILReflectionContext"/>. Will be used only if assembly file list is not present in XML file.</param>
        /// <param name="streamOpener">The callback to open assemblies in the target framework directory. Will be used only if assembly file list is not present in XML file.</param>
        /// <param name="fileExistsCheck">The callback to check for file existence. Will be used only if assembly file list is present in XML file. The first argument is target framework directory, and second argument is assembly name.</param>
        /// <param name="msCorLibName">The detected name of the assembly which acts as <c>mscorlib</c> assembly of this framework.</param>
        /// <param name="frameworkDisplayName">The detected display name of the framework.</param>
        /// <param name="targetFWDir">The detected value of target framework directory, potentially relative.</param>
        /// <returns>Assembly information persisted in the file.</returns>
        /// <exception cref="ArgumentNullException">If <paramref name="assemblyFilenameEnumerator"/> or <paramref name="ctxFactory"/> is <c>null</c>.</exception>
        /// <exception cref="InvalidDataException">If the <c>FrameworkList.xml</c> is in malformed format.</exception>
        /// <exception cref="InvalidOperationException">If the <c>FrameworkList.xml</c> does not define <c>TargetFrameworkDirectory</c> attribute and <paramref name="defaultTargetFWDir"/> is <c>null</c> or empty.</exception>
        public static IDictionary <String, Tuple <Version, Byte[]> > ReadAssemblyInformationFromRedistXMLFile(
            String defaultTargetFWDir,
            Stream stream,
            Func <String, IEnumerable <String> > assemblyFilenameEnumerator,
            Func <CILReflectionContext> ctxFactory,
            Func <String, Stream> streamOpener,
            Func <String, String, Boolean> fileExistsCheck,
            out String msCorLibName,
            out String frameworkDisplayName,
            out String targetFWDir
            )
        {
            var xmlSettings = new System.Xml.XmlReaderSettings();

            xmlSettings.CloseInput = false;

            using (var xml = System.Xml.XmlReader.Create(stream, xmlSettings))
            {
                xml.Read();
                // Move to Root and then to File-listing
                if (!xml.ReadToNextSibling("FileList"))
                {
                    throw new InvalidDataException("FrameworkList.xml seems to be in invalid format (FileList).");
                }

                frameworkDisplayName = xml.GetAttribute("Name");

                var asses = new List <Tuple <String, Version, Byte[]> >();


                targetFWDir = xml.GetAttribute("TargetFrameworkDirectory");
                if (String.IsNullOrEmpty(targetFWDir))
                {
                    // Can't trust <FileList> element children, since they contain facade assemblies as well.
                    targetFWDir = defaultTargetFWDir;
                    if (String.IsNullOrEmpty(targetFWDir))
                    {
                        throw new InvalidOperationException("Failed to resolve target framework moniker directory, as XML redistribution list file did not contain 'TargetFrameworkDirectory' attribute nor default target framework directory was specified.");
                    }
                }

                // If the <FileList> is present, we need to read the file information while checking that the file really exists
                if (xml.ReadToDescendant("File"))
                {
                    ArgumentValidator.ValidateNotNull("File existence checker", fileExistsCheck);

                    do
                    {
                        var simpleAssemblyName = xml.GetAttribute("AssemblyName");
                        if (fileExistsCheck(targetFWDir, simpleAssemblyName))
                        {
                            asses.Add(Tuple.Create(simpleAssemblyName, Version.Parse(xml.GetAttribute("Version")), StringConversions.HexStr2ByteArray(xml.GetAttribute("PublicKeyToken"))));
                        }
                    } while (xml.ReadToNextSibling("File"));
                }
                else
                {
                    // On Mono, .NETFramework assemblies are not enumerated in the FrameworkList.xml, making this process really slow
                    ArgumentValidator.ValidateNotNull("Assembly file name enumerator", assemblyFilenameEnumerator);
                    ArgumentValidator.ValidateNotNull("CIL Reflection Context factory", ctxFactory);
                    ArgumentValidator.ValidateNotNull("Stream opener", streamOpener);

                    using (var ctx = ctxFactory())
                    {
                        foreach (var fn in assemblyFilenameEnumerator(targetFWDir))
                        {
                            var eArgs = EmittingArguments.CreateForLoadingAssembly();
                            using (var curStream = streamOpener(fn))
                            {
                                try
                                {
                                    var ass = ctx.LoadAssembly(curStream, eArgs);
                                    var an  = ass.Name;
                                    asses.Add(Tuple.Create(an.Name, new Version(an.MajorVersion, an.MinorVersion, an.BuildNumber, an.Revision), ass.GetPublicKeyToken()));
                                }
                                catch
                                {
                                    // Ignore - some non-CLI files present sometimes as well here.
                                }
                            }
                        }
                    }
                }

                var result = asses.ToDictionary(t => t.Item1, t => Tuple.Create(t.Item2, t.Item3));
                msCorLibName = result.ContainsKey(Consts.NEW_MSCORLIB_NAME) ? Consts.NEW_MSCORLIB_NAME : Consts.MSCORLIB_NAME;
                return(result);
            }
        }
コード例 #13
0
ファイル: CILAssemblyLoader.cs プロジェクト: PlumpMath/CAM
 /// <summary>
 /// Tries to get <see cref="EmittingArguments"/> of a loaded module.
 /// </summary>
 /// <param name="module">The <see cref="CILModule"/> to get emitting arguments for.</param>
 /// <param name="eArgs">The emitting arguments associated with <paramref name="module"/>, if it was loaded by this <see cref="CILAssemblyLoader"/>.</param>
 /// <returns><c>true</c> if <paramref name="module"/> was loaded by this <see cref="CILAssemblyLoader"/>; <c>false</c> otherwise.</returns>
 public Boolean TryGetEmittingArgumentsFor(CILModule module, out EmittingArguments eArgs)
 {
     eArgs = null;
     return(module != null && this._loadingArgs.TryGetValue(module, out eArgs));
 }
コード例 #14
0
    private static CILAssemblyImpl LoadAssembly(CILReflectionContextImpl cctx, Stream stream, EmittingArguments eArgs, ModuleReader existingModuleReader, MetaDataReader existingMD, CILModule existingModule)
    {
        ArgumentValidator.ValidateNotNull("Reflection context", cctx);
        ArgumentValidator.ValidateNotNull("Emitting arguments", eArgs);

        var fileStreamOpener = eArgs.FileStreamOpener ?? THROW_INVALID_OPERATION;

        var moduleReader = existingModuleReader;
        var md           = existingMD;
        var thisModule   = existingModule;

        CILAssemblyImpl result = null;

        result = (CILAssemblyImpl)cctx.Cache.NewAssembly(id => new CILAssemblyImpl(
                                                             cctx,
                                                             id,
                                                             new LazyWithLock <ListProxy <CILCustomAttribute> >(() =>
        {
            // Force evaluation of module types ( to get stuff populated in module reader)
            var dummy = thisModule.DefinedTypes;
            return(moduleReader.ReadAssemblyCustomAttributes(id));
        }),
                                                             () =>
        {
            var aRow   = md.assembly[0];
            var aFlags = aRow.Item6;
            if (!aRow.Item7.IsNullOrEmpty())
            {
                aFlags |= AssemblyFlags.PublicKey;
            }
            return(new CILAssemblyName(aRow.Item8, aRow.Item2, aRow.Item3, aRow.Item4, aRow.Item5, aRow.Item1, aFlags, aRow.Item7, aRow.Item9));
        },
                                                             () =>
        {
            var list = new List <CILModule>();
            list.Add(thisModule);
            list.AddRange(md.file
                          .Where(f => f.Item1.ContainsMetadata())
                          .Select(f =>
            {
                using (var strm = fileStreamOpener(thisModule, f.Item2))
                {
                    ModuleReader mRdr;
                    MetaDataReader mdRdr;
                    return(LoadModule(cctx, strm, eArgs, mod => result, out mRdr, out mdRdr));
                }
            }));
            return(cctx.CollectionsFactory.NewListProxy(list));
        },
                                                             () => cctx.CollectionsFactory.NewDictionaryProxy(md.exportedType
                                                                                                              .Where(eRow => eRow.Item1.IsTypeForwarder() && eRow.Item5.table == Tables.AssemblyRef || eRow.Item5.table == Tables.ExportedType)
                                                                                                              .Select(eRow => moduleReader.ResolveExportedType(eRow.Item5, (TypeAttributes)eRow.Item1, eRow.Item4, eRow.Item3))
                                                                                                              .GroupBy(tf => Tuple.Create(tf.Name, tf.Namespace))
                                                                                                              .ToDictionary(g => g.Key, g => g.First())),
                                                             () => thisModule
                                                             ));

        if (thisModule == null)
        {
            thisModule = LoadModule(cctx, stream, eArgs, mod => result, out moduleReader, out md);
        }

        if (md.assembly.Length != 1)
        {
            throw new BadImageFormatException("Assembly table had " + (md.assembly.Length == 0 ? "too few" : "too many") + " rows, exactly one expected, but had " + md.assembly.Length + ".");
        }

        return(result);
    }
コード例 #15
0
    private static CILModule LoadModule(CILReflectionContextImpl cctx, Stream stream, EmittingArguments eArgs, Func <CILModule, CILAssembly> modOwnerLoader, out ModuleReader moduleReaderOut, out MetaDataReader mdOut)
    {
        ArgumentValidator.ValidateNotNull("Reflection context", cctx);
        ArgumentValidator.ValidateNotNull("Stream", stream);
        ArgumentValidator.ValidateNotNull("Emitting arguments", eArgs);

        DLLFlags       dllFlags; TargetRuntime targetRuntime;
        ModuleReader   moduleReader;
        MetaDataReader md;
        IDictionary <String, ManifestResource> mResources;

        try
        {
            moduleReaderOut = new ModuleReader(cctx, stream, eArgs, out targetRuntime, out dllFlags, out mdOut, out mResources);
            moduleReader    = moduleReaderOut;
            md = mdOut;
            eArgs.AssemblyRefs.Clear();
            foreach (var aRef in md.assemblyRef)
            {
                eArgs.AssemblyRefs.Add(new CILAssemblyName(aRef.Item7, aRef.Item1, aRef.Item2, aRef.Item3, aRef.Item4, AssemblyHashAlgorithm.None, aRef.Item5, aRef.Item6, aRef.Item8));
            }
        }
        catch (Exception x)
        {
            if (x is BadImageFormatException)
            {
                throw;
            }
            else
            {
                throw new BadImageFormatException("Exception when loading assembly (" + x + ").", x);
            }
        }

        var retVal = cctx.Cache.NewModule(mID => new CILModuleImpl(
                                              cctx,
                                              mID,
                                              new LazyWithLock <ListProxy <CILCustomAttribute> >(() =>
        {
            // Force evaluation of module types ( to get stuff populated in module reader)
            var dummy = cctx.Cache.ResolveModuleID(mID).DefinedTypes;
            return(moduleReader.ReadModuleCustomAttributes(mID));
        }),
                                              () => modOwnerLoader(cctx.Cache.ResolveModuleID(mID)),
                                              md.module[0].Item2,
                                              () => moduleReader.GetModuleInitializer(),
                                              () => moduleReader.CreateLogicalStructure(),
                                              () => moduleReader._mscorLibRef.Value,
                                              mResources
                                              ));

        moduleReader.SetThisModule(retVal);

        eArgs.SetCLREntryPoint(() =>
        {
            CILMethod epMethod;
            if (moduleReader.HasEntryPoint())
            {
                // Initialize logical structures first
                var dummy = retVal.DefinedTypes;
                // Get the CILMethod
                epMethod = moduleReader.GetEntryPoint();
            }
            else
            {
                epMethod = null;
            }
            return(epMethod);
        });
        return(retVal);
    }
コード例 #16
0
    /// <summary>
    /// Loads a new instance of <see cref="CILAssembly"/> from the contents of the <paramref name="stream"/>.
    /// </summary>
    /// <param name="ctx">The current reflection context.</param>
    /// <param name="stream">The stream to load assembly from.</param>
    /// <param name="eArgs">The <see cref="EmittingArguments"/> to be used during loading. After successful assembly load, this will contain some additional information about the loaded assembly.</param>
    /// <returns>A new instance of <see cref="CILAssembly"/> from the contents of the <paramref name="stream"/>.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="ctx"/> or <paramref name="stream"/> or <paramref name="eArgs"/> is <c>null</c>.</exception>
    /// <exception cref="BadImageFormatException">If the headers or metadata section of the stream has invalid values, or stream contents are otherwise malformed.</exception>
    public static CILAssembly LoadAssembly(this CILReflectionContext ctx, Stream stream, EmittingArguments eArgs)
    {
        var result = LoadAssembly((CILReflectionContextImpl)ctx, stream, eArgs, null, null, null);

        if (!eArgs.LazyLoad)
        {
            ForceLoadAssembly(result);
        }
        return(result);
    }