/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see .
*/
using System;
using System.Collections.ObjectModel;
namespace dnSpy.Debugger.DotNet.Metadata {
///
/// .NET method body
///
public abstract class DmdMethodBody {
///
/// Gets the token of the locals signature
///
public abstract int LocalSignatureMetadataToken { get; }
///
/// Gets all locals
///
public abstract ReadOnlyCollection LocalVariables { get; }
///
/// Gets max stack size
///
public abstract int MaxStackSize { get; }
///
/// true if locals are automatically initialized
///
public abstract bool InitLocals { get; }
///
/// Gets the IL bytes
///
///
public abstract byte[] GetILAsByteArray();
///
/// Gets the exception clauses
///
public abstract ReadOnlyCollection ExceptionHandlingClauses { get; }
///
/// Gets the generic type arguments that were used to create this method body
///
public abstract ReadOnlyCollection GenericTypeArguments { get; }
///
/// Gets the generic method arguments that were used to create this method body
///
public abstract ReadOnlyCollection GenericMethodArguments { get; }
}
///
/// Local variable info
///
public sealed class DmdLocalVariableInfo {
///
/// Gets the type of the local
///
public DmdType LocalType { get; }
///
/// true if it's a pinned local
///
public bool IsPinned { get; }
///
/// Index of the local in the locals signature
///
public int LocalIndex { get; }
///
/// Constructor
///
/// Type of the local
/// Index of local
/// True if it's a pinned local
public DmdLocalVariableInfo(DmdType localType, int localIndex, bool isPinned) {
if (localIndex < 0)
throw new ArgumentOutOfRangeException(nameof(localIndex));
LocalType = localType ?? throw new ArgumentNullException(nameof(localType));
LocalIndex = localIndex;
IsPinned = isPinned;
}
///
/// ToString()
///
///
public override string ToString() {
if (IsPinned)
return LocalType.ToString() + " (" + LocalIndex.ToString() + ") (pinned)";
return LocalType.ToString() + " (" + LocalIndex.ToString() + ")";
}
}
///
/// Exception clause kind
///
[Flags]
public enum DmdExceptionHandlingClauseOptions {
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
Clause = 0,
Filter = 1,
Finally = 2,
Fault = 4,
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
}
///
/// Exception clause
///
public sealed class DmdExceptionHandlingClause {
///
/// Gets the clause kind
///
public DmdExceptionHandlingClauseOptions Flags { get; }
///
/// Try offset
///
public int TryOffset { get; }
///
/// Try length
///
public int TryLength { get; }
///
/// Handler offset
///
public int HandlerOffset { get; }
///
/// Handler length
///
public int HandlerLength { get; }
///
/// Filter offset
///
public int FilterOffset {
get {
if (Flags != DmdExceptionHandlingClauseOptions.Filter)
throw new InvalidOperationException();
return filterOffset;
}
}
readonly int filterOffset;
///
/// Catch type
///
public DmdType? CatchType {
get {
if (Flags != DmdExceptionHandlingClauseOptions.Clause)
throw new InvalidOperationException();
return catchType;
}
}
readonly DmdType? catchType;
///
/// Constructor
///
/// Flags
/// Try offset
/// Try length
/// Handler offset
/// Handler length
/// Filter offset
/// Catch type
public DmdExceptionHandlingClause(DmdExceptionHandlingClauseOptions flags, int tryOffset, int tryLength, int handlerOffset, int handlerLength, int filterOffset, DmdType? catchType) {
Flags = flags;
TryOffset = tryOffset;
TryLength = tryLength;
HandlerOffset = handlerOffset;
HandlerLength = handlerLength;
this.filterOffset = filterOffset;
this.catchType = catchType;
}
///
/// ToString()
///
///
public override string ToString() {
switch (Flags) {
case DmdExceptionHandlingClauseOptions.Clause:
return $"Flags={Flags}, TryOffset={TryOffset}, TryLength={TryLength}, HandlerOffset={HandlerOffset}, HandlerLength={HandlerLength}, CatchType={CatchType}";
case DmdExceptionHandlingClauseOptions.Filter:
return $"Flags={Flags}, TryOffset={TryOffset}, TryLength={TryLength}, HandlerOffset={HandlerOffset}, HandlerLength={HandlerLength}, FilterOffset={FilterOffset}";
case DmdExceptionHandlingClauseOptions.Finally:
case DmdExceptionHandlingClauseOptions.Fault:
default:
return $"Flags={Flags}, TryOffset={TryOffset}, TryLength={TryLength}, HandlerOffset={HandlerOffset}, HandlerLength={HandlerLength}";
}
}
}
}