Esempio n. 1
0
        internal void Encode(DebugInfoBlob blob)
        {
            blob.WriteDWORD(Timestamp);
            blob.WriteDWORD(AssemblyIndex & 0x7FFFFFFF | (HasPDB ? 0x80000000 : 0));
            blob.WriteBuffer(VersionInfo, 0, VersionInfoLength);

            string nameWithPublicKey = Name;

            if (PublicKey != null && PublicKey.Length > 0)
            {
                nameWithPublicKey += ", PublicKey=";
                nameWithPublicKey += BitConverter.ToString(PublicKey).Replace("-", "");
            }
            blob.WriteString(nameWithPublicKey);
            blob.AlignToDWORD();
        }
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            // This node does not trigger generation of other nodes.
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this }));
            }

            ObjectDataBuilder objDataBuilder = new ObjectDataBuilder(factory, relocsOnly);

            // Emit number of dictionaries in table
            objDataBuilder.AddSymbol(this);
            IReadOnlyCollection <GenericDictionaryNode> dictionariesEmitted = factory.MetadataManager.GetCompiledGenericDictionaries();

            objDataBuilder.EmitInt(dictionariesEmitted.Count);
            DebugInfoBlob signatureData = new DebugInfoBlob();

            BlobBuilder          signatureBlobBuilder = new BlobBuilder();
            BlobBuilder          signatureLenBuilder  = new BlobBuilder();
            ManagedBinaryEmitter pseudoAssembly       = factory.WindowsDebugData.DebugPseudoAssemblySection.PseudoAssembly;

            foreach (GenericDictionaryNode dictionary in dictionariesEmitted)
            {
                objDataBuilder.EmitReloc(dictionary, RelocType.IMAGE_REL_BASED_ADDR32NB);
                objDataBuilder.EmitUInt(signatureData.Size());

                signatureBlobBuilder.Clear();

                int typeDictLen   = dictionary.TypeInstantiation.IsNull ? 0 : dictionary.TypeInstantiation.Length;
                int methodDictLen = dictionary.MethodInstantiation.IsNull ? 0 : dictionary.MethodInstantiation.Length;
                signatureBlobBuilder.WriteCompressedInteger(typeDictLen + methodDictLen);

                if (typeDictLen != 0)
                {
                    foreach (TypeDesc type in dictionary.TypeInstantiation)
                    {
                        pseudoAssembly.EncodeSignatureForType(type, signatureBlobBuilder);
                    }
                }

                if (methodDictLen != 0)
                {
                    foreach (TypeDesc type in dictionary.MethodInstantiation)
                    {
                        pseudoAssembly.EncodeSignatureForType(type, signatureBlobBuilder);
                    }
                }

                int blobSize = signatureBlobBuilder.Count;

                signatureLenBuilder.Clear();
                signatureLenBuilder.WriteCompressedInteger(blobSize);

                // Prepend the signature data with a length
                signatureData.WriteBuffer(signatureLenBuilder);
                // And then attach the actual signature data
                signatureData.WriteBuffer(signatureBlobBuilder);
            }

            // Attach signature information to end after all of the rva/offset pairs
            objDataBuilder.EmitBytes(signatureData.ToArray());

            return(objDataBuilder.ToObjectData());
        }
