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

ThreadStaticsIndexNode.cs « DependencyAnalysis « Compiler « src « ILCompiler.Compiler « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: fbfe07f9ea41cf9a0824d09edf5e3096ad83771e (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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// 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 Internal.Text;
using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler.DependencyAnalysis
{
    // These classes defined below are Windows-specific. The VC CRT library has equivalent definition
    // for ThreadStaticsIndexNode and ThreadStaticsDirectoryNode, but it does not support cross-module
    // TLS references where the name of _tls_index_ will need to be module-sensitive. Therefore, we
    // define them here.

    // The TLS slot index allocated for this module by the OS loader. We keep a pointer to this
    // value in the module header.
    public class ThreadStaticsIndexNode : ObjectNode, IExportableSymbolNode, ISortableSymbolNode
    {
        string _prefix;

        public ThreadStaticsIndexNode(string prefix)  
        {
            _prefix = prefix;
        }

        public string MangledName
        {
            get
            {
                return GetMangledName(_prefix);
            }
        }

        public static string GetMangledName(string prefix)
        {
            return  "_tls_index_" + prefix;
        }

        public int Offset => 0;
        
        protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);

        public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
        {
            sb.Append(GetMangledName(_prefix));
        }        

        public override ObjectNodeSection Section
        {
            get
            {
                return ObjectNodeSection.DataSection;
            }
        }

        public ExportForm GetExportForm(NodeFactory factory) => ExportForm.ByName;

        public override bool IsShareable => false;            

        public override bool StaticDependenciesAreComputed => true;

        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            // TODO: define _tls_index as "comdat select any" when multiple object files present.

            ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly);
            objData.RequireInitialPointerAlignment();
            objData.AddSymbol(this);

            // Emit an aliased symbol named _tls_index for native P/Invoke code that uses TLS. This is required
            // because we do not link against libcmt.lib.
            ObjectAndOffsetSymbolNode aliasedSymbol = new ObjectAndOffsetSymbolNode(this, objData.CountBytes, "_tls_index", false);
            objData.AddSymbol(aliasedSymbol);

            // This is the TLS index field which is a 4-byte integer. 
            objData.EmitInt(0); 

            return objData.ToObjectData();
        }

        public override int ClassCode => -968500265;

        public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
        {
            return string.Compare(_prefix, ((ThreadStaticsIndexNode)other)._prefix);
        }
    }

    // The data structure used by the OS loader to load TLS chunks. 
    public class ThreadStaticsDirectoryNode : ObjectNode, ISymbolDefinitionNode
    {
        string _prefix;
        public ThreadStaticsDirectoryNode(string prefix)
        {
            _prefix = prefix;
        }

        public string MangledName
        {
            get
            {
                return GetMangledName(_prefix);
            }
        }

        public static string GetMangledName(string prefix)
        {
            return prefix + "_tls_used";
        }

        public int Offset => 0;

        protected override string GetName(NodeFactory factory) => GetMangledName("");

        public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
        {
            sb.Append(GetMangledName(_prefix));
        }

        public override ObjectNodeSection Section
        {
            get
            {
                return ObjectNodeSection.ReadOnlyDataSection;
            }
        }

        public override bool IsShareable => false;

        public override bool StaticDependenciesAreComputed => true;

        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            // TODO: define _tls_used as comdat select any when multiple object files present.
            UtcNodeFactory hostedFactory = factory as UtcNodeFactory;
            ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly);
            objData.RequireInitialPointerAlignment();
            objData.AddSymbol(this);

            // Allocate and initialize the IMAGE_TLS_DIRECTORY PE data structure used by the OS loader to determine
            // TLS allocations. The structure is defined by the OS as following:
            /*
                struct _IMAGE_TLS_DIRECTORY32
                {
                    DWORD StartAddressOfRawData;
                    DWORD EndAddressOfRawData;
                    DWORD AddressOfIndex;
                    DWORD AddressOfCallBacks;
                    DWORD SizeOfZeroFill;
                    DWORD Characteristics;
                }

                struct _IMAGE_TLS_DIRECTORY64
                {
                    ULONGLONG StartAddressOfRawData;
                    ULONGLONG EndAddressOfRawData;
                    ULONGLONG AddressOfIndex;
                    ULONGLONG AddressOfCallBacks;
                    DWORD SizeOfZeroFill;
                    DWORD Characteristics;
                }
            */
            // In order to utilize linker support, the struct variable needs to be named _tls_used
            objData.EmitPointerReloc(hostedFactory.TlsStart);     // start of tls data
            objData.EmitPointerReloc(hostedFactory.TlsEnd);     // end of tls data
            objData.EmitPointerReloc(hostedFactory.ThreadStaticsIndex);     // address of tls_index
            objData.EmitZeroPointer();          // pointer to call back array
            objData.EmitInt(0);                 // size of tls zero fill
            objData.EmitInt(0);                 // characteristics

            return objData.ToObjectData();
        }

        public override int ClassCode => -754150753;

        public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
        {
            return string.Compare(_prefix, ((ThreadStaticsDirectoryNode)other)._prefix);
        }
    }
}