5
// Jb Evain (jbevain@gmail.com)
7
// Copyright (c) 2008 - 2010 Jb Evain
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:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
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.
30
using System.Collections.Generic;
35
using RVA = System.UInt32;
39
namespace Mono.Cecil.Metadata {
41
sealed class TableHeapBuffer : HeapBuffer {
43
readonly ModuleDefinition module;
44
readonly MetadataBuilder metadata;
46
internal MetadataTable [] tables = new MetadataTable [45];
50
readonly int [] coded_index_sizes = new int [13];
51
readonly Func<Table, int> counter;
53
public override bool IsEmpty {
57
public TableHeapBuffer (ModuleDefinition module, MetadataBuilder metadata)
61
this.metadata = metadata;
62
this.counter = GetTableLength;
65
int GetTableLength (Table table)
67
var md_table = tables [(int) table];
68
return md_table != null ? md_table.Length : 0;
71
public TTable GetTable<TTable> (Table table) where TTable : MetadataTable, new ()
73
var md_table = (TTable) tables [(int) table];
77
md_table = new TTable ();
78
tables [(int) table] = md_table;
82
public void WriteBySize (uint value, int size)
87
WriteUInt16 ((ushort) value);
90
public void WriteBySize (uint value, bool large)
95
WriteUInt16 ((ushort) value);
98
public void WriteString (uint @string)
100
WriteBySize (@string, large_string);
103
public void WriteBlob (uint blob)
105
WriteBySize (blob, large_blob);
108
public void WriteRID (uint rid, Table table)
110
var md_table = tables [(int) table];
111
WriteBySize (rid, md_table == null ? false : md_table.IsLarge);
114
int GetCodedIndexSize (CodedIndex coded_index)
116
var index = (int) coded_index;
117
var size = coded_index_sizes [index];
121
return coded_index_sizes [index] = coded_index.GetSize (counter);
124
public void WriteCodedRID (uint rid, CodedIndex coded_index)
126
WriteBySize (rid, GetCodedIndexSize (coded_index));
129
public void WriteTableHeap ()
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
143
void WriteRowCount ()
145
for (int i = 0; i < tables.Length; i++) {
146
var table = tables [i];
147
if (table == null || table.Length == 0)
150
WriteUInt32 ((uint) table.Length);
156
for (int i = 0; i < tables.Length; i++) {
157
var table = tables [i];
158
if (table == null || table.Length == 0)
169
for (int i = 0; i < tables.Length; i++) {
170
var table = tables [i];
171
if (table == null || table.Length == 0)
185
if (metadata.string_heap.IsLarge) {
190
if (metadata.blob_heap.IsLarge) {
198
byte GetTableHeapVersion ()
200
switch (module.Runtime) {
201
case TargetRuntime.Net_1_0:
202
case TargetRuntime.Net_1_1:
209
public void FixupData (RVA data_rva)
211
var table = GetTable<FieldRVATable> (Table.FieldRVA);
212
if (table.length == 0)
215
var field_idx_size = GetTable<FieldTable> (Table.Field).IsLarge ? 4 : 2;
216
var previous = this.position;
218
base.position = table.position;
219
for (int i = 0; i < table.length; i++) {
220
var rva = ReadUInt32 ();
222
WriteUInt32 (rva + data_rva);
223
base.position += field_idx_size;
226
base.position = previous;
230
sealed class ResourceBuffer : ByteBuffer {
232
public ResourceBuffer ()
237
public uint AddResource (byte [] resource)
239
var offset = (uint) this.position;
240
WriteInt32 (resource.Length);
241
WriteBytes (resource);
246
sealed class DataBuffer : ByteBuffer {
253
public RVA AddData (byte [] data)
255
var rva = (RVA) position;
261
abstract class HeapBuffer : ByteBuffer {
263
public bool IsLarge {
264
get { return base.length > 65536; }
267
public abstract bool IsEmpty { get; }
269
protected HeapBuffer (int length)
275
class StringHeapBuffer : HeapBuffer {
277
readonly Dictionary<string, uint> strings = new Dictionary<string, uint> ();
279
public sealed override bool IsEmpty {
280
get { return length <= 1; }
283
public StringHeapBuffer ()
289
public uint GetStringIndex (string @string)
292
if (strings.TryGetValue (@string, out index))
295
index = (uint) base.position;
296
WriteString (@string);
297
strings.Add (@string, index);
301
protected virtual void WriteString (string @string)
303
WriteBytes (Encoding.UTF8.GetBytes (@string));
308
sealed class BlobHeapBuffer : HeapBuffer {
310
readonly Dictionary<ByteBuffer, uint> blobs = new Dictionary<ByteBuffer, uint> (new ByteBufferEqualityComparer ());
312
public override bool IsEmpty {
313
get { return length <= 1; }
316
public BlobHeapBuffer ()
322
public uint GetBlobIndex (ByteBuffer blob)
325
if (blobs.TryGetValue (blob, out index))
328
index = (uint) base.position;
330
blobs.Add (blob, index);
334
void WriteBlob (ByteBuffer blob)
336
WriteCompressedUInt32 ((uint) blob.length);
341
sealed class UserStringHeapBuffer : StringHeapBuffer {
343
protected override void WriteString (string @string)
345
WriteCompressedUInt32 ((uint) @string.Length * 2 + 1);
349
for (int i = 0; i < @string.Length; i++) {
350
var @char = @string [i];
356
if (@char < 0x20 || @char > 0x7e) {
358
|| (@char >= 0x01 && @char <= 0x08)
359
|| (@char >= 0x0e && @char <= 0x1f)