// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.DotNet.Pdb; using dnlib.PE; namespace dnlib.DotNet.Emit { /// /// Method body base class /// public abstract class MethodBody { } /// /// A native method body /// public sealed class NativeMethodBody : MethodBody { RVA rva; /// /// Gets/sets the RVA of the native method body /// public RVA RVA { get => rva; set => rva = value; } /// /// Default constructor /// public NativeMethodBody() { } /// /// Constructor /// /// RVA of method body public NativeMethodBody(RVA rva) => this.rva = rva; } /// /// CIL (managed code) body /// public sealed class CilBody : MethodBody { bool keepOldMaxStack; bool initLocals; byte headerSize; ushort maxStack; uint localVarSigTok; readonly IList instructions; readonly IList exceptionHandlers; readonly LocalList localList; /// /// Size of a small header /// public const byte SMALL_HEADER_SIZE = 1; /// /// Gets/sets a flag indicating whether the original max stack value should be used. /// public bool KeepOldMaxStack { get => keepOldMaxStack; set => keepOldMaxStack = value; } /// /// Gets/sets the init locals flag. This is only valid if the method has any locals. /// public bool InitLocals { get => initLocals; set => initLocals = value; } /// /// Gets/sets the size in bytes of the method body header. The instructions immediately follow /// the header. /// public byte HeaderSize { get => headerSize; set => headerSize = value; } /// /// true if it was a small body header ( is 1) /// public bool IsSmallHeader => headerSize == SMALL_HEADER_SIZE; /// /// true if it was a big body header /// public bool IsBigHeader => headerSize != SMALL_HEADER_SIZE; /// /// Gets/sets max stack value from the fat method header. /// public ushort MaxStack { get => maxStack; set => maxStack = value; } /// /// Gets/sets the locals metadata token /// public uint LocalVarSigTok { get => localVarSigTok; set => localVarSigTok = value; } /// /// true if is not empty /// public bool HasInstructions => instructions.Count > 0; /// /// Gets the instructions /// public IList Instructions => instructions; /// /// true if is not empty /// public bool HasExceptionHandlers => exceptionHandlers.Count > 0; /// /// Gets the exception handlers /// public IList ExceptionHandlers => exceptionHandlers; /// /// true if is not empty /// public bool HasVariables => localList.Count > 0; /// /// Gets the locals /// public LocalList Variables => localList; /// /// Gets/sets the PDB method. This is null if no PDB has been loaded or if there's /// no PDB info for this method. /// public PdbMethod PdbMethod { get => pdbMethod; set => pdbMethod = value; } PdbMethod pdbMethod; /// /// true if is not null /// public bool HasPdbMethod => PdbMethod is not null; /// /// Gets the total size of the body in the PE file, including header, IL bytes, and exception handlers. /// This property returns 0 if the size is unknown. /// internal uint MetadataBodySize { get; set; } /// /// Default constructor /// public CilBody() { initLocals = true; instructions = new List(); exceptionHandlers = new List(); localList = new LocalList(); } /// /// Constructor /// /// Init locals flag /// All instructions. This instance will own the list. /// All exception handlers. This instance will own the list. /// All locals. This instance will own the locals in the list. public CilBody(bool initLocals, IList instructions, IList exceptionHandlers, IList locals) { this.initLocals = initLocals; this.instructions = instructions; this.exceptionHandlers = exceptionHandlers; localList = new LocalList(locals); } /// /// Shorter instructions are converted to the longer form, eg. Ldc_I4_1 is /// converted to Ldc_I4 with a 1 as the operand. /// /// All method parameters, including the hidden 'this' parameter /// if it's an instance method. Use . public void SimplifyMacros(IList parameters) => instructions.SimplifyMacros(localList, parameters); /// /// Optimizes instructions by using the shorter form if possible. Eg. Ldc_I4 1 /// will be replaced with Ldc_I4_1. /// public void OptimizeMacros() => instructions.OptimizeMacros(); /// /// Short branch instructions are converted to the long form, eg. Beq_S is /// converted to Beq. /// public void SimplifyBranches() => instructions.SimplifyBranches(); /// /// Optimizes branches by using the smallest possible branch /// public void OptimizeBranches() => instructions.OptimizeBranches(); /// /// Updates each instruction's offset /// /// Total size in bytes of all instructions public uint UpdateInstructionOffsets() => instructions.UpdateInstructionOffsets(); } }