Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2893_BNLR/HeuristicLab.ExtLibs/HeuristicLab.Cecil/0.9.5/Mono.Cecil-0.9.5/Mono.Cecil/Mono.Cecil.Metadata/Buffers.cs

Last change on this file was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 7.7 KB
Line 
1//
2// TableHeapBuffer.cs
3//
4// Author:
5//   Jb Evain (jbevain@gmail.com)
6//
7// Copyright (c) 2008 - 2011 Jb Evain
8//
9// Permission is hereby granted, free of charge, to any person obtaining
10// a copy of this software and associated documentation files (the
11// "Software"), to deal in the Software without restriction, including
12// without limitation the rights to use, copy, modify, merge, publish,
13// distribute, sublicense, and/or sell copies of the Software, and to
14// permit persons to whom the Software is furnished to do so, subject to
15// the following conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27//
28
29using System;
30using System.Collections.Generic;
31using System.Text;
32
33using Mono.Cecil.PE;
34
35using RVA = System.UInt32;
36
37#if !READ_ONLY
38
39namespace Mono.Cecil.Metadata {
40
41  sealed class TableHeapBuffer : HeapBuffer {
42
43    readonly ModuleDefinition module;
44    readonly MetadataBuilder metadata;
45
46    internal MetadataTable [] tables = new MetadataTable [45];
47
48    bool large_string;
49    bool large_blob;
50    readonly int [] coded_index_sizes = new int [13];
51    readonly Func<Table, int> counter;
52
53    public override bool IsEmpty {
54      get { return false; }
55    }
56
57    public TableHeapBuffer (ModuleDefinition module, MetadataBuilder metadata)
58      : base (24)
59    {
60      this.module = module;
61      this.metadata = metadata;
62      this.counter = GetTableLength;
63    }
64
65    int GetTableLength (Table table)
66    {
67      var md_table = tables [(int) table];
68      return md_table != null ? md_table.Length : 0;
69    }
70
71    public TTable GetTable<TTable> (Table table) where TTable : MetadataTable, new ()
72    {
73      var md_table = (TTable) tables [(int) table];
74      if (md_table != null)
75        return md_table;
76
77      md_table = new TTable ();
78      tables [(int) table] = md_table;
79      return md_table;
80    }
81
82    public void WriteBySize (uint value, int size)
83    {
84      if (size == 4)
85        WriteUInt32 (value);
86      else
87        WriteUInt16 ((ushort) value);
88    }
89
90    public void WriteBySize (uint value, bool large)
91    {
92      if (large)
93        WriteUInt32 (value);
94      else
95        WriteUInt16 ((ushort) value);
96    }
97
98    public void WriteString (uint @string)
99    {
100      WriteBySize (@string, large_string);
101    }
102
103    public void WriteBlob (uint blob)
104    {
105      WriteBySize (blob, large_blob);
106    }
107
108    public void WriteRID (uint rid, Table table)
109    {
110      var md_table = tables [(int) table];
111      WriteBySize (rid, md_table == null ? false : md_table.IsLarge);
112    }
113
114    int GetCodedIndexSize (CodedIndex coded_index)
115    {
116      var index = (int) coded_index;
117      var size = coded_index_sizes [index];
118      if (size != 0)
119        return size;
120
121      return coded_index_sizes [index] = coded_index.GetSize (counter);
122    }
123
124    public void WriteCodedRID (uint rid, CodedIndex coded_index)
125    {
126      WriteBySize (rid, GetCodedIndexSize (coded_index));
127    }
128
129    public void WriteTableHeap ()
130    {
131      WriteUInt32 (0);          // Reserved
132      WriteByte (GetTableHeapVersion ()); // MajorVersion
133      WriteByte (0);            // MinorVersion
134      WriteByte (GetHeapSizes ());    // HeapSizes
135      WriteByte (10);           // Reserved2
136      WriteUInt64 (GetValid ());      // Valid
137      WriteUInt64 (0x0016003301fa00);   // Sorted
138
139      WriteRowCount ();
140      WriteTables ();
141    }
142
143    void WriteRowCount ()
144    {
145      for (int i = 0; i < tables.Length; i++) {
146        var table = tables [i];
147        if (table == null || table.Length == 0)
148          continue;
149
150        WriteUInt32 ((uint) table.Length);
151      }
152    }
153
154    void WriteTables ()
155    {
156      for (int i = 0; i < tables.Length; i++) {
157        var table = tables [i];
158        if (table == null || table.Length == 0)
159          continue;
160
161        table.Write (this);
162      }
163    }
164
165    ulong GetValid ()
166    {
167      ulong valid = 0;
168
169      for (int i = 0; i < tables.Length; i++) {
170        var table = tables [i];
171        if (table == null || table.Length == 0)
172          continue;
173
174        table.Sort ();
175        valid |= (1UL << i);
176      }
177
178      return valid;
179    }
180
181    byte GetHeapSizes ()
182    {
183      byte heap_sizes = 0;
184
185      if (metadata.string_heap.IsLarge) {
186        large_string = true;
187        heap_sizes |= 0x01;
188      }
189
190      if (metadata.blob_heap.IsLarge) {
191        large_blob = true;
192        heap_sizes |= 0x04;
193      }
194
195      return heap_sizes;
196    }
197
198    byte GetTableHeapVersion ()
199    {
200      switch (module.Runtime) {
201      case TargetRuntime.Net_1_0:
202      case TargetRuntime.Net_1_1:
203        return 1;
204      default:
205        return 2;
206      }
207    }
208
209    public void FixupData (RVA data_rva)
210    {
211      var table = GetTable<FieldRVATable> (Table.FieldRVA);
212      if (table.length == 0)
213        return;
214
215      var field_idx_size = GetTable<FieldTable> (Table.Field).IsLarge ? 4 : 2;
216      var previous = this.position;
217
218      base.position = table.position;
219      for (int i = 0; i < table.length; i++) {
220        var rva = ReadUInt32 ();
221        base.position -= 4;
222        WriteUInt32 (rva + data_rva);
223        base.position += field_idx_size;
224      }
225
226      base.position = previous;
227    }
228  }
229
230  sealed class ResourceBuffer : ByteBuffer {
231
232    public ResourceBuffer ()
233      : base (0)
234    {
235    }
236
237    public uint AddResource (byte [] resource)
238    {
239      var offset = (uint) this.position;
240      WriteInt32 (resource.Length);
241      WriteBytes (resource);
242      return offset;
243    }
244  }
245
246  sealed class DataBuffer : ByteBuffer {
247
248    public DataBuffer ()
249      : base (0)
250    {
251    }
252
253    public RVA AddData (byte [] data)
254    {
255      var rva = (RVA) position;
256      WriteBytes (data);
257      return rva;
258    }
259  }
260
261  abstract class HeapBuffer : ByteBuffer {
262
263    public bool IsLarge {
264      get { return base.length > 65535; }
265    }
266
267    public abstract bool IsEmpty { get; }
268
269    protected HeapBuffer (int length)
270      : base (length)
271    {
272    }
273  }
274
275  class StringHeapBuffer : HeapBuffer {
276
277    readonly Dictionary<string, uint> strings = new Dictionary<string, uint> ();
278
279    public sealed override bool IsEmpty {
280      get { return length <= 1; }
281    }
282
283    public StringHeapBuffer ()
284      : base (1)
285    {
286      WriteByte (0);
287    }
288
289    public uint GetStringIndex (string @string)
290    {
291      uint index;
292      if (strings.TryGetValue (@string, out index))
293        return index;
294
295      index = (uint) base.position;
296      WriteString (@string);
297      strings.Add (@string, index);
298      return index;
299    }
300
301    protected virtual void WriteString (string @string)
302    {
303      WriteBytes (Encoding.UTF8.GetBytes (@string));
304      WriteByte (0);
305    }
306  }
307
308  sealed class BlobHeapBuffer : HeapBuffer {
309
310    readonly Dictionary<ByteBuffer, uint> blobs = new Dictionary<ByteBuffer, uint> (new ByteBufferEqualityComparer ());
311
312    public override bool IsEmpty {
313      get { return length <= 1; }
314    }
315
316    public BlobHeapBuffer ()
317      : base (1)
318    {
319      WriteByte (0);
320    }
321
322    public uint GetBlobIndex (ByteBuffer blob)
323    {
324      uint index;
325      if (blobs.TryGetValue (blob, out index))
326        return index;
327
328      index = (uint) base.position;
329      WriteBlob (blob);
330      blobs.Add (blob, index);
331      return index;
332    }
333
334    void WriteBlob (ByteBuffer blob)
335    {
336      WriteCompressedUInt32 ((uint) blob.length);
337      WriteBytes (blob);
338    }
339  }
340
341  sealed class UserStringHeapBuffer : StringHeapBuffer {
342
343    protected override void WriteString (string @string)
344    {
345      WriteCompressedUInt32 ((uint) @string.Length * 2 + 1);
346
347      byte special = 0;
348
349      for (int i = 0; i < @string.Length; i++) {
350        var @char = @string [i];
351        WriteUInt16 (@char);
352
353        if (special == 1)
354          continue;
355
356        if (@char < 0x20 || @char > 0x7e) {
357          if (@char > 0x7e
358            || (@char >= 0x01 && @char <= 0x08)
359            || (@char >= 0x0e && @char <= 0x1f)
360            || @char == 0x27
361            || @char == 0x2d) {
362
363            special = 1;
364          }
365        }
366      }
367
368      WriteByte (special);
369    }
370  }
371}
372
373#endif
Note: See TracBrowser for help on using the repository browser.