Example #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();
        }
        private void Add_DEBUG_S_FUNC_MDTOKEN_MAP_Entry(DebugInfoBlob methodRVAToTokenMap, List <Relocation> debugRelocations, IMethodBodyNode method, uint methodDataOrOffsetToMethodData, ref uint entryCount)
        {
            debugRelocations.Add(new Relocation(RelocType.IMAGE_REL_BASED_ADDR32NB, checked ((int)methodRVAToTokenMap.Size()), method));
            methodRVAToTokenMap.WriteDWORD(0);
            methodRVAToTokenMap.WriteDWORD(methodDataOrOffsetToMethodData);
            entryCount++;

            IMethodBodyNodeWithFuncletSymbols funcletSymbolsNode = method as IMethodBodyNodeWithFuncletSymbols;

            if (funcletSymbolsNode != null)
            {
                foreach (ISymbolNode funclet in funcletSymbolsNode.FuncletSymbols)
                {
                    debugRelocations.Add(new Relocation(RelocType.IMAGE_REL_BASED_ADDR32NB, checked ((int)methodRVAToTokenMap.Size()), funclet));
                    methodRVAToTokenMap.WriteDWORD(0);
                    methodRVAToTokenMap.WriteDWORD(methodDataOrOffsetToMethodData);
                    entryCount++;
                }
            }
        }
Example #3
0
        private DebugInfoBlob ConvertToDebugInfoBlob(List <SortedDictionary <uint, int> > assemblyMethods)
        {
            DebugInfoBlob debugInfoBlob = new DebugInfoBlob();

            // version
            debugInfoBlob.WriteDWORD(0);
            // number of assemblies
            debugInfoBlob.WriteDWORD((uint)assemblyMethods.Count);
            foreach (var methods in assemblyMethods)
            {
                debugInfoBlob.WriteDWORD((uint)methods.Count);
                foreach (var method in methods)
                {
                    // method token
                    debugInfoBlob.WriteDWORD(method.Key);
                    // method info length , now it's 4
                    debugInfoBlob.WriteWORD(4);
                    // method slot
                    debugInfoBlob.WriteDWORD((uint)method.Value);
                }
            }
            return(debugInfoBlob);
        }
Example #4
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);
        }
Example #5
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);
        }