You've already forked linux-packaging-mono
Imported Upstream version 4.8.0.309
Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850
This commit is contained in:
parent
ee1447783b
commit
94b2861243
241
external/cecil/Mono.Cecil.Cil/CodeReader.cs
vendored
241
external/cecil/Mono.Cecil.Cil/CodeReader.cs
vendored
@@ -1,29 +1,11 @@
|
||||
//
|
||||
// CodeReader.cs
|
||||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2011 Jb Evain
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
@@ -35,58 +17,53 @@ using RVA = System.UInt32;
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
sealed class CodeReader : ByteBuffer {
|
||||
sealed class CodeReader : BinaryStreamReader {
|
||||
|
||||
readonly internal MetadataReader reader;
|
||||
|
||||
int start;
|
||||
Section code_section;
|
||||
|
||||
MethodDefinition method;
|
||||
MethodBody body;
|
||||
|
||||
int Offset {
|
||||
get { return base.position - start; }
|
||||
get { return Position - start; }
|
||||
}
|
||||
|
||||
public CodeReader (Section section, MetadataReader reader)
|
||||
: base (section.Data)
|
||||
public CodeReader (MetadataReader reader)
|
||||
: base (reader.image.Stream.value)
|
||||
{
|
||||
this.code_section = section;
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
public int MoveTo (MethodDefinition method)
|
||||
{
|
||||
this.method = method;
|
||||
this.reader.context = method;
|
||||
var position = this.Position;
|
||||
this.Position = (int) reader.image.ResolveVirtualAddress ((uint) method.RVA);
|
||||
return position;
|
||||
}
|
||||
|
||||
void MoveBackTo (int position)
|
||||
{
|
||||
this.reader.context = null;
|
||||
this.Position = position;
|
||||
}
|
||||
|
||||
public MethodBody ReadMethodBody (MethodDefinition method)
|
||||
{
|
||||
this.method = method;
|
||||
var position = MoveTo (method);
|
||||
this.body = new MethodBody (method);
|
||||
|
||||
reader.context = method;
|
||||
|
||||
ReadMethodBody ();
|
||||
|
||||
MoveBackTo (position);
|
||||
return this.body;
|
||||
}
|
||||
|
||||
public void MoveTo (int rva)
|
||||
{
|
||||
if (!IsInSection (rva)) {
|
||||
code_section = reader.image.GetSectionAtVirtualAddress ((uint) rva);
|
||||
Reset (code_section.Data);
|
||||
}
|
||||
|
||||
base.position = rva - (int) code_section.VirtualAddress;
|
||||
}
|
||||
|
||||
bool IsInSection (int rva)
|
||||
{
|
||||
return code_section.VirtualAddress <= rva && rva < code_section.VirtualAddress + code_section.SizeOfRawData;
|
||||
}
|
||||
|
||||
void ReadMethodBody ()
|
||||
{
|
||||
MoveTo (method.RVA);
|
||||
|
||||
var flags = ReadByte ();
|
||||
switch (flags & 0x3) {
|
||||
case 0x2: // tiny
|
||||
@@ -95,7 +72,7 @@ namespace Mono.Cecil.Cil {
|
||||
ReadCode ();
|
||||
break;
|
||||
case 0x3: // fat
|
||||
base.position--;
|
||||
Advance (-1);
|
||||
ReadFatMethod ();
|
||||
break;
|
||||
default:
|
||||
@@ -104,12 +81,102 @@ namespace Mono.Cecil.Cil {
|
||||
|
||||
var symbol_reader = reader.module.symbol_reader;
|
||||
|
||||
if (symbol_reader != null) {
|
||||
var instructions = body.Instructions;
|
||||
symbol_reader.Read (body, offset => GetInstruction (instructions, offset));
|
||||
if (symbol_reader != null && method.debug_info == null)
|
||||
method.debug_info = symbol_reader.Read (method);
|
||||
|
||||
if (method.debug_info != null)
|
||||
ReadDebugInfo ();
|
||||
}
|
||||
|
||||
void ReadDebugInfo ()
|
||||
{
|
||||
if (method.debug_info.sequence_points != null)
|
||||
ReadSequencePoints ();
|
||||
|
||||
if (method.debug_info.scope != null)
|
||||
ReadScope (method.debug_info.scope);
|
||||
|
||||
if (method.custom_infos != null)
|
||||
ReadCustomDebugInformations (method);
|
||||
}
|
||||
|
||||
void ReadCustomDebugInformations (MethodDefinition method)
|
||||
{
|
||||
var custom_infos = method.custom_infos;
|
||||
|
||||
for (int i = 0; i < custom_infos.Count; i++) {
|
||||
var state_machine_scope = custom_infos [i] as StateMachineScopeDebugInformation;
|
||||
if (state_machine_scope != null)
|
||||
ReadStateMachineScope (state_machine_scope);
|
||||
|
||||
var async_method = custom_infos [i] as AsyncMethodBodyDebugInformation;
|
||||
if (async_method != null)
|
||||
ReadAsyncMethodBody (async_method);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadAsyncMethodBody (AsyncMethodBodyDebugInformation async_method)
|
||||
{
|
||||
if (async_method.catch_handler.Offset > -1)
|
||||
async_method.catch_handler = new InstructionOffset (GetInstruction (async_method.catch_handler.Offset));
|
||||
|
||||
if (!async_method.yields.IsNullOrEmpty ())
|
||||
for (int i = 0; i < async_method.yields.Count; i++)
|
||||
async_method.yields [i] = new InstructionOffset (GetInstruction (async_method.yields [i].Offset));
|
||||
|
||||
if (!async_method.resumes.IsNullOrEmpty ())
|
||||
for (int i = 0; i < async_method.resumes.Count; i++)
|
||||
async_method.resumes [i] = new InstructionOffset (GetInstruction (async_method.resumes [i].Offset));
|
||||
}
|
||||
|
||||
void ReadStateMachineScope (StateMachineScopeDebugInformation state_machine_scope)
|
||||
{
|
||||
state_machine_scope.start = new InstructionOffset (GetInstruction (state_machine_scope.start.Offset));
|
||||
|
||||
var end_instruction = GetInstruction (state_machine_scope.end.Offset);
|
||||
state_machine_scope.end = end_instruction == null
|
||||
? new InstructionOffset ()
|
||||
: new InstructionOffset (end_instruction);
|
||||
}
|
||||
|
||||
void ReadSequencePoints ()
|
||||
{
|
||||
var symbol = method.debug_info;
|
||||
|
||||
for (int i = 0; i < symbol.sequence_points.Count; i++) {
|
||||
var sequence_point = symbol.sequence_points [i];
|
||||
var instruction = GetInstruction (sequence_point.Offset);
|
||||
if (instruction != null)
|
||||
sequence_point.offset = new InstructionOffset (instruction);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadScopes (Collection<ScopeDebugInformation> scopes)
|
||||
{
|
||||
for (int i = 0; i < scopes.Count; i++)
|
||||
ReadScope (scopes [i]);
|
||||
}
|
||||
|
||||
void ReadScope (ScopeDebugInformation scope)
|
||||
{
|
||||
scope.Start = new InstructionOffset (GetInstruction (scope.Start.Offset));
|
||||
|
||||
var end_instruction = GetInstruction (scope.End.Offset);
|
||||
scope.End = end_instruction == null
|
||||
? new InstructionOffset ()
|
||||
: new InstructionOffset (end_instruction);
|
||||
|
||||
if (!scope.variables.IsNullOrEmpty ()) {
|
||||
for (int i = 0; i < scope.variables.Count; i++) {
|
||||
var variable = scope.variables [i];
|
||||
variable.index = new VariableIndex (GetVariable (variable.Index));
|
||||
}
|
||||
}
|
||||
|
||||
if (!scope.scopes.IsNullOrEmpty ())
|
||||
ReadScopes (scope.scopes);
|
||||
}
|
||||
|
||||
void ReadFatMethod ()
|
||||
{
|
||||
var flags = ReadUInt16 ();
|
||||
@@ -138,17 +205,17 @@ namespace Mono.Cecil.Cil {
|
||||
|
||||
void ReadCode ()
|
||||
{
|
||||
start = position;
|
||||
start = Position;
|
||||
var code_size = body.code_size;
|
||||
|
||||
if (code_size < 0 || buffer.Length <= (uint) (code_size + position))
|
||||
if (code_size < 0 || Length <= (uint) (code_size + Position))
|
||||
code_size = 0;
|
||||
|
||||
var end = start + code_size;
|
||||
var instructions = body.instructions = new InstructionCollection ((code_size + 1) / 2);
|
||||
var instructions = body.instructions = new InstructionCollection (method, (code_size + 1) / 2);
|
||||
|
||||
while (position < end) {
|
||||
var offset = base.position - start;
|
||||
while (Position < end) {
|
||||
var offset = Position - start;
|
||||
var opcode = ReadOpCode ();
|
||||
var current = new Instruction (offset, opcode);
|
||||
|
||||
@@ -248,7 +315,9 @@ namespace Mono.Cecil.Cil {
|
||||
switch (instruction.opcode.OperandType) {
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
instruction.operand = GetInstruction ((int) instruction.operand);
|
||||
var targetInstruction = GetInstruction ((int) instruction.operand);
|
||||
if (targetInstruction != null)
|
||||
instruction.operand = targetInstruction;
|
||||
break;
|
||||
case OperandType.InlineSwitch:
|
||||
var offsets = (int []) instruction.operand;
|
||||
@@ -323,7 +392,7 @@ namespace Mono.Cecil.Cil {
|
||||
|
||||
void ReadFatSection ()
|
||||
{
|
||||
position--;
|
||||
Advance (-1);
|
||||
var count = (ReadInt32 () >> 8) / 24;
|
||||
|
||||
ReadExceptionHandlers (
|
||||
@@ -369,6 +438,7 @@ namespace Mono.Cecil.Cil {
|
||||
void Align (int align)
|
||||
{
|
||||
align--;
|
||||
var position = Position;
|
||||
Advance (((position + align) & ~align) - position);
|
||||
}
|
||||
|
||||
@@ -379,78 +449,57 @@ namespace Mono.Cecil.Cil {
|
||||
|
||||
#if !READ_ONLY
|
||||
|
||||
public ByteBuffer PatchRawMethodBody (MethodDefinition method, CodeWriter writer, out MethodSymbols symbols)
|
||||
public ByteBuffer PatchRawMethodBody (MethodDefinition method, CodeWriter writer, out int code_size, out MetadataToken local_var_token)
|
||||
{
|
||||
var position = MoveTo (method);
|
||||
|
||||
var buffer = new ByteBuffer ();
|
||||
symbols = new MethodSymbols (method.Name);
|
||||
|
||||
this.method = method;
|
||||
reader.context = method;
|
||||
|
||||
MoveTo (method.RVA);
|
||||
|
||||
var flags = ReadByte ();
|
||||
|
||||
MetadataToken local_var_token;
|
||||
|
||||
switch (flags & 0x3) {
|
||||
case 0x2: // tiny
|
||||
buffer.WriteByte (flags);
|
||||
local_var_token = MetadataToken.Zero;
|
||||
symbols.code_size = flags >> 2;
|
||||
PatchRawCode (buffer, symbols.code_size, writer);
|
||||
code_size = flags >> 2;
|
||||
PatchRawCode (buffer, code_size, writer);
|
||||
break;
|
||||
case 0x3: // fat
|
||||
base.position--;
|
||||
|
||||
PatchRawFatMethod (buffer, symbols, writer, out local_var_token);
|
||||
Advance (-1);
|
||||
PatchRawFatMethod (buffer, writer, out code_size, out local_var_token);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
var symbol_reader = reader.module.symbol_reader;
|
||||
if (symbol_reader != null && writer.metadata.write_symbols) {
|
||||
symbols.method_token = GetOriginalToken (writer.metadata, method);
|
||||
symbols.local_var_token = local_var_token;
|
||||
symbol_reader.Read (symbols);
|
||||
}
|
||||
MoveBackTo (position);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void PatchRawFatMethod (ByteBuffer buffer, MethodSymbols symbols, CodeWriter writer, out MetadataToken local_var_token)
|
||||
void PatchRawFatMethod (ByteBuffer buffer, CodeWriter writer, out int code_size, out MetadataToken local_var_token)
|
||||
{
|
||||
var flags = ReadUInt16 ();
|
||||
buffer.WriteUInt16 (flags);
|
||||
buffer.WriteUInt16 (ReadUInt16 ());
|
||||
symbols.code_size = ReadInt32 ();
|
||||
buffer.WriteInt32 (symbols.code_size);
|
||||
code_size = ReadInt32 ();
|
||||
buffer.WriteInt32 (code_size);
|
||||
local_var_token = ReadToken ();
|
||||
|
||||
if (local_var_token.RID > 0) {
|
||||
var variables = symbols.variables = ReadVariables (local_var_token);
|
||||
var variables = ReadVariables (local_var_token);
|
||||
buffer.WriteUInt32 (variables != null
|
||||
? writer.GetStandAloneSignature (symbols.variables).ToUInt32 ()
|
||||
? writer.GetStandAloneSignature (variables).ToUInt32 ()
|
||||
: 0);
|
||||
} else
|
||||
buffer.WriteUInt32 (0);
|
||||
|
||||
PatchRawCode (buffer, symbols.code_size, writer);
|
||||
PatchRawCode (buffer, code_size, writer);
|
||||
|
||||
if ((flags & 0x8) != 0)
|
||||
PatchRawSection (buffer, writer.metadata);
|
||||
}
|
||||
|
||||
static MetadataToken GetOriginalToken (MetadataBuilder metadata, MethodDefinition method)
|
||||
{
|
||||
MetadataToken original;
|
||||
if (metadata.TryGetOriginalMethodToken (method.token, out original))
|
||||
return original;
|
||||
|
||||
return MetadataToken.Zero;
|
||||
}
|
||||
|
||||
void PatchRawCode (ByteBuffer buffer, int code_size, CodeWriter writer)
|
||||
{
|
||||
var metadata = writer.metadata;
|
||||
@@ -519,9 +568,9 @@ namespace Mono.Cecil.Cil {
|
||||
|
||||
void PatchRawSection (ByteBuffer buffer, MetadataBuilder metadata)
|
||||
{
|
||||
var position = base.position;
|
||||
var position = Position;
|
||||
Align (4);
|
||||
buffer.WriteBytes (base.position - position);
|
||||
buffer.WriteBytes (Position - position);
|
||||
|
||||
const byte fat_format = 0x40;
|
||||
const byte more_sects = 0x80;
|
||||
@@ -552,7 +601,7 @@ namespace Mono.Cecil.Cil {
|
||||
|
||||
void PatchRawFatSection (ByteBuffer buffer, MetadataBuilder metadata)
|
||||
{
|
||||
position--;
|
||||
Advance (-1);
|
||||
var length = ReadInt32 ();
|
||||
buffer.WriteInt32 (length);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user