26
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
using Mono.Collections.Generic;
34
using RVA = System.UInt32;
29
36
namespace Mono.Cecil.Cil {
32
using System.Collections;
36
using Mono.Cecil.Metadata;
37
using Mono.Cecil.Signatures;
39
sealed class CodeReader : BaseCodeVisitor {
41
ReflectionReader m_reflectReader;
43
IDictionary m_instructions;
45
public CodeReader (ReflectionReader reflectReader)
47
m_reflectReader = reflectReader;
48
m_root = m_reflectReader.MetadataRoot;
49
m_instructions = new Hashtable ();
52
public override void VisitMethodBody (MethodBody body)
54
MethodDefinition meth = body.Method;
55
MethodBody methBody = body;
56
BinaryReader br = m_reflectReader.Module.ImageReader.MetadataReader.GetDataReader (meth.RVA);
58
// lets read the method
59
int flags = br.ReadByte ();
38
sealed class CodeReader : ByteBuffer {
40
readonly internal MetadataReader reader;
45
MethodDefinition method;
49
get { return base.position - start; }
52
CodeReader (Section section, MetadataReader reader)
55
this.code_section = section;
59
public static CodeReader CreateCodeReader (MetadataReader metadata)
61
return new CodeReader (metadata.image.MetadataSection, metadata);
64
public MethodBody ReadMethodBody (MethodDefinition method)
67
this.body = new MethodBody (method);
69
reader.context = method;
76
public void MoveTo (int rva)
78
if (!IsInSection (rva)) {
79
code_section = reader.image.GetSectionAtVirtualAddress ((uint) rva);
80
Reset (code_section.Data);
83
base.position = rva - (int) code_section.VirtualAddress;
86
bool IsInSection (int rva)
88
return code_section.VirtualAddress <= rva && rva < code_section.VirtualAddress + code_section.SizeOfRawData;
91
void ReadMethodBody ()
95
var flags = ReadByte ();
60
96
switch (flags & 0x3) {
61
case (int) MethodHeader.TinyFormat :
62
methBody.CodeSize = flags >> 2;
63
methBody.MaxStack = 8;
64
ReadCilBody (methBody, br);
66
case (int) MethodHeader.FatFormat :
67
br.BaseStream.Position--;
68
int fatflags = br.ReadUInt16 ();
69
//int headersize = (fatflags >> 12) & 0xf;
70
methBody.MaxStack = br.ReadUInt16 ();
71
methBody.CodeSize = br.ReadInt32 ();
72
methBody.LocalVarToken = br.ReadInt32 ();
73
body.InitLocals = (fatflags & (int) MethodHeader.InitLocals) != 0;
74
if (methBody.LocalVarToken != 0)
75
VisitVariableDefinitionCollection (methBody.Variables);
76
ReadCilBody (methBody, br);
77
if ((fatflags & (int) MethodHeader.MoreSects) != 0)
78
ReadSection (methBody, br);
83
public static uint GetRid (int token)
85
return (uint) token & 0x00ffffff;
88
public static ParameterDefinition GetParameter (MethodBody body, int index)
90
if (body.Method.HasThis) {
92
return body.Method.This;
96
return body.Method.Parameters [index];
99
public static VariableDefinition GetVariable (MethodBody body, int index)
101
return body.Variables [index];
104
void ReadCilBody (MethodBody body, BinaryReader br)
106
long start = br.BaseStream.Position;
107
Instruction last = null;
108
m_instructions.Clear();
109
InstructionCollection code = body.Instructions;
110
GenericContext context = new GenericContext (body.Method);
112
while (br.BaseStream.Position < start + body.CodeSize) {
114
long offset = br.BaseStream.Position - start;
115
int cursor = br.ReadByte ();
117
op = OpCodes.TwoBytesOpCode [br.ReadByte ()];
98
body.code_size = flags >> 2;
99
body.MaxStackSize = 8;
107
throw new InvalidOperationException ();
110
var symbol_reader = reader.module.SymbolReader;
112
if (symbol_reader != null) {
113
var instructions = body.Instructions;
114
symbol_reader.Read (body, offset => GetInstruction (instructions, offset));
118
void ReadFatMethod ()
120
var flags = ReadUInt16 ();
121
body.max_stack_size = ReadUInt16 ();
122
body.code_size = (int) ReadUInt32 ();
123
body.local_var_token = new MetadataToken (ReadUInt32 ());
124
body.init_locals = (flags & 0x10) != 0;
126
if (body.local_var_token.RID != 0)
127
body.variables = ReadVariables (body.local_var_token);
131
if ((flags & 0x8) != 0)
135
public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token)
137
var position = reader.position;
138
var variables = reader.ReadVariables (local_var_token);
139
reader.position = position;
147
var code_size = body.code_size;
149
if (code_size < 0 || buffer.Length <= (uint) (code_size + position))
152
var end = start + code_size;
153
var instructions = body.instructions = new InstructionCollection (code_size / 3);
155
while (position < end) {
156
var offset = base.position - start;
157
var opcode = ReadOpCode ();
158
var current = new Instruction (offset, opcode);
160
if (opcode.OperandType != OperandType.InlineNone)
161
current.operand = ReadOperand (current);
163
instructions.Add (current);
166
ResolveBranches (instructions);
171
var il_opcode = ReadByte ();
172
return il_opcode != 0xfe
173
? OpCodes.OneByteOpCode [il_opcode]
174
: OpCodes.TwoBytesOpCode [ReadByte ()];
177
object ReadOperand (Instruction instruction)
179
switch (instruction.opcode.OperandType) {
180
case OperandType.InlineSwitch:
181
var length = ReadInt32 ();
182
var base_offset = Offset + (4 * length);
183
var branches = new int [length];
184
for (int i = 0; i < length; i++)
185
branches [i] = base_offset + ReadInt32 ();
187
case OperandType.ShortInlineBrTarget:
188
return ReadSByte () + Offset;
189
case OperandType.InlineBrTarget:
190
return ReadInt32 () + Offset;
191
case OperandType.ShortInlineI:
192
if (instruction.opcode == OpCodes.Ldc_I4_S)
196
case OperandType.InlineI:
198
case OperandType.ShortInlineR:
199
return ReadSingle ();
200
case OperandType.InlineR:
201
return ReadDouble ();
202
case OperandType.InlineI8:
204
case OperandType.ShortInlineVar:
205
return GetVariable (ReadByte ());
206
case OperandType.InlineVar:
207
return GetVariable (ReadUInt16 ());
208
case OperandType.ShortInlineArg:
209
return GetParameter (ReadByte ());
210
case OperandType.InlineArg:
211
return GetParameter (ReadUInt16 ());
212
case OperandType.InlineSig:
213
return GetCallSite (ReadToken ());
214
case OperandType.InlineString:
215
return GetString (ReadToken ());
216
case OperandType.InlineTok:
217
case OperandType.InlineType:
218
case OperandType.InlineMethod:
219
case OperandType.InlineField:
220
return reader.LookupToken (ReadToken ());
222
throw new NotSupportedException ();
226
public string GetString (MetadataToken token)
228
return reader.image.UserStringHeap.Read (token.RID);
231
public ParameterDefinition GetParameter (int index)
233
return body.GetParameter (index);
236
public VariableDefinition GetVariable (int index)
238
return body.GetVariable (index);
241
public CallSite GetCallSite (MetadataToken token)
243
return reader.ReadCallSite (token);
246
void ResolveBranches (Collection<Instruction> instructions)
248
var items = instructions.items;
249
var size = instructions.size;
251
for (int i = 0; i < size; i++) {
252
var instruction = items [i];
253
switch (instruction.opcode.OperandType) {
254
case OperandType.ShortInlineBrTarget:
255
case OperandType.InlineBrTarget:
256
instruction.operand = GetInstruction ((int) instruction.operand);
258
case OperandType.InlineSwitch:
259
var offsets = (int []) instruction.operand;
260
var branches = new Instruction [offsets.Length];
261
for (int j = 0; j < offsets.Length; j++)
262
branches [j] = GetInstruction (offsets [j]);
264
instruction.operand = branches;
270
Instruction GetInstruction (int offset)
272
return GetInstruction (body.Instructions, offset);
275
static Instruction GetInstruction (Collection<Instruction> instructions, int offset)
277
var size = instructions.size;
278
var items = instructions.items;
279
if (offset < 0 || offset > items [size - 1].offset)
285
int mid = min + ((max - min) / 2);
286
var instruction = items [mid];
287
var instruction_offset = instruction.offset;
289
if (offset == instruction_offset)
292
if (offset < instruction_offset)
119
op = OpCodes.OneByteOpCode [cursor];
121
Instruction instr = new Instruction ((int) offset, op);
122
switch (op.OperandType) {
123
case OperandType.InlineNone :
125
case OperandType.InlineSwitch :
126
uint length = br.ReadUInt32 ();
127
int [] branches = new int [length];
128
int [] buf = new int [length];
129
for (int i = 0; i < length; i++)
130
buf [i] = br.ReadInt32 ();
131
for (int i = 0; i < length; i++)
132
branches [i] = Convert.ToInt32 (br.BaseStream.Position - start + buf [i]);
133
instr.Operand = branches;
135
case OperandType.ShortInlineBrTarget :
136
sbyte sbrtgt = br.ReadSByte ();
137
instr.Operand = Convert.ToInt32 (br.BaseStream.Position - start + sbrtgt);
139
case OperandType.InlineBrTarget :
140
int brtgt = br.ReadInt32 ();
141
instr.Operand = Convert.ToInt32 (br.BaseStream.Position - start + brtgt);
143
case OperandType.ShortInlineI :
144
if (op == OpCodes.Ldc_I4_S)
145
instr.Operand = br.ReadSByte ();
147
instr.Operand = br.ReadByte ();
149
case OperandType.ShortInlineVar :
150
instr.Operand = GetVariable (body, br.ReadByte ());
152
case OperandType.ShortInlineParam :
153
instr.Operand = GetParameter (body, br.ReadByte ());
155
case OperandType.InlineSig :
156
instr.Operand = GetCallSiteAt (br.ReadInt32 (), context);
158
case OperandType.InlineI :
159
instr.Operand = br.ReadInt32 ();
161
case OperandType.InlineVar :
162
instr.Operand = GetVariable (body, br.ReadInt16 ());
164
case OperandType.InlineParam :
165
instr.Operand = GetParameter (body, br.ReadInt16 ());
167
case OperandType.InlineI8 :
168
instr.Operand = br.ReadInt64 ();
170
case OperandType.ShortInlineR :
171
instr.Operand = br.ReadSingle ();
173
case OperandType.InlineR :
174
instr.Operand = br.ReadDouble ();
176
case OperandType.InlineString :
177
instr.Operand = m_root.Streams.UserStringsHeap [GetRid (br.ReadInt32 ())];
179
case OperandType.InlineField :
180
case OperandType.InlineMethod :
181
case OperandType.InlineType :
182
case OperandType.InlineTok :
183
MetadataToken token = new MetadataToken (br.ReadInt32 ());
184
switch (token.TokenType) {
185
case TokenType.TypeDef:
186
instr.Operand = m_reflectReader.GetTypeDefAt (token.RID);
188
case TokenType.TypeRef:
189
instr.Operand = m_reflectReader.GetTypeRefAt (token.RID);
191
case TokenType.TypeSpec:
192
instr.Operand = m_reflectReader.GetTypeSpecAt (token.RID, context);
194
case TokenType.Field:
195
instr.Operand = m_reflectReader.GetFieldDefAt (token.RID);
197
case TokenType.Method:
198
instr.Operand = m_reflectReader.GetMethodDefAt (token.RID);
200
case TokenType.MethodSpec:
201
instr.Operand = m_reflectReader.GetMethodSpecAt (token.RID, context);
203
case TokenType.MemberRef:
204
instr.Operand = m_reflectReader.GetMemberRefAt (token.RID, context);
207
throw new ReflectionException ("Wrong token: " + token);
212
m_instructions.Add (instr.Offset, instr);
216
instr.Previous = last;
225
foreach (Instruction i in code) {
226
switch (i.OpCode.OperandType) {
305
const byte fat_format = 0x40;
306
const byte more_sects = 0x80;
308
var flags = ReadByte ();
309
if ((flags & fat_format) == 0)
314
if ((flags & more_sects) != 0)
318
void ReadSmallSection ()
320
var count = ReadByte () / 12;
323
ReadExceptionHandlers (
325
() => (int) ReadUInt16 (),
326
() => (int) ReadByte ());
329
void ReadFatSection ()
332
var count = (ReadInt32 () >> 8) / 24;
334
ReadExceptionHandlers (
341
void ReadExceptionHandlers (int count, Func<int> read_entry, Func<int> read_length)
343
for (int i = 0; i < count; i++) {
344
var handler = new ExceptionHandler (
345
(ExceptionHandlerType) (read_entry () & 0x7));
347
handler.TryStart = GetInstruction (read_entry ());
348
handler.TryEnd = GetInstruction (handler.TryStart.Offset + read_length ());
350
handler.HandlerStart = GetInstruction (read_entry ());
351
handler.HandlerEnd = GetInstruction (handler.HandlerStart.Offset + read_length ());
353
ReadExceptionHandlerSpecific (handler);
355
this.body.ExceptionHandlers.Add (handler);
359
void ReadExceptionHandlerSpecific (ExceptionHandler handler)
361
switch (handler.HandlerType) {
362
case ExceptionHandlerType.Catch:
363
handler.CatchType = (TypeReference) reader.LookupToken (ReadToken ());
365
case ExceptionHandlerType.Filter:
366
handler.FilterStart = GetInstruction (ReadInt32 ());
367
handler.FilterEnd = handler.HandlerStart.Previous;
375
void Align (int align)
378
Advance (((position + align) & ~align) - position);
381
public MetadataToken ReadToken ()
383
return new MetadataToken (ReadUInt32 ());
388
public ByteBuffer PatchRawMethodBody (MethodDefinition method, CodeWriter writer, out MethodSymbols symbols)
390
var buffer = new ByteBuffer ();
391
symbols = new MethodSymbols (method.Name);
393
this.method = method;
394
reader.context = method;
398
var flags = ReadByte ();
400
MetadataToken local_var_token;
402
switch (flags & 0x3) {
404
buffer.WriteByte (flags);
405
local_var_token = MetadataToken.Zero;
406
symbols.code_size = flags >> 2;
407
PatchRawCode (buffer, symbols.code_size, writer);
412
PatchRawFatMethod (buffer, symbols, writer, out local_var_token);
415
throw new NotSupportedException ();
418
var symbol_reader = reader.module.SymbolReader;
419
if (symbol_reader != null && writer.metadata.write_symbols) {
420
symbols.method_token = GetOriginalToken (writer.metadata, method);
421
symbols.local_var_token = local_var_token;
422
symbol_reader.Read (symbols);
428
void PatchRawFatMethod (ByteBuffer buffer, MethodSymbols symbols, CodeWriter writer, out MetadataToken local_var_token)
430
var flags = ReadUInt16 ();
431
buffer.WriteUInt16 (flags);
432
buffer.WriteUInt16 (ReadUInt16 ());
433
symbols.code_size = ReadInt32 ();
434
buffer.WriteInt32 (symbols.code_size);
435
local_var_token = ReadToken ();
437
if (local_var_token.RID > 0) {
438
var variables = symbols.variables = ReadVariables (local_var_token);
439
buffer.WriteUInt32 (variables != null
440
? writer.GetStandAloneSignature (symbols.variables).ToUInt32 ()
443
buffer.WriteUInt32 (0);
445
PatchRawCode (buffer, symbols.code_size, writer);
447
if ((flags & 0x8) != 0)
448
PatchRawSection (buffer, writer.metadata);
451
static MetadataToken GetOriginalToken (MetadataBuilder metadata, MethodDefinition method)
453
MetadataToken original;
454
if (metadata.TryGetOriginalMethodToken (method.token, out original))
457
return MetadataToken.Zero;
460
void PatchRawCode (ByteBuffer buffer, int code_size, CodeWriter writer)
462
var metadata = writer.metadata;
463
buffer.WriteBytes (ReadBytes (code_size));
464
var end = buffer.position;
465
buffer.position -= code_size;
467
while (buffer.position < end) {
469
var il_opcode = buffer.ReadByte ();
470
if (il_opcode != 0xfe) {
471
opcode = OpCodes.OneByteOpCode [il_opcode];
473
var il_opcode2 = buffer.ReadByte ();
474
opcode = OpCodes.TwoBytesOpCode [il_opcode2];
477
switch (opcode.OperandType) {
478
case OperandType.ShortInlineI:
227
479
case OperandType.ShortInlineBrTarget:
480
case OperandType.ShortInlineVar:
481
case OperandType.ShortInlineArg:
482
buffer.position += 1;
484
case OperandType.InlineVar:
485
case OperandType.InlineArg:
486
buffer.position += 2;
228
488
case OperandType.InlineBrTarget:
229
i.Operand = GetInstruction (body, (int) i.Operand);
489
case OperandType.ShortInlineR:
490
case OperandType.InlineI:
491
buffer.position += 4;
493
case OperandType.InlineI8:
494
case OperandType.InlineR:
495
buffer.position += 8;
231
497
case OperandType.InlineSwitch:
232
int [] lbls = (int []) i.Operand;
233
Instruction [] instrs = new Instruction [lbls.Length];
234
for (int j = 0; j < lbls.Length; j++)
235
instrs [j] = GetInstruction (body, lbls [j]);
241
if (m_reflectReader.SymbolReader != null)
242
m_reflectReader.SymbolReader.Read (body, m_instructions);
245
Instruction GetInstruction (MethodBody body, int offset)
247
Instruction instruction = m_instructions [offset] as Instruction;
248
if (instruction != null)
251
return body.Instructions.Outside;
254
void ReadSection (MethodBody body, BinaryReader br)
256
br.BaseStream.Position += 3;
257
br.BaseStream.Position &= ~3;
259
byte flags = br.ReadByte ();
260
if ((flags & (byte) MethodDataSection.FatFormat) == 0) {
261
int length = br.ReadByte () / 12;
264
for (int i = 0; i < length; i++) {
265
ExceptionHandler eh = new ExceptionHandler (
266
(ExceptionHandlerType) (br.ReadInt16 () & 0x7));
267
eh.TryStart = GetInstruction (body, Convert.ToInt32 (br.ReadInt16 ()));
268
eh.TryEnd = GetInstruction (body, eh.TryStart.Offset + Convert.ToInt32 (br.ReadByte ()));
269
eh.HandlerStart = GetInstruction (body, Convert.ToInt32 (br.ReadInt16 ()));
270
eh.HandlerEnd = GetInstruction (body, eh.HandlerStart.Offset + Convert.ToInt32 (br.ReadByte ()));
271
ReadExceptionHandlerEnd (eh, br, body);
272
body.ExceptionHandlers.Add (eh);
275
br.BaseStream.Position--;
276
int length = (br.ReadInt32 () >> 8) / 24;
277
if ((flags & (int) MethodDataSection.EHTable) == 0)
278
br.ReadBytes (length * 24);
279
for (int i = 0; i < length; i++) {
280
ExceptionHandler eh = new ExceptionHandler (
281
(ExceptionHandlerType) (br.ReadInt32 () & 0x7));
282
eh.TryStart = GetInstruction (body, br.ReadInt32 ());
283
eh.TryEnd = GetInstruction (body, eh.TryStart.Offset + br.ReadInt32 ());
284
eh.HandlerStart = GetInstruction (body, br.ReadInt32 ());
285
eh.HandlerEnd = GetInstruction (body, eh.HandlerStart.Offset + br.ReadInt32 ());
286
ReadExceptionHandlerEnd (eh, br, body);
287
body.ExceptionHandlers.Add (eh);
291
if ((flags & (byte) MethodDataSection.MoreSects) != 0)
292
ReadSection (body, br);
295
void ReadExceptionHandlerEnd (ExceptionHandler eh, BinaryReader br, MethodBody body)
298
case ExceptionHandlerType.Catch :
299
MetadataToken token = new MetadataToken (br.ReadInt32 ());
300
eh.CatchType = m_reflectReader.GetTypeDefOrRef (token, new GenericContext (body.Method));
302
case ExceptionHandlerType.Filter :
303
eh.FilterStart = GetInstruction (body, br.ReadInt32 ());
304
eh.FilterEnd = GetInstruction (body, eh.HandlerStart.Previous.Offset);
312
CallSite GetCallSiteAt (int token, GenericContext context)
314
StandAloneSigTable sasTable = m_reflectReader.TableReader.GetStandAloneSigTable ();
315
MethodSig ms = m_reflectReader.SigReader.GetStandAloneMethodSig (
316
sasTable [(int) GetRid (token) - 1].Signature);
317
CallSite cs = new CallSite (ms.HasThis, ms.ExplicitThis,
318
ms.MethCallConv, m_reflectReader.GetMethodReturnType (ms, context));
319
cs.MetadataToken = new MetadataToken (token);
321
for (int i = 0; i < ms.ParamCount; i++) {
322
Param p = ms.Parameters [i];
323
cs.Parameters.Add (m_reflectReader.BuildParameterDefinition (i, p, context));
326
ReflectionReader.CreateSentinelIfNeeded (cs, ms);
331
public override void VisitVariableDefinitionCollection (VariableDefinitionCollection variables)
333
MethodBody body = variables.Container as MethodBody;
334
if (body == null || body.LocalVarToken == 0)
337
StandAloneSigTable sasTable = m_reflectReader.TableReader.GetStandAloneSigTable ();
338
StandAloneSigRow sasRow = sasTable [(int) GetRid (body.LocalVarToken) - 1];
339
LocalVarSig sig = m_reflectReader.SigReader.GetLocalVarSig (sasRow.Signature);
340
for (int i = 0; i < sig.Count; i++) {
341
LocalVarSig.LocalVariable lv = sig.LocalVariables [i];
342
TypeReference varType = m_reflectReader.GetTypeRefFromSig (
343
lv.Type, new GenericContext (body.Method));
346
varType = new ReferenceType (varType);
347
if ((lv.Constraint & Constraint.Pinned) != 0)
348
varType = new PinnedType (varType);
350
varType = m_reflectReader.GetModifierType (lv.CustomMods, varType);
352
body.Variables.Add (new VariableDefinition (
353
string.Concat ("V_", i), i, body.Method, varType));
498
var length = buffer.ReadInt32 ();
499
buffer.position += length * 4;
501
case OperandType.InlineString:
502
var @string = GetString (new MetadataToken (buffer.ReadUInt32 ()));
503
buffer.position -= 4;
507
metadata.user_string_heap.GetStringIndex (@string)).ToUInt32 ());
509
case OperandType.InlineSig:
510
var call_site = GetCallSite (new MetadataToken (buffer.ReadUInt32 ()));
511
buffer.position -= 4;
512
buffer.WriteUInt32 (writer.GetStandAloneSignature (call_site).ToUInt32 ());
514
case OperandType.InlineTok:
515
case OperandType.InlineType:
516
case OperandType.InlineMethod:
517
case OperandType.InlineField:
518
var provider = reader.LookupToken (new MetadataToken (buffer.ReadUInt32 ()));
519
buffer.position -= 4;
520
buffer.WriteUInt32 (metadata.LookupToken (provider).ToUInt32 ());
526
void PatchRawSection (ByteBuffer buffer, MetadataBuilder metadata)
528
var position = base.position;
530
buffer.WriteBytes (base.position - position);
532
const byte fat_format = 0x40;
533
const byte more_sects = 0x80;
535
var flags = ReadByte ();
536
if ((flags & fat_format) == 0) {
537
buffer.WriteByte (flags);
538
PatchRawSmallSection (buffer, metadata);
540
PatchRawFatSection (buffer, metadata);
542
if ((flags & more_sects) != 0)
543
PatchRawSection (buffer, metadata);
546
void PatchRawSmallSection (ByteBuffer buffer, MetadataBuilder metadata)
548
var length = ReadByte ();
549
buffer.WriteByte (length);
552
buffer.WriteUInt16 (0);
554
var count = length / 12;
556
PatchRawExceptionHandlers (buffer, metadata, count, false);
559
void PatchRawFatSection (ByteBuffer buffer, MetadataBuilder metadata)
562
var length = ReadInt32 ();
563
buffer.WriteInt32 (length);
565
var count = (length >> 8) / 24;
567
PatchRawExceptionHandlers (buffer, metadata, count, true);
570
void PatchRawExceptionHandlers (ByteBuffer buffer, MetadataBuilder metadata, int count, bool fat_entry)
572
const int fat_entry_size = 16;
573
const int small_entry_size = 6;
575
for (int i = 0; i < count; i++) {
576
ExceptionHandlerType handler_type;
578
var type = ReadUInt32 ();
579
handler_type = (ExceptionHandlerType) (type & 0x7);
580
buffer.WriteUInt32 (type);
582
var type = ReadUInt16 ();
583
handler_type = (ExceptionHandlerType) (type & 0x7);
584
buffer.WriteUInt16 (type);
587
buffer.WriteBytes (ReadBytes (fat_entry ? fat_entry_size : small_entry_size));
589
switch (handler_type) {
590
case ExceptionHandlerType.Catch:
591
var exception = reader.LookupToken (ReadToken ());
592
buffer.WriteUInt32 (metadata.LookupToken (exception).ToUInt32 ());
595
buffer.WriteUInt32 (ReadUInt32 ());