2021-09-20 18:20:01 +02:00

136 lines
6.0 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.IO;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using dnlib.DotNet.Writer;
namespace dnSpy.Debugger.DotNet.Evaluation.Engine {
readonly struct IntrinsicsAssemblyBuilder {
readonly ModuleDef module;
readonly TypeDef intrinsicsType;
readonly ICorLibTypes corlibTypes;
readonly TypeSig exceptionTypeSig;
readonly TypeSig typeTypeSig;
readonly TypeSig guidTypeSig;
public IntrinsicsAssemblyBuilder(string corlibAssemblyFullName, string imageRuntimeVersion) {
var corlibRef = new AssemblyRefUser(new AssemblyNameInfo(corlibAssemblyFullName));
module = new ModuleDefUser(Guid.NewGuid().ToString(), Guid.NewGuid(), corlibRef);
module.RuntimeVersion = imageRuntimeVersion;
module.Kind = ModuleKind.Dll;
var asm = new AssemblyDefUser(Guid.NewGuid().ToString());
asm.Modules.Add(module);
intrinsicsType = new TypeDefUser(ExpressionCompilerConstants.IntrinsicAssemblyNamespace, ExpressionCompilerConstants.IntrinsicAssemblyTypeName, module.CorLibTypes.Object.TypeDefOrRef);
intrinsicsType.Attributes = TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.AnsiClass | TypeAttributes.Abstract | TypeAttributes.Sealed;
module.Types.Add(intrinsicsType);
corlibTypes = module.CorLibTypes;
exceptionTypeSig = new ClassSig(corlibTypes.GetTypeRef(nameof(System), nameof(Exception)));
typeTypeSig = new ClassSig(corlibTypes.GetTypeRef(nameof(System), nameof(Type)));
guidTypeSig = new ValueTypeSig(corlibTypes.GetTypeRef(nameof(System), nameof(Guid)));
}
public (byte[] assemblyBytes, string assemblySimpleName) Create() {
intrinsicsType.Methods.Add(CreateGetObjectAtAddress());
intrinsicsType.Methods.Add(CreateGetException());
intrinsicsType.Methods.Add(CreateGetStowedException());
intrinsicsType.Methods.Add(CreateGetReturnValue());
intrinsicsType.Methods.Add(CreateCreateVariable());
intrinsicsType.Methods.Add(CreateGetObjectByAlias());
intrinsicsType.Methods.Add(CreateGetVariableAddress());
var memStream = new MemoryStream();
var writerOptions = new ModuleWriterOptions(module);
module.Write(memStream, writerOptions);
return (memStream.ToArray(), module.Assembly.Name);
}
const MethodImplAttributes methodImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed;
const MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.ReuseSlot;
CilBody CreateBody() {
var body = new CilBody();
body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
body.Instructions.Add(Instruction.Create(OpCodes.Throw));
return body;
}
MethodDef CreateGetObjectAtAddress() {
var sig = MethodSig.CreateStatic(corlibTypes.Object, corlibTypes.UInt64);
var method = new MethodDefUser(ExpressionCompilerConstants.GetObjectAtAddressMethodName, sig, methodImplAttributes, methodAttributes);
method.ParamDefs.Add(new ParamDefUser("address", 1));
method.Body = CreateBody();
return method;
}
MethodDef CreateGetException() {
var sig = MethodSig.CreateStatic(exceptionTypeSig);
var method = new MethodDefUser(ExpressionCompilerConstants.GetExceptionMethodName, sig, methodImplAttributes, methodAttributes);
method.Body = CreateBody();
return method;
}
MethodDef CreateGetStowedException() {
var sig = MethodSig.CreateStatic(exceptionTypeSig);
var method = new MethodDefUser(ExpressionCompilerConstants.GetStowedExceptionMethodName, sig, methodImplAttributes, methodAttributes);
method.Body = CreateBody();
return method;
}
MethodDef CreateGetReturnValue() {
var sig = MethodSig.CreateStatic(corlibTypes.Object, corlibTypes.Int32);
var method = new MethodDefUser(ExpressionCompilerConstants.GetReturnValueMethodName, sig, methodImplAttributes, methodAttributes);
method.ParamDefs.Add(new ParamDefUser("index", 1));
method.Body = CreateBody();
return method;
}
MethodDef CreateCreateVariable() {
var sig = MethodSig.CreateStatic(corlibTypes.Void, typeTypeSig, corlibTypes.String, guidTypeSig, new SZArraySig(corlibTypes.Byte));
var method = new MethodDefUser(ExpressionCompilerConstants.CreateVariableMethodName, sig, methodImplAttributes, methodAttributes);
method.ParamDefs.Add(new ParamDefUser("type", 1));
method.ParamDefs.Add(new ParamDefUser("name", 2));
method.ParamDefs.Add(new ParamDefUser("customTypeInfoPayloadTypeId", 3));
method.ParamDefs.Add(new ParamDefUser("customTypeInfoPayload", 4));
method.Body = CreateBody();
return method;
}
MethodDef CreateGetObjectByAlias() {
var sig = MethodSig.CreateStatic(corlibTypes.Object, corlibTypes.String);
var method = new MethodDefUser(ExpressionCompilerConstants.GetVariableValueMethodName, sig, methodImplAttributes, methodAttributes);
method.ParamDefs.Add(new ParamDefUser("name", 1));
method.Body = CreateBody();
return method;
}
MethodDef CreateGetVariableAddress() {
var method = new MethodDefUser(ExpressionCompilerConstants.GetVariableAddressMethodName, null, methodImplAttributes, methodAttributes);
var sig = MethodSig.CreateStaticGeneric(1, new PtrSig(new GenericMVar(0, method)), corlibTypes.String);
method.MethodSig = sig;
method.GenericParameters.Add(new GenericParamUser(0, GenericParamAttributes.NonVariant, "T"));
method.ParamDefs.Add(new ParamDefUser("name", 1));
method.Body = CreateBody();
return method;
}
}
}