/* 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.Contracts.Hex.Files.DotNet { /// /// kind /// public enum DotNetMethodBodyKind { /// /// Invalid method body () /// Invalid, /// /// Tiny method body () /// Tiny, /// /// Fat method body () /// Fat, } /// /// .NET method body /// public abstract class DotNetMethodBody : StructureData { /// /// Gets tokens of all methods that reference this method body /// public ReadOnlyCollection Tokens { get; } /// /// Gets the owner instance /// public DotNetMethodProvider MethodProvider { get; } /// /// Constructor /// /// Owner /// Name /// Span /// Tokens of all methods that reference this method body protected DotNetMethodBody(DotNetMethodProvider methodProvider, string name, HexBufferSpan span, ReadOnlyCollection tokens) : base(name, span) { if (tokens is null) throw new ArgumentOutOfRangeException(nameof(tokens)); if (tokens.Count == 0) throw new ArgumentOutOfRangeException(nameof(tokens)); MethodProvider = methodProvider ?? throw new ArgumentNullException(nameof(methodProvider)); Tokens = tokens; } /// /// Gets the kind /// public abstract DotNetMethodBodyKind Kind { get; } /// /// Gets the instruction bytes /// public abstract StructField> Instructions { get; } } /// /// Invalid .NET method body /// public abstract class InvalidMethodBody : DotNetMethodBody { const string NAME = "IMAGE_COR_ILMETHOD_???"; /// /// Constructor /// /// Owner /// Span /// Tokens of all methods that reference this method body protected InvalidMethodBody(DotNetMethodProvider methodProvider, HexBufferSpan span, ReadOnlyCollection tokens) : base(methodProvider, NAME, span, tokens) { } /// /// Gets the kind /// public sealed override DotNetMethodBodyKind Kind => DotNetMethodBodyKind.Invalid; } /// /// Tiny .NET method body /// public abstract class TinyMethodBody : DotNetMethodBody { const string NAME = "IMAGE_COR_ILMETHOD_TINY"; /// /// Constructor /// /// Owner /// Span /// Tokens of all methods that reference this method body protected TinyMethodBody(DotNetMethodProvider methodProvider, HexBufferSpan span, ReadOnlyCollection tokens) : base(methodProvider, NAME, span, tokens) { } /// /// Gets the kind /// public sealed override DotNetMethodBodyKind Kind => DotNetMethodBodyKind.Tiny; /// IMAGE_COR_ILMETHOD_TINY.Flags_CodeSize public abstract StructField Flags_CodeSize { get; } } /// /// Fat .NET method body /// public abstract class FatMethodBody : DotNetMethodBody { const string NAME = "IMAGE_COR_ILMETHOD_FAT"; /// /// Constructor /// /// Owner /// Span /// Tokens of all methods that reference this method body protected FatMethodBody(DotNetMethodProvider methodProvider, HexBufferSpan span, ReadOnlyCollection tokens) : base(methodProvider, NAME, span, tokens) { } /// /// Gets the kind /// public sealed override DotNetMethodBodyKind Kind => DotNetMethodBodyKind.Fat; /// IMAGE_COR_ILMETHOD_FAT.Flags / Size public abstract StructField Flags_Size { get; } /// IMAGE_COR_ILMETHOD_FAT.MaxStack public abstract StructField MaxStack { get; } /// IMAGE_COR_ILMETHOD_FAT.CodeSize public abstract StructField CodeSize { get; } /// IMAGE_COR_ILMETHOD_FAT.LocalVarSigTok public abstract StructField LocalVarSigTok { get; } /// /// Padding between and . /// It's null if isn't present. /// public abstract StructField>? Padding { get; } /// /// Gets the exception handler table or null if there's none /// public abstract StructField? EHTable { get; } } /// /// .NET method body section /// public abstract class DotNetMethodSection : StructureData { /// /// Constructor /// /// Name /// Span protected DotNetMethodSection(string name, HexBufferSpan span) : base(name, span) { } /// /// Returns true if this is a small section /// public abstract bool IsSmall { get; } } /// /// Small section /// public abstract class SmallSection : DotNetMethodSection { const string NAME = "IMAGE_COR_ILMETHOD_SECT_SMALL"; /// /// Constructor /// /// Span protected SmallSection(HexBufferSpan span) : base(NAME, span) { if (span.Length != 2) throw new ArgumentOutOfRangeException(nameof(span)); } /// /// Returns true since this is a small section /// public override bool IsSmall => true; /// IMAGE_COR_ILMETHOD_SECT_SMALL.Kind public abstract StructField Kind { get; } /// IMAGE_COR_ILMETHOD_SECT_SMALL.DataSize public abstract StructField DataSize { get; } } /// /// Fat section /// public abstract class FatSection : DotNetMethodSection { const string NAME = "IMAGE_COR_ILMETHOD_SECT_FAT"; /// /// Constructor /// /// Span protected FatSection(HexBufferSpan span) : base(NAME, span) { if (span.Length != 4) throw new ArgumentOutOfRangeException(nameof(span)); } /// /// Returns false since this is a fat section /// public override bool IsSmall => false; /// IMAGE_COR_ILMETHOD_SECT_FAT.Kind public abstract StructField Kind { get; } /// IMAGE_COR_ILMETHOD_SECT_FAT.DataSize public abstract StructField DataSize { get; } } /// /// Exception handler table /// public abstract class ExceptionHandlerTable : StructureData { /// /// Constructor /// /// Name /// Span protected ExceptionHandlerTable(string name, HexBufferSpan span) : base(name, span) { } /// /// true if it's a small exception handler table /// public abstract bool IsSmall { get; } } /// /// Small exception handler table /// public abstract class SmallExceptionHandlerTable : ExceptionHandlerTable { const string NAME = "IMAGE_COR_ILMETHOD_SECT_EH_SMALL"; /// /// Constructor /// /// Span protected SmallExceptionHandlerTable(HexBufferSpan span) : base(NAME, span) { } /// /// Returns true since this is a small exception handler table /// public override bool IsSmall => true; /// IMAGE_COR_ILMETHOD_SECT_EH_SMALL.SectSmall public abstract StructField SectSmall { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_SMALL.Reserved public abstract StructField Reserved { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_SMALL.Clauses public abstract StructField> Clauses { get; } } /// /// Fat exception handler table /// public abstract class FatExceptionHandlerTable : ExceptionHandlerTable { const string NAME = "IMAGE_COR_ILMETHOD_SECT_EH_FAT"; /// /// Constructor /// /// Span protected FatExceptionHandlerTable(HexBufferSpan span) : base(NAME, span) { } /// /// Returns false since this is a fat exception handler table /// public override bool IsSmall => false; /// IMAGE_COR_ILMETHOD_SECT_EH_FAT.SectFat public abstract StructField SectFat { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_FAT.Clauses public abstract StructField> Clauses { get; } } /// /// Exception clause /// public abstract class ExceptionClause : StructureData { /// /// Constructor /// /// Name /// Span protected ExceptionClause(string name, HexBufferSpan span) : base(name, span) { } /// /// true if it's a small exception clause /// public abstract bool IsSmall { get; } } /// /// Small exception clause /// public abstract class SmallExceptionClause : ExceptionClause { const string NAME = "IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL"; /// /// Constructor /// protected SmallExceptionClause(HexBufferSpan span) : base(NAME, span) { if (span.Length != 12) throw new ArgumentOutOfRangeException(nameof(span)); } /// /// Returns true since this is a small exception clause /// public override bool IsSmall => true; /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL.Flags public abstract StructField Flags { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL.TryOffset public abstract StructField TryOffset { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL.TryLength public abstract StructField TryLength { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL.HandlerOffset public abstract StructField HandlerOffset { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL.HandlerLength public abstract StructField HandlerLength { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL.ClassToken/FilterOffset public abstract StructField ClassTokenOrFilterOffset { get; } } /// /// Fat exception clause /// public abstract class FatExceptionClause : ExceptionClause { const string NAME = "IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT"; /// /// Constructor /// protected FatExceptionClause(HexBufferSpan span) : base(NAME, span) { if (span.Length != 24) throw new ArgumentOutOfRangeException(nameof(span)); } /// /// Returns false since this is a fat exception clause /// public override bool IsSmall => false; /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT.Flags public abstract StructField Flags { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT.TryOffset public abstract StructField TryOffset { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT.TryLength public abstract StructField TryLength { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT.HandlerOffset public abstract StructField HandlerOffset { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT.HandlerLength public abstract StructField HandlerLength { get; } /// IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT.ClassToken / FilterOffset public abstract StructField ClassTokenOrFilterOffset { get; } } }