/* 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}"; } } } }