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