Dnspy/dnSpy/dnSpy.Contracts.DnSpy/Hex/Files/DotNet/DotNetMethodBodyData.cs
2021-09-20 18:20:01 +02:00

424 lines
13 KiB
C#

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