Esempio n. 3
0
        //
        // returns the DEBUG_S_FUNC_MDTOKEN_MAP subsection as a byte array
        // DEBUG_S_FUNC_MDTOKEN_MAP subsection contains method RVA to mdToken mapping
        //
        // contents of subsection:
        // offset 0,     4   bytes: count of entries in the map
        // offset 4,     8*N bytes: 4 byte RVA + 4 byte 'offset' relative to the start of 'method data'
        // offset 4+8*N, *   bytes: all method data packed sequentially with no padding. method data consists of
        //                          1 byte 'count' of generic parameters, 3 bytes of method's rid and 'count'
        //                          variable sized ECMA formatted TypeSpec signatures for each generic parameter
        //
        // Compiler places the CTLToken (for a method) or the lexical funclet order (if a method has 1 or more funclets),
        // which binder uses to compute the RVA.
        //
        // all entries are sorted by 'offset' field.
        //
        // 'offset' optimization: if the method has no generic parameters, we don't need to pass in a signature
        //                        and can encode the mdToken of method in 'offset'
        //                        We do this by setting the high bit of 'offset' and then storing rid part of
        //                        token in last 3 bytes of 'offset'
        //
        internal DebugInfoBlob GetDebugMethodRVAToTokenMap(ManagedBinaryEmitter pseudoAssembly, IEnumerable <IMethodBodyNode> emittedMethods, out List <Relocation> debugRelocations)
        {
            DebugInfoBlob methodRVAToTokenMap = new DebugInfoBlob();
            DebugInfoBlob methodDataBlob      = new DebugInfoBlob();

            debugRelocations = new List <Relocation>();
            BlobBuilder blobBuilder = new BlobBuilder();

            uint entryCount = 0;

            methodRVAToTokenMap.WriteDWORD(0); // Placeholder for count of entries in map. Will be udpated later.

            List <EmittedMethodWithILToken> tokenInOffsetEntries = new List <EmittedMethodWithILToken>();

            foreach (IMethodBodyNode emitted in emittedMethods)
            {
                if (!(emitted.Method.GetTypicalMethodDefinition() is Internal.TypeSystem.Ecma.EcmaMethod))
                {
                    continue;
                }

                EntityHandle methodHandle = pseudoAssembly.EmitMetadataHandleForTypeSystemEntity(emitted.Method.GetTypicalMethodDefinition());
                Debug.Assert(methodHandle.Kind == HandleKind.MemberReference);
                uint methodToken    = (uint)MetadataTokens.GetToken(methodHandle);
                uint methodTokenRid = methodToken & 0xFFFFFF;

                if (!(emitted.Method.HasInstantiation || emitted.Method.OwningType.HasInstantiation))
                {
                    tokenInOffsetEntries.Add(new EmittedMethodWithILToken(emitted, methodTokenRid));
                    continue;
                }

                uint cGenericArguments = checked ((uint)emitted.Method.Instantiation.Length + (uint)emitted.Method.OwningType.Instantiation.Length);

                // Debugger format does not allow the debugging of methods that have more than 255 generic parameters (spread between the type and method instantiation)
                if (cGenericArguments > 0xFF)
                {
                    continue;
                }

                blobBuilder.Clear();

                // write the signature for each generic parameter of class
                foreach (TypeDesc instantiationType in emitted.Method.OwningType.Instantiation)
                {
                    pseudoAssembly.EncodeSignatureForType(instantiationType, blobBuilder);
                }

                // write the signature for each generic parameter of the method
                foreach (TypeDesc instantiationType in emitted.Method.Instantiation)
                {
                    pseudoAssembly.EncodeSignatureForType(instantiationType, blobBuilder);
                }

                Add_DEBUG_S_FUNC_MDTOKEN_MAP_Entry(methodRVAToTokenMap, debugRelocations, emitted, methodDataBlob.Size(), ref entryCount);

                methodDataBlob.WriteDWORD(cGenericArguments << 24 | methodTokenRid);
                methodDataBlob.WriteBuffer(blobBuilder);
            }

            // sort tokenInOffsetEntries based on tokenInOffset
            tokenInOffsetEntries.Sort();

            foreach (EmittedMethodWithILToken emitted in tokenInOffsetEntries)
            {
                Add_DEBUG_S_FUNC_MDTOKEN_MAP_Entry(methodRVAToTokenMap, debugRelocations, emitted.EmittedMethod, emitted.IlTokenRid | 0x80000000, ref entryCount);
            }

            methodRVAToTokenMap.SetDWORDAtBlobIndex(0, entryCount); // // Update placeholder for count of entries in map
            methodRVAToTokenMap.WriteBuffer(methodDataBlob);

            return(methodRVAToTokenMap);
        }
