Welcome to mirror list, hosted at ThFree Co, Russian Federation.

WindowsDebugMethodInfoSection.cs « DependencyAnalysis « Compiler « src « ILCompiler.Compiler « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9a8d8e765d181eb8869b15533328f363b47990dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using Internal.TypeSystem.Ecma;
using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.TypesDebugInfo;

namespace ILCompiler.DependencyAnalysis
{
    internal class WindowsDebugMethodInfoSection : ObjectNode, ISymbolDefinitionNode
    {
        private MergedAssemblyRecords _mergedAssemblies;

        public WindowsDebugMethodInfoSection(MergedAssemblyRecords mergedAssemblies)
        {
            _mergedAssemblies = mergedAssemblies;
        }

        private ObjectNodeSection _section = new ObjectNodeSection(".mdinfo", SectionType.ReadOnly);
        public override ObjectNodeSection Section => _section;

        public override bool IsShareable => false;

        public override bool StaticDependenciesAreComputed => true;

        public int Offset => 0;

        public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
        {
            sb.Append(GetName(null));
        }

        private uint AdjustIndex(uint assemblyIndex, uint corLibIndex)
        {
            if (assemblyIndex == 0x7FFFFFFF)
                return corLibIndex;
            if (assemblyIndex < corLibIndex)
                return assemblyIndex;
            return assemblyIndex + 1;
        }

        //
        // returns the DebugInfoBlob containing the method token to virtual method slot mapping

        // .mdinfo format
        // offset 0,     4   bytes: version number
        // offset 4,     4   bytes: count of assemblies
        // 
        // for each assembly
        // offset 0,     4   bytes: count of methods with a virtual method slot
        //
        // for each method 
        // offset 0,     4   bytes: method def token (as they are in the input assembly)
        // offset 4,     2   bytes: length of the per method information [ currently always 4 ]
        // offset 6,     4   bytes: virtual slot number
        // methods are sorted by their method def token

        internal DebugInfoBlob GetDebugMethodInfoMap(NodeFactory factory)
        {
            Dictionary<EcmaAssembly, uint> originalAssemblyOrder = new Dictionary<EcmaAssembly, uint>();
            List<SortedDictionary<uint, int>> moduleMethods = new List<SortedDictionary<uint, int>>();

            // re-construct orginal assembly input order
            foreach (MergedAssemblyRecord mergedAssembly in _mergedAssemblies.MergedAssemblies)
            {
                uint assemblyIndex = AdjustIndex(mergedAssembly.AssemblyIndex, _mergedAssemblies.CorLibIndex);
                originalAssemblyOrder.Add(mergedAssembly.Assembly, assemblyIndex);
                moduleMethods.Add(new SortedDictionary<uint, int>());
            }

            foreach (TypeDesc type in factory.MetadataManager.GetTypesWithConstructedEETypes())
            {
                // skip if sealed
                if (type.IsSealed())
                    continue;

                // no generic support yet 
                if (type is EcmaType)
                {
                    EcmaType ecmaType = (EcmaType)type;
                    EcmaAssembly ecmaAssembly = (EcmaAssembly)ecmaType.EcmaModule;
                    int assemblyIndex = (int)originalAssemblyOrder[ecmaAssembly];
                    SortedDictionary<uint, int> methodList = moduleMethods[assemblyIndex];
                    foreach (MethodDesc md in type.GetAllMethods())
                    {
                        // skip non-virtual and final methods
                        if (!md.IsVirtual || md.IsFinal)
                            continue;
                        // skip generic 
                        if (md.HasInstantiation)
                            continue;
                        // method token.
                        EntityHandle methodHandle = ((EcmaMethod)md).Handle;
                        uint methodToken = (uint)MetadataTokens.GetToken(methodHandle);
                        // find virtual method slot.
                        MethodDesc declaringMethodForSlot =
                            MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(md.GetTypicalMethodDefinition());
                        int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, declaringMethodForSlot, type);
                        if (slot != -1 && !methodList.ContainsKey(methodToken))
                            methodList.Add(methodToken, slot);
                    }
                }
            }
            return ConvertToDebugInfoBlob(moduleMethods);
        }

        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;
        }

        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 });
            }
            DebugInfoBlob debugData = GetDebugMethodInfoMap(factory);
            return new ObjectData(debugData.ToArray(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
        }

        protected override string GetName(NodeFactory context)
        {
            return "___DebugMethodInfoSection";
        }

        public override int ClassCode => 513099721;
    }
}