Esempio n. 4
0
        // returns the DEBUG_S_TYPE_MDTOKEN_MAP subsection as a byte array
        // DEBUG_S_TYPE_MDTOKEN_MAP subsection contains type-index to mdToken mapping
        //
        // contents of subsection:
        // offset 0,     4   bytes: count of entries in the map
        // offset 4,     8*N bytes: 4 byte type-index + 4 byte 'offset' relative to the start of 'type data'
        // offset 4+8*N, *   bytes: ECMA formatted type signature packed sequentially with no padding
        //
        // 'offset' optimization: for type signatures with size<= 4-bytes
        //                        we can store the signature in offset field such that
        //                        offset = (1 << 31) | (sig[0] << 24 | sig[1] << 16 | sig[2] << 8 | sig[3])
        //                        We chose this bit encoding because sig[0] holds the CorElementType whose
        //                        highest bit is always 0 and the highest bit of offset can be used as a flag
        //                        to indicate that it is not an offset but the signature itself.
        //
        // all entries are sorted by 'offset' field and so offset-based entries are arranged before other
        // (raw-signature) entries (since raw-signature entries are of the form 0x80000000 | signature, and will always be
        // numerically bigger than the offset)
        //
        private DebugInfoBlob GetDebugTypeIndexToTokenMap(ManagedBinaryEmitter pseudoAssembly, ICollection <KeyValuePair <TypeDesc, uint> > completeKnownTypes)
        {
            DebugInfoBlob typeDataBlob            = new DebugInfoBlob();
            DebugInfoBlob typeIndexToTokenMapBlob = new DebugInfoBlob();
            List <KeyValuePair <uint, uint> > sigInOffsetEntries = new List <KeyValuePair <uint, uint> >();

            typeIndexToTokenMapBlob.WriteDWORD(checked ((uint)completeKnownTypes.Count));
            BlobBuilder blobBuilder = new BlobBuilder();

            foreach (var entry in completeKnownTypes)
            {
                uint typeIndex = entry.Value;
                blobBuilder.Clear();
                pseudoAssembly.EncodeSignatureForType(entry.Key, blobBuilder);

                // if signature fits in 4-bytes, store it in sigInOffsetEntries
                // otherwise store it in the type-data blob
                if (blobBuilder.Count <= 4)
                {
                    uint sigInOffset = 0x80000000;
                    int  i           = 0;

                    // This is a slightly confusing approach, but this is how one iterates through the bytes in a blobBuilder without flattening it to a byte[]
                    foreach (Blob blob in blobBuilder.GetBlobs())
                    {
                        foreach (byte b in blob.GetBytes())
                        {
                            sigInOffset |= ((uint)b) << (8 * (3 - i));
                            i++;
                        }
                    }

                    // sigInOffsetEntries will be later sorted and appended to typeIndexToTokenMapBlob
                    sigInOffsetEntries.Add(new KeyValuePair <uint, uint>(typeIndex, sigInOffset));
                }
                else
                {
                    typeIndexToTokenMapBlob.WriteDWORD(typeIndex);
                    typeIndexToTokenMapBlob.WriteDWORD(typeDataBlob.Size());
                    typeDataBlob.WriteBuffer(blobBuilder);
                }
            }

            // sort sigInOffsetEntries based on sigInOffset
            sigInOffsetEntries.Sort((KeyValuePair <uint, uint> left, KeyValuePair <uint, uint> right) =>
            {
                if (left.Value < right.Value)
                {
                    return(-1);
                }
                if (left.Value == right.Value)
                {
                    return(0);
                }
                return(1);
            });

            // write the sorted sigInOffsetEntries
            foreach (KeyValuePair <uint, uint> sigInOffsetEntry in sigInOffsetEntries)
            {
                typeIndexToTokenMapBlob.WriteDWORD(sigInOffsetEntry.Key);
                typeIndexToTokenMapBlob.WriteDWORD(sigInOffsetEntry.Value);
            }

            // add typeDataBlob to the end of m_typeIndexToTokenMapBlob
            typeIndexToTokenMapBlob.WriteBuffer(typeDataBlob.ToArray());

            return(typeIndexToTokenMapBlob);
        }