mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-07 06:58:39 +00:00
Shonky assembly loading
This commit is contained in:
@@ -3,6 +3,7 @@ namespace WoofWare.PawPrint
|
|||||||
open System
|
open System
|
||||||
open System.Collections.Immutable
|
open System.Collections.Immutable
|
||||||
open System.IO
|
open System.IO
|
||||||
|
open WoofWare.DotnetRuntimeLocator
|
||||||
|
|
||||||
module Program =
|
module Program =
|
||||||
/// Returns the pointer to the resulting array on the heap.
|
/// Returns the pointer to the resulting array on the heap.
|
||||||
@@ -34,14 +35,26 @@ module Program =
|
|||||||
let reallyMain (argv : string[]) : int =
|
let reallyMain (argv : string[]) : int =
|
||||||
match argv |> Array.toList with
|
match argv |> Array.toList with
|
||||||
| dllPath :: args ->
|
| dllPath :: args ->
|
||||||
|
let dotnetRuntimes =
|
||||||
|
// TODO: work out which runtime it expects to use. For now we just use the first one we find.
|
||||||
|
DotnetEnvironmentInfo.Get().Frameworks
|
||||||
|
|> Seq.map (fun fi -> Path.Combine (fi.Path, fi.Version.ToString ()))
|
||||||
|
|> Seq.toArray
|
||||||
|
|
||||||
use fileStream = new FileStream (dllPath, FileMode.Open, FileAccess.Read)
|
use fileStream = new FileStream (dllPath, FileMode.Open, FileAccess.Read)
|
||||||
let dumped = Assembly.read fileStream
|
let dumped = Assembly.read fileStream
|
||||||
let mainMethod = dumped.Methods.[dumped.MainMethod]
|
|
||||||
|
let entryPoint =
|
||||||
|
match dumped.MainMethod with
|
||||||
|
| None -> failwith $"No entry point in {dllPath}"
|
||||||
|
| Some d -> d
|
||||||
|
|
||||||
|
let mainMethod = dumped.Methods.[entryPoint]
|
||||||
|
|
||||||
if mainMethod.Signature.GenericParameterCount > 0 then
|
if mainMethod.Signature.GenericParameterCount > 0 then
|
||||||
failwith "Refusing to execute generic main method"
|
failwith "Refusing to execute generic main method"
|
||||||
|
|
||||||
let state = IlMachineState.Initial
|
let state = IlMachineState.Initial dumped
|
||||||
|
|
||||||
let arrayAllocation, state =
|
let arrayAllocation, state =
|
||||||
match mainMethod.Signature.ParameterTypes |> Seq.toList with
|
match mainMethod.Signature.ParameterTypes |> Seq.toList with
|
||||||
@@ -56,20 +69,14 @@ module Program =
|
|||||||
let state, mainThread =
|
let state, mainThread =
|
||||||
state
|
state
|
||||||
|> IlMachineState.AddThread
|
|> IlMachineState.AddThread
|
||||||
{
|
{ MethodState.Empty mainMethod None with
|
||||||
LocalVariables = ImmutableArray.Empty
|
|
||||||
IlOpIndex = 0
|
|
||||||
EvaluationStack = EvalStack.Empty
|
|
||||||
Arguments = ImmutableArray.Create (CliObject.OfManagedObject arrayAllocation)
|
Arguments = ImmutableArray.Create (CliObject.OfManagedObject arrayAllocation)
|
||||||
ExecutingMethod = dumped.Methods.[dumped.MainMethod]
|
|
||||||
LocalMemoryPool = ()
|
|
||||||
ReturnState = None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mutable state = state
|
let mutable state = state
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
state <- AbstractMachine.executeOneStep state dumped mainThread
|
state <- AbstractMachine.executeOneStep dotnetRuntimes state mainThread
|
||||||
|
|
||||||
0
|
0
|
||||||
| _ ->
|
| _ ->
|
||||||
|
@@ -13,6 +13,10 @@
|
|||||||
<ProjectReference Include="../WoofWare.PawPrint/WoofWare.PawPrint.fsproj"/>
|
<ProjectReference Include="../WoofWare.PawPrint/WoofWare.PawPrint.fsproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="WoofWare.DotnetRuntimeLocator" Version="0.1.11" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
namespace WoofWare.PawPrint
|
namespace WoofWare.PawPrint
|
||||||
|
|
||||||
open System
|
open System
|
||||||
|
open System.Collections.Generic
|
||||||
open System.Collections.Immutable
|
open System.Collections.Immutable
|
||||||
|
open System.IO
|
||||||
open System.Reflection.Metadata
|
open System.Reflection.Metadata
|
||||||
open Microsoft.FSharp.Core
|
open Microsoft.FSharp.Core
|
||||||
|
|
||||||
@@ -131,6 +133,19 @@ type MethodState =
|
|||||||
EvaluationStack = state.EvaluationStack |> EvalStack.Push state.Arguments.[index]
|
EvaluationStack = state.EvaluationStack |> EvalStack.Push state.Arguments.[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static member Empty (method : MethodInfo) (returnState : MethodState option) =
|
||||||
|
{
|
||||||
|
EvaluationStack = EvalStack.Empty
|
||||||
|
LocalVariables =
|
||||||
|
// TODO: use method.LocalsInit
|
||||||
|
ImmutableArray.Empty
|
||||||
|
IlOpIndex = 0
|
||||||
|
Arguments = Array.zeroCreate method.Parameters.Length |> ImmutableArray.ToImmutableArray
|
||||||
|
ExecutingMethod = method
|
||||||
|
LocalMemoryPool = ()
|
||||||
|
ReturnState = returnState
|
||||||
|
}
|
||||||
|
|
||||||
type ThreadState =
|
type ThreadState =
|
||||||
{
|
{
|
||||||
// TODO: thread-local storage, synchronisation state, exception handling context
|
// TODO: thread-local storage, synchronisation state, exception handling context
|
||||||
@@ -208,15 +223,25 @@ type IlMachineState =
|
|||||||
/// Multiple managed heaps are allowed, but we hopefully only need one.
|
/// Multiple managed heaps are allowed, but we hopefully only need one.
|
||||||
ManagedHeap : ManagedHeap
|
ManagedHeap : ManagedHeap
|
||||||
ThreadState : Map<ThreadId, ThreadState>
|
ThreadState : Map<ThreadId, ThreadState>
|
||||||
|
InternedStrings : ImmutableDictionary<StringToken, ManagedHeapAddress>
|
||||||
|
ActiveAssemblyName : string
|
||||||
|
LoadedAssemblies : Map<string, DumpedAssembly>
|
||||||
}
|
}
|
||||||
|
|
||||||
static member Initial : IlMachineState =
|
member this.ActiveAssembly = this.LoadedAssemblies.[this.ActiveAssemblyName]
|
||||||
|
|
||||||
|
static member Initial (entryAssembly : DumpedAssembly) : IlMachineState =
|
||||||
|
let assyName = entryAssembly.ThisAssemblyDefinition.Name
|
||||||
|
|
||||||
{
|
{
|
||||||
NextThreadId = 0
|
NextThreadId = 0
|
||||||
EvalStacks = Map.empty
|
EvalStacks = Map.empty
|
||||||
// CallStack = []
|
// CallStack = []
|
||||||
ManagedHeap = ManagedHeap.Empty
|
ManagedHeap = ManagedHeap.Empty
|
||||||
ThreadState = Map.empty
|
ThreadState = Map.empty
|
||||||
|
InternedStrings = ImmutableDictionary.Empty
|
||||||
|
ActiveAssemblyName = assyName
|
||||||
|
LoadedAssemblies = Map.ofList [ assyName, entryAssembly ]
|
||||||
}
|
}
|
||||||
|
|
||||||
static member AddThread (newThreadState : MethodState) (state : IlMachineState) : IlMachineState * ThreadId =
|
static member AddThread (newThreadState : MethodState) (state : IlMachineState) : IlMachineState * ThreadId =
|
||||||
@@ -229,6 +254,9 @@ type IlMachineState =
|
|||||||
// CallStack = state.CallStack
|
// CallStack = state.CallStack
|
||||||
ManagedHeap = state.ManagedHeap
|
ManagedHeap = state.ManagedHeap
|
||||||
ThreadState = state.ThreadState |> Map.add thread (ThreadState.New newThreadState)
|
ThreadState = state.ThreadState |> Map.add thread (ThreadState.New newThreadState)
|
||||||
|
InternedStrings = state.InternedStrings
|
||||||
|
ActiveAssemblyName = state.ActiveAssemblyName
|
||||||
|
LoadedAssemblies = state.LoadedAssemblies
|
||||||
}
|
}
|
||||||
|
|
||||||
newState, thread
|
newState, thread
|
||||||
@@ -241,6 +269,19 @@ type IlMachineState =
|
|||||||
ManagedHeap = heap
|
ManagedHeap = heap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static member PushToStack (o : CliObject) (thread : ThreadId) (state : IlMachineState) =
|
||||||
|
{ state with
|
||||||
|
EvalStacks =
|
||||||
|
state.EvalStacks
|
||||||
|
|> Map.change
|
||||||
|
thread
|
||||||
|
(fun s ->
|
||||||
|
match s with
|
||||||
|
| None -> failwith "tried to push to stack of nonexistent thread"
|
||||||
|
| Some stack -> EvalStack.Push o stack |> Some
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
static member SetArrayValue
|
static member SetArrayValue
|
||||||
(arrayAllocation : ManagedHeapAddress)
|
(arrayAllocation : ManagedHeapAddress)
|
||||||
(v : CliObject)
|
(v : CliObject)
|
||||||
@@ -294,7 +335,6 @@ module AbstractMachine =
|
|||||||
let internal executeNullary
|
let internal executeNullary
|
||||||
(state : IlMachineState)
|
(state : IlMachineState)
|
||||||
(currentThread : ThreadId)
|
(currentThread : ThreadId)
|
||||||
(dumped : DumpedAssembly)
|
|
||||||
(op : NullaryIlOp)
|
(op : NullaryIlOp)
|
||||||
: IlMachineState
|
: IlMachineState
|
||||||
=
|
=
|
||||||
@@ -377,27 +417,179 @@ module AbstractMachine =
|
|||||||
| Endfinally -> failwith "todo"
|
| Endfinally -> failwith "todo"
|
||||||
| Rethrow -> failwith "todo"
|
| Rethrow -> failwith "todo"
|
||||||
| Throw -> failwith "todo"
|
| Throw -> failwith "todo"
|
||||||
|
| Localloc -> failwith "todo"
|
||||||
|
| Stind_I -> failwith "todo"
|
||||||
|
| Stind_I1 -> failwith "todo"
|
||||||
|
| Stind_I2 -> failwith "todo"
|
||||||
|
| Stind_I4 -> failwith "todo"
|
||||||
|
| Stind_I8 -> failwith "todo"
|
||||||
|
| Stind_R4 -> failwith "todo"
|
||||||
|
| Stind_R8 -> failwith "todo"
|
||||||
|
| Ldind_i -> failwith "todo"
|
||||||
|
| Ldind_i1 -> failwith "todo"
|
||||||
|
| Ldind_i2 -> failwith "todo"
|
||||||
|
| Ldind_i4 -> failwith "todo"
|
||||||
|
| Ldind_i8 -> failwith "todo"
|
||||||
|
| Ldind_u1 -> failwith "todo"
|
||||||
|
| Ldind_u2 -> failwith "todo"
|
||||||
|
| Ldind_u4 -> failwith "todo"
|
||||||
|
| Ldind_u8 -> failwith "todo"
|
||||||
|
| Ldind_r4 -> failwith "todo"
|
||||||
|
| Ldind_r8 -> failwith "todo"
|
||||||
|
| Rem -> failwith "todo"
|
||||||
|
| Rem_un -> failwith "todo"
|
||||||
|
| Volatile -> failwith "todo"
|
||||||
|
| Tail -> failwith "todo"
|
||||||
|
| Conv_ovf_i_un -> failwith "todo"
|
||||||
|
| Conv_ovf_u_un -> failwith "todo"
|
||||||
|
| Conv_ovf_i1_un -> failwith "todo"
|
||||||
|
| Conv_ovf_u1_un -> failwith "todo"
|
||||||
|
| Conv_ovf_i2_un -> failwith "todo"
|
||||||
|
| Conv_ovf_u2_un -> failwith "todo"
|
||||||
|
| Conv_ovf_i4_un -> failwith "todo"
|
||||||
|
| Conv_ovf_u4_un -> failwith "todo"
|
||||||
|
| Conv_ovf_i8_un -> failwith "todo"
|
||||||
|
| Conv_ovf_u8_un -> failwith "todo"
|
||||||
|
| Conv_ovf_i -> failwith "todo"
|
||||||
|
| Conv_ovf_u -> failwith "todo"
|
||||||
|
| Neg -> failwith "todo"
|
||||||
|
| Not -> failwith "todo"
|
||||||
|
| Ldind_ref -> failwith "todo"
|
||||||
|
| Stind_ref -> failwith "todo"
|
||||||
|
| Ldelem_i -> failwith "todo"
|
||||||
|
| Ldelem_i1 -> failwith "todo"
|
||||||
|
| Ldelem_u1 -> failwith "todo"
|
||||||
|
| Ldelem_i2 -> failwith "todo"
|
||||||
|
| Ldelem_u2 -> failwith "todo"
|
||||||
|
| Ldelem_i4 -> failwith "todo"
|
||||||
|
| Ldelem_u4 -> failwith "todo"
|
||||||
|
| Ldelem_i8 -> failwith "todo"
|
||||||
|
| Ldelem_u8 -> failwith "todo"
|
||||||
|
| Ldelem_r4 -> failwith "todo"
|
||||||
|
| Ldelem_r8 -> failwith "todo"
|
||||||
|
| Ldelem_ref -> failwith "todo"
|
||||||
|
| Stelem_i -> failwith "todo"
|
||||||
|
| Stelem_i1 -> failwith "todo"
|
||||||
|
| Stelem_u1 -> failwith "todo"
|
||||||
|
| Stelem_i2 -> failwith "todo"
|
||||||
|
| Stelem_u2 -> failwith "todo"
|
||||||
|
| Stelem_i4 -> failwith "todo"
|
||||||
|
| Stelem_u4 -> failwith "todo"
|
||||||
|
| Stelem_i8 -> failwith "todo"
|
||||||
|
| Stelem_u8 -> failwith "todo"
|
||||||
|
| Stelem_r4 -> failwith "todo"
|
||||||
|
| Stelem_r8 -> failwith "todo"
|
||||||
|
| Stelem_ref -> failwith "todo"
|
||||||
|
|
||||||
let private executeUnaryMetadata
|
let private executeUnaryMetadata
|
||||||
|
(dotnetRuntimeDirs : string[])
|
||||||
(op : UnaryMetadataTokenIlOp)
|
(op : UnaryMetadataTokenIlOp)
|
||||||
(metadataToken : MetadataToken)
|
(metadataToken : MetadataToken)
|
||||||
(state : IlMachineState)
|
(state : IlMachineState)
|
||||||
(dumped : DumpedAssembly)
|
|
||||||
(thread : ThreadId)
|
(thread : ThreadId)
|
||||||
: IlMachineState
|
: IlMachineState
|
||||||
=
|
=
|
||||||
match op with
|
match op with
|
||||||
| Call ->
|
| Call ->
|
||||||
let handle =
|
let state, methodToCall =
|
||||||
match metadataToken.Kind with
|
match metadataToken with
|
||||||
| HandleKind.MethodSpecification -> MethodSpecificationHandle.op_Explicit metadataToken
|
| MetadataToken.MethodSpecification h ->
|
||||||
|
let spec = state.ActiveAssembly.MethodSpecs.[h]
|
||||||
|
|
||||||
|
match spec.Method with
|
||||||
|
| MetadataToken.MethodDef token -> state, state.ActiveAssembly.Methods.[token]
|
||||||
|
| k -> failwith $"Unrecognised kind: %O{k}"
|
||||||
|
| MetadataToken.MemberReference h ->
|
||||||
|
let mem = state.ActiveAssembly.Members.[h]
|
||||||
|
|
||||||
|
let memberSig =
|
||||||
|
match mem.Signature with
|
||||||
|
| MemberSignature.Field _ -> failwith "Trying to CALL a field?!"
|
||||||
|
| MemberSignature.Method method -> method
|
||||||
|
|
||||||
|
let memberName : string = state.ActiveAssembly.Strings mem.Name
|
||||||
|
|
||||||
|
let parent =
|
||||||
|
match mem.Parent with
|
||||||
|
| MetadataToken.TypeReference typeRef -> state.ActiveAssembly.TypeRefs.[typeRef]
|
||||||
|
| parent -> failwith $"Unexpected: {parent}"
|
||||||
|
|
||||||
|
match parent.ResolutionScope with
|
||||||
|
| AssemblyReference r ->
|
||||||
|
let state, assy, newAssyName =
|
||||||
|
let assemblyRef = state.ActiveAssembly.AssemblyReferences.[r]
|
||||||
|
let assemblyName = state.ActiveAssembly.Strings assemblyRef.Name
|
||||||
|
|
||||||
|
match state.LoadedAssemblies.TryGetValue assemblyName with
|
||||||
|
| true, v -> state, v, assemblyName
|
||||||
|
| false, _ ->
|
||||||
|
let assy =
|
||||||
|
dotnetRuntimeDirs
|
||||||
|
|> Seq.choose (fun dir ->
|
||||||
|
let file = Path.Combine (dir, assemblyName + ".dll")
|
||||||
|
|
||||||
|
try
|
||||||
|
use f = File.OpenRead file
|
||||||
|
Console.Error.WriteLine $"Loading {file}"
|
||||||
|
Assembly.read f |> Some
|
||||||
|
with :? FileNotFoundException ->
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|> Seq.exactlyOne
|
||||||
|
|
||||||
|
{ state with
|
||||||
|
LoadedAssemblies = state.LoadedAssemblies |> Map.add assemblyName assy
|
||||||
|
},
|
||||||
|
assy,
|
||||||
|
assemblyName
|
||||||
|
|
||||||
|
let nsPath =
|
||||||
|
state.ActiveAssembly.Strings(parent.Namespace).Split '.' |> Array.toList
|
||||||
|
|
||||||
|
let targetNs = assy.NonRootNamespaces.[nsPath]
|
||||||
|
|
||||||
|
let targetType =
|
||||||
|
targetNs.TypeDefinitions
|
||||||
|
|> Seq.choose (fun td ->
|
||||||
|
let ty = assy.TypeDefs.[td]
|
||||||
|
|
||||||
|
if ty.Name = state.ActiveAssembly.Strings parent.Name then
|
||||||
|
Some ty
|
||||||
|
else
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|> Seq.exactlyOne
|
||||||
|
|
||||||
|
let availableMethods =
|
||||||
|
targetType.Methods
|
||||||
|
|> List.filter (fun mi -> mi.Name = memberName)
|
||||||
|
|> List.filter (fun mi -> mi.Signature = memberSig)
|
||||||
|
|
||||||
|
let method =
|
||||||
|
match availableMethods with
|
||||||
|
| [] -> failwith $"Could not find member {memberName} with the right signature in CALL"
|
||||||
|
| [ x ] -> x
|
||||||
|
| _ -> failwith $"Multiple overloads matching signature for call to {memberName}!"
|
||||||
|
|
||||||
|
{ state with
|
||||||
|
ActiveAssemblyName = newAssyName
|
||||||
|
},
|
||||||
|
method
|
||||||
|
| k -> failwith $"Unexpected: {k}"
|
||||||
|
| MetadataToken.MethodDef defn -> state, state.ActiveAssembly.Methods.[defn]
|
||||||
| k -> failwith $"Unrecognised kind: %O{k}"
|
| k -> failwith $"Unrecognised kind: %O{k}"
|
||||||
|
|
||||||
let method =
|
let threadState =
|
||||||
dumped.Methods.[MethodDefinitionHandle.op_Explicit dumped.MethodSpecs.[handle].Method]
|
let threadState = state.ThreadState.[thread]
|
||||||
|
|
||||||
|
{ threadState with
|
||||||
|
MethodState = MethodState.Empty methodToCall (Some threadState.MethodState)
|
||||||
|
}
|
||||||
|
|
||||||
|
{ state with
|
||||||
|
ThreadState = state.ThreadState |> Map.add thread threadState
|
||||||
|
}
|
||||||
|
|
||||||
failwith "TODO: now do this!"
|
|
||||||
state
|
|
||||||
| Callvirt -> failwith "todo"
|
| Callvirt -> failwith "todo"
|
||||||
| Castclass -> failwith "todo"
|
| Castclass -> failwith "todo"
|
||||||
| Newobj -> failwith "todo"
|
| Newobj -> failwith "todo"
|
||||||
@@ -413,14 +605,61 @@ module AbstractMachine =
|
|||||||
| Unbox_Any -> failwith "todo"
|
| Unbox_Any -> failwith "todo"
|
||||||
| Stelem -> failwith "todo"
|
| Stelem -> failwith "todo"
|
||||||
| Ldelem -> failwith "todo"
|
| Ldelem -> failwith "todo"
|
||||||
|
| Initobj -> failwith "todo"
|
||||||
|
| Ldsflda -> failwith "todo"
|
||||||
|
| Ldftn -> failwith "todo"
|
||||||
|
| Stobj -> failwith "todo"
|
||||||
|
| Constrained -> failwith "todo"
|
||||||
|
| Ldtoken -> failwith "todo"
|
||||||
|
| Cpobj -> failwith "todo"
|
||||||
|
| Ldobj -> failwith "todo"
|
||||||
|
|
||||||
let executeOneStep (state : IlMachineState) (dumped : DumpedAssembly) (thread : ThreadId) : IlMachineState =
|
let private executeUnaryStringToken
|
||||||
|
(op : UnaryStringTokenIlOp)
|
||||||
|
(sh : StringToken)
|
||||||
|
(state : IlMachineState)
|
||||||
|
(thread : ThreadId)
|
||||||
|
: IlMachineState
|
||||||
|
=
|
||||||
|
match op with
|
||||||
|
| UnaryStringTokenIlOp.Ldstr ->
|
||||||
|
let addressToLoad, state =
|
||||||
|
match state.InternedStrings.TryGetValue sh with
|
||||||
|
| false, _ ->
|
||||||
|
let toAllocate = state.ActiveAssembly.Strings sh
|
||||||
|
let addr, state = IlMachineState.Allocate (ReferenceType.String toAllocate) state
|
||||||
|
|
||||||
|
addr,
|
||||||
|
{ state with
|
||||||
|
InternedStrings = state.InternedStrings.Add (sh, addr)
|
||||||
|
}
|
||||||
|
| true, v -> v, state
|
||||||
|
|
||||||
|
let state =
|
||||||
|
IlMachineState.PushToStack
|
||||||
|
(CliObject.Basic (BasicCliObject.ObjectReference (Some addressToLoad)))
|
||||||
|
thread
|
||||||
|
state
|
||||||
|
// +1 for the opcode, +4 for the bytes of the handle.
|
||||||
|
// TODO: some opcodes are multiple bytes! Should deal with that.
|
||||||
|
let mutable state = state
|
||||||
|
|
||||||
|
for i = 0 to 4 do
|
||||||
|
state <- IlMachineState.AdvanceProgramCounter thread state
|
||||||
|
|
||||||
|
state
|
||||||
|
|
||||||
|
let executeOneStep (dotnetRuntimePath : string[]) (state : IlMachineState) (thread : ThreadId) : IlMachineState =
|
||||||
let instruction = state.ThreadState.[thread].MethodState
|
let instruction = state.ThreadState.[thread].MethodState
|
||||||
|
|
||||||
|
Console.Error.WriteLine
|
||||||
|
$"[DBG] Executing one step! Now executing: {instruction.IlOpIndex} in {instruction.ExecutingMethod.Name}"
|
||||||
|
|
||||||
match instruction.ExecutingMethod.Locations.[instruction.IlOpIndex] with
|
match instruction.ExecutingMethod.Locations.[instruction.IlOpIndex] with
|
||||||
| IlOp.Nullary op -> executeNullary state thread dumped op
|
| IlOp.Nullary op -> executeNullary state thread op
|
||||||
| UnaryConst unaryConstIlOp -> failwith "todo"
|
| UnaryConst unaryConstIlOp -> failwith "todo"
|
||||||
| UnaryMetadataToken (unaryMetadataTokenIlOp, bytes) ->
|
| UnaryMetadataToken (unaryMetadataTokenIlOp, bytes) ->
|
||||||
executeUnaryMetadata unaryMetadataTokenIlOp bytes state dumped thread
|
executeUnaryMetadata dotnetRuntimePath unaryMetadataTokenIlOp bytes state thread
|
||||||
| Switch immutableArray -> failwith "todo"
|
| Switch immutableArray -> failwith "todo"
|
||||||
| UnaryStringToken (unaryStringTokenIlOp, stringHandle) -> failwith "todo"
|
| UnaryStringToken (unaryStringTokenIlOp, stringHandle) ->
|
||||||
|
executeUnaryStringToken unaryStringTokenIlOp stringHandle state thread
|
||||||
|
@@ -9,36 +9,121 @@ open System.Reflection.Metadata.Ecma335
|
|||||||
open System.Reflection.PortableExecutable
|
open System.Reflection.PortableExecutable
|
||||||
open Microsoft.FSharp.Core
|
open Microsoft.FSharp.Core
|
||||||
|
|
||||||
|
type AssemblyDefinition =
|
||||||
|
{
|
||||||
|
Name : string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Namespace =
|
||||||
|
{
|
||||||
|
Name : StringToken
|
||||||
|
Parent : NamespaceDefinitionHandle
|
||||||
|
TypeDefinitions : ImmutableArray<TypeDefinitionHandle>
|
||||||
|
ExportedTypes : ImmutableArray<ExportedTypeHandle>
|
||||||
|
}
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module Namespace =
|
||||||
|
/// Returns also the children.
|
||||||
|
let make
|
||||||
|
(getString : StringHandle -> string)
|
||||||
|
(getNamespace : NamespaceDefinitionHandle -> NamespaceDefinition)
|
||||||
|
(ns : NamespaceDefinition)
|
||||||
|
: Namespace * ImmutableDictionary<string list, Namespace>
|
||||||
|
=
|
||||||
|
let children = ImmutableDictionary.CreateBuilder ()
|
||||||
|
|
||||||
|
let rec inner (path : string list) (ns : NamespaceDefinition) : Namespace =
|
||||||
|
for child in ns.NamespaceDefinitions do
|
||||||
|
let rendered = getNamespace child
|
||||||
|
let location = getString rendered.Name :: path
|
||||||
|
children.Add (List.rev location, inner location rendered)
|
||||||
|
|
||||||
|
{
|
||||||
|
Name = StringToken.String ns.Name
|
||||||
|
Parent = ns.Parent
|
||||||
|
TypeDefinitions = ns.TypeDefinitions
|
||||||
|
ExportedTypes = ns.ExportedTypes
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = inner [] ns
|
||||||
|
result, children.ToImmutable ()
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module AssemblyDefinition =
|
||||||
|
let make
|
||||||
|
(strings : StringToken -> string)
|
||||||
|
(assy : System.Reflection.Metadata.AssemblyDefinition)
|
||||||
|
: AssemblyDefinition
|
||||||
|
=
|
||||||
|
{
|
||||||
|
Name = strings (StringToken.String assy.Name)
|
||||||
|
}
|
||||||
|
|
||||||
type DumpedAssembly =
|
type DumpedAssembly =
|
||||||
{
|
{
|
||||||
Types : TypeInfo list
|
TypeDefs : IReadOnlyDictionary<TypeDefinitionHandle, TypeInfo>
|
||||||
|
TypeRefs : IReadOnlyDictionary<TypeReferenceHandle, TypeRef>
|
||||||
Methods : IReadOnlyDictionary<MethodDefinitionHandle, MethodInfo>
|
Methods : IReadOnlyDictionary<MethodDefinitionHandle, MethodInfo>
|
||||||
MainMethod : MethodDefinitionHandle
|
Members : IReadOnlyDictionary<MemberReferenceHandle, WoofWare.PawPrint.MemberReference<MetadataToken>>
|
||||||
|
MainMethod : MethodDefinitionHandle option
|
||||||
/// Map of four-byte int token to metadata
|
/// Map of four-byte int token to metadata
|
||||||
MethodDefinitions : Map<int, MethodDefinition>
|
MethodDefinitions : Map<int, MethodDefinition>
|
||||||
MethodSpecs : ImmutableDictionary<MethodSpecificationHandle, MethodSpecification>
|
MethodSpecs : ImmutableDictionary<MethodSpecificationHandle, MethodSpec>
|
||||||
|
Strings : StringToken -> string
|
||||||
|
AssemblyReferences : ImmutableDictionary<AssemblyReferenceHandle, WoofWare.PawPrint.AssemblyReference>
|
||||||
|
ThisAssemblyDefinition : AssemblyDefinition
|
||||||
|
RootNamespace : Namespace
|
||||||
|
NonRootNamespaces : ImmutableDictionary<string list, Namespace>
|
||||||
|
// TODO: work out how to render all the strings up front, then drop this
|
||||||
|
PeReader : PEReader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IDisposable with
|
||||||
|
member this.Dispose () = this.PeReader.Dispose ()
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module Assembly =
|
module Assembly =
|
||||||
let read (dllBytes : Stream) : DumpedAssembly =
|
let read (dllBytes : Stream) : DumpedAssembly =
|
||||||
use peReader = new PEReader (dllBytes)
|
let peReader = new PEReader (dllBytes)
|
||||||
let metadataReader = peReader.GetMetadataReader ()
|
let metadataReader = peReader.GetMetadataReader ()
|
||||||
|
|
||||||
let entryPoint =
|
let entryPoint =
|
||||||
peReader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress
|
peReader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress
|
||||||
|> fun x -> if x = 0 then failwith "No entry point" else x
|
|> fun x -> if x = 0 then None else Some x
|
||||||
|
|
||||||
let entryPointMethod = MetadataTokens.MethodDefinitionHandle entryPoint
|
let entryPointMethod =
|
||||||
|
entryPoint |> Option.map MetadataTokens.MethodDefinitionHandle
|
||||||
|
|
||||||
let result =
|
let typeRefs =
|
||||||
metadataReader.TypeDefinitions
|
let builder = ImmutableDictionary.CreateBuilder ()
|
||||||
|> Seq.map (TypeInfo.read peReader metadataReader)
|
|
||||||
|> Seq.toList
|
|
||||||
|
|
||||||
|
for ty in metadataReader.TypeReferences do
|
||||||
|
let typeRef = metadataReader.GetTypeReference ty
|
||||||
|
|
||||||
|
let result =
|
||||||
|
{
|
||||||
|
Name = StringToken.String typeRef.Name
|
||||||
|
Namespace = StringToken.String typeRef.Namespace
|
||||||
|
ResolutionScope = MetadataToken.ofEntityHandle typeRef.ResolutionScope
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Add (ty, result)
|
||||||
|
|
||||||
|
builder.ToImmutable ()
|
||||||
|
|
||||||
|
let typeDefs =
|
||||||
|
let builder = ImmutableDictionary.CreateBuilder ()
|
||||||
|
|
||||||
|
for ty in metadataReader.TypeDefinitions do
|
||||||
|
builder.Add (ty, TypeInfo.read peReader metadataReader ty)
|
||||||
|
|
||||||
|
builder.ToImmutable ()
|
||||||
|
|
||||||
|
// TODO: this probably misses any methods out which aren't associated with a type definition?
|
||||||
let methods =
|
let methods =
|
||||||
result
|
typeDefs
|
||||||
|> List.collect (fun ty -> ty.Methods |> List.map (fun mi -> KeyValuePair (mi.Handle, mi)))
|
|> Seq.collect (fun (KeyValue (_, ty)) -> ty.Methods |> List.map (fun mi -> KeyValuePair (mi.Handle, mi)))
|
||||||
|> ImmutableDictionary.CreateRange
|
|> ImmutableDictionary.CreateRange
|
||||||
|
|
||||||
let methodDefnMetadata =
|
let methodDefnMetadata =
|
||||||
@@ -57,20 +142,62 @@ module Assembly =
|
|||||||
(fun i ->
|
(fun i ->
|
||||||
let i = i + 1
|
let i = i + 1
|
||||||
let handle = MetadataTokens.MethodSpecificationHandle i
|
let handle = MetadataTokens.MethodSpecificationHandle i
|
||||||
KeyValuePair (handle, metadataReader.GetMethodSpecification handle)
|
KeyValuePair (handle, MethodSpec.make (metadataReader.GetMethodSpecification handle))
|
||||||
)
|
)
|
||||||
|> ImmutableDictionary.CreateRange
|
|> ImmutableDictionary.CreateRange
|
||||||
|
|
||||||
|
let memberReferences =
|
||||||
|
let builder = ImmutableDictionary.CreateBuilder ()
|
||||||
|
|
||||||
|
for c in metadataReader.MemberReferences do
|
||||||
|
builder.Add (
|
||||||
|
c,
|
||||||
|
MemberReference.make<MetadataToken>
|
||||||
|
MetadataToken.ofEntityHandle
|
||||||
|
(metadataReader.GetMemberReference c)
|
||||||
|
)
|
||||||
|
|
||||||
|
builder.ToImmutable ()
|
||||||
|
|
||||||
|
// TODO: render all this up front
|
||||||
|
let strings (token : StringToken) =
|
||||||
|
match token with
|
||||||
|
| StringToken.String s -> metadataReader.GetString s
|
||||||
|
| StringToken.UserString s -> metadataReader.GetUserString s
|
||||||
|
|
||||||
|
let assemblyRefs =
|
||||||
|
let builder = ImmutableDictionary.CreateBuilder ()
|
||||||
|
|
||||||
|
for ref in metadataReader.AssemblyReferences do
|
||||||
|
builder.Add (ref, AssemblyReference.make (metadataReader.GetAssemblyReference ref))
|
||||||
|
|
||||||
|
builder.ToImmutable ()
|
||||||
|
|
||||||
|
let assy =
|
||||||
|
metadataReader.GetAssemblyDefinition () |> AssemblyDefinition.make strings
|
||||||
|
|
||||||
|
let rootNamespace, nonRootNamespaces =
|
||||||
|
metadataReader.GetNamespaceDefinitionRoot ()
|
||||||
|
|> Namespace.make metadataReader.GetString metadataReader.GetNamespaceDefinition
|
||||||
|
|
||||||
{
|
{
|
||||||
Types = result
|
TypeDefs = typeDefs
|
||||||
|
TypeRefs = typeRefs
|
||||||
MainMethod = entryPointMethod
|
MainMethod = entryPointMethod
|
||||||
Methods = methods
|
Methods = methods
|
||||||
MethodDefinitions = methodDefnMetadata
|
MethodDefinitions = methodDefnMetadata
|
||||||
MethodSpecs = methodSpecs
|
MethodSpecs = methodSpecs
|
||||||
|
Members = memberReferences
|
||||||
|
Strings = strings
|
||||||
|
AssemblyReferences = assemblyRefs
|
||||||
|
ThisAssemblyDefinition = assy
|
||||||
|
RootNamespace = rootNamespace
|
||||||
|
NonRootNamespaces = nonRootNamespaces
|
||||||
|
PeReader = peReader
|
||||||
}
|
}
|
||||||
|
|
||||||
let print (main : MethodDefinitionHandle) (dumped : DumpedAssembly) : unit =
|
let print (main : MethodDefinitionHandle) (dumped : DumpedAssembly) : unit =
|
||||||
for typ in dumped.Types do
|
for KeyValue (_, typ) in dumped.TypeDefs do
|
||||||
printfn "\nType: %s.%s" typ.Namespace typ.Name
|
printfn "\nType: %s.%s" typ.Namespace typ.Name
|
||||||
|
|
||||||
for method in typ.Methods do
|
for method in typ.Methods do
|
||||||
|
@@ -1,7 +1,157 @@
|
|||||||
namespace WoofWare.PawPrint
|
namespace WoofWare.PawPrint
|
||||||
|
|
||||||
|
open System
|
||||||
open System.Collections.Immutable
|
open System.Collections.Immutable
|
||||||
|
open System.Reflection
|
||||||
open System.Reflection.Metadata
|
open System.Reflection.Metadata
|
||||||
|
open System.Reflection.Metadata.Ecma335
|
||||||
|
|
||||||
|
type StringToken =
|
||||||
|
| UserString of UserStringHandle
|
||||||
|
| String of StringHandle
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module StringToken =
|
||||||
|
let ofInt (value : int) : StringToken =
|
||||||
|
match LanguagePrimitives.EnumOfValue<byte, HandleKind> (byte (value &&& 0xFF000000 >>> 24)) with
|
||||||
|
| HandleKind.UserString -> StringToken.UserString (MetadataTokens.UserStringHandle value)
|
||||||
|
| HandleKind.String -> StringToken.String (MetadataTokens.StringHandle value)
|
||||||
|
| v -> failwith $"Unrecognised string handle kind: {v}"
|
||||||
|
|
||||||
|
type MetadataToken =
|
||||||
|
| MethodDef of MethodDefinitionHandle
|
||||||
|
| MethodSpecification of MethodSpecificationHandle
|
||||||
|
| MemberReference of MemberReferenceHandle
|
||||||
|
| TypeReference of TypeReferenceHandle
|
||||||
|
| ModuleDefinition of ModuleDefinitionHandle
|
||||||
|
| AssemblyReference of AssemblyReferenceHandle
|
||||||
|
| TypeSpecification of TypeSpecificationHandle
|
||||||
|
| TypeDefinition of TypeDefinitionHandle
|
||||||
|
| FieldDefinition of FieldDefinitionHandle
|
||||||
|
| Parameter of ParameterHandle
|
||||||
|
| InterfaceImplementation of InterfaceImplementationHandle
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module MetadataToken =
|
||||||
|
let ofInt (value : int32) : MetadataToken =
|
||||||
|
let asRowNum = value &&& 0x00FFFFFF
|
||||||
|
|
||||||
|
match LanguagePrimitives.EnumOfValue<byte, HandleKind> (byte (value &&& 0xFF000000 >>> 24)) with
|
||||||
|
| HandleKind.ModuleDefinition -> MetadataToken.ModuleDefinition (failwith "TODO")
|
||||||
|
| HandleKind.TypeReference -> MetadataToken.TypeReference (MetadataTokens.TypeReferenceHandle asRowNum)
|
||||||
|
| HandleKind.TypeDefinition -> MetadataToken.TypeDefinition (MetadataTokens.TypeDefinitionHandle asRowNum)
|
||||||
|
| HandleKind.FieldDefinition -> MetadataToken.FieldDefinition (MetadataTokens.FieldDefinitionHandle asRowNum)
|
||||||
|
| HandleKind.MethodDefinition -> MetadataToken.MethodDef (MetadataTokens.MethodDefinitionHandle asRowNum)
|
||||||
|
| HandleKind.Parameter -> MetadataToken.Parameter (MetadataTokens.ParameterHandle asRowNum)
|
||||||
|
| HandleKind.InterfaceImplementation ->
|
||||||
|
MetadataToken.InterfaceImplementation (MetadataTokens.InterfaceImplementationHandle asRowNum)
|
||||||
|
| HandleKind.MemberReference -> MetadataToken.MemberReference (MetadataTokens.MemberReferenceHandle asRowNum)
|
||||||
|
| HandleKind.Constant -> failwith "todo"
|
||||||
|
| HandleKind.CustomAttribute -> failwith "todo"
|
||||||
|
| HandleKind.DeclarativeSecurityAttribute -> failwith "todo"
|
||||||
|
| HandleKind.StandaloneSignature -> failwith "todo"
|
||||||
|
| HandleKind.EventDefinition -> failwith "todo"
|
||||||
|
| HandleKind.PropertyDefinition -> failwith "todo"
|
||||||
|
| HandleKind.MethodImplementation -> failwith "todo"
|
||||||
|
| HandleKind.ModuleReference -> failwith "todo"
|
||||||
|
| HandleKind.TypeSpecification ->
|
||||||
|
MetadataToken.TypeSpecification (MetadataTokens.TypeSpecificationHandle asRowNum)
|
||||||
|
| HandleKind.AssemblyDefinition -> failwith "todo"
|
||||||
|
| HandleKind.AssemblyReference ->
|
||||||
|
MetadataToken.AssemblyReference (MetadataTokens.AssemblyReferenceHandle asRowNum)
|
||||||
|
| HandleKind.AssemblyFile -> failwith "todo"
|
||||||
|
| HandleKind.ExportedType -> failwith "todo"
|
||||||
|
| HandleKind.ManifestResource -> failwith "todo"
|
||||||
|
| HandleKind.GenericParameter -> failwith "todo"
|
||||||
|
| HandleKind.MethodSpecification ->
|
||||||
|
MetadataToken.MethodSpecification (MetadataTokens.MethodSpecificationHandle asRowNum)
|
||||||
|
| HandleKind.GenericParameterConstraint -> failwith "todo"
|
||||||
|
| HandleKind.Document -> failwith "todo"
|
||||||
|
| HandleKind.MethodDebugInformation -> failwith "todo"
|
||||||
|
| HandleKind.LocalScope -> failwith "todo"
|
||||||
|
| HandleKind.LocalVariable -> failwith "todo"
|
||||||
|
| HandleKind.LocalConstant -> failwith "todo"
|
||||||
|
| HandleKind.ImportScope -> failwith "todo"
|
||||||
|
| HandleKind.CustomDebugInformation -> failwith "todo"
|
||||||
|
| HandleKind.UserString -> failwith "todo"
|
||||||
|
| HandleKind.Blob -> failwith "todo"
|
||||||
|
| HandleKind.Guid -> failwith "todo"
|
||||||
|
| HandleKind.String -> failwith "todo"
|
||||||
|
| HandleKind.NamespaceDefinition -> failwith "todo"
|
||||||
|
| h -> failwith $"Unrecognised kind: {h}"
|
||||||
|
|
||||||
|
let ofEntityHandle (eh : EntityHandle) : MetadataToken = ofInt (eh.GetHashCode ())
|
||||||
|
|
||||||
|
type MemberSignature =
|
||||||
|
| Field of TypeDefn
|
||||||
|
| Method of TypeMethodSignature<TypeDefn>
|
||||||
|
|
||||||
|
type MemberReference<'parent> =
|
||||||
|
{
|
||||||
|
Name : StringToken
|
||||||
|
Parent : 'parent
|
||||||
|
Signature : MemberSignature
|
||||||
|
}
|
||||||
|
|
||||||
|
type MemberRefSigSwitch =
|
||||||
|
| Default
|
||||||
|
| Field
|
||||||
|
| VarArg
|
||||||
|
| Generic
|
||||||
|
|
||||||
|
static member Identify (b : byte) =
|
||||||
|
match b &&& 0xFuy with
|
||||||
|
| 0uy -> MemberRefSigSwitch.Default
|
||||||
|
| 5uy -> MemberRefSigSwitch.VarArg
|
||||||
|
| 6uy -> MemberRefSigSwitch.Field
|
||||||
|
| 0x10uy -> MemberRefSigSwitch.Generic
|
||||||
|
| n -> failwith $"Bad member ref sig: %i{n}"
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module MemberReference =
|
||||||
|
let make<'parent>
|
||||||
|
(makeParent : EntityHandle -> 'parent)
|
||||||
|
(mr : System.Reflection.Metadata.MemberReference)
|
||||||
|
: MemberReference<'parent>
|
||||||
|
=
|
||||||
|
let name = StringToken.String mr.Name
|
||||||
|
|
||||||
|
let signature =
|
||||||
|
try
|
||||||
|
mr.DecodeMethodSignature (TypeDefn.typeProvider, ()) |> Choice1Of2
|
||||||
|
with :? BadImageFormatException ->
|
||||||
|
mr.DecodeFieldSignature (TypeDefn.typeProvider, ()) |> Choice2Of2
|
||||||
|
|
||||||
|
let signature =
|
||||||
|
match signature with
|
||||||
|
| Choice1Of2 methodSignature -> TypeMethodSignature.make methodSignature |> MemberSignature.Method
|
||||||
|
| Choice2Of2 typeDefn -> MemberSignature.Field typeDefn
|
||||||
|
|
||||||
|
{
|
||||||
|
Name = name
|
||||||
|
// Horrible abuse to get this as an int
|
||||||
|
Parent = makeParent mr.Parent
|
||||||
|
Signature = signature
|
||||||
|
}
|
||||||
|
|
||||||
|
type AssemblyReference =
|
||||||
|
{
|
||||||
|
Culture : StringToken
|
||||||
|
Flags : AssemblyFlags
|
||||||
|
Name : StringToken
|
||||||
|
Version : Version
|
||||||
|
}
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module AssemblyReference =
|
||||||
|
let make (ref : System.Reflection.Metadata.AssemblyReference) : AssemblyReference =
|
||||||
|
{
|
||||||
|
Culture = StringToken.String ref.Culture
|
||||||
|
Flags = ref.Flags
|
||||||
|
Name = StringToken.String ref.Name
|
||||||
|
Version = ref.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
type NullaryIlOp =
|
type NullaryIlOp =
|
||||||
| Nop
|
| Nop
|
||||||
@@ -47,9 +197,15 @@ type NullaryIlOp =
|
|||||||
| Mul_ovf_un
|
| Mul_ovf_un
|
||||||
| Div
|
| Div
|
||||||
| Div_un
|
| Div_un
|
||||||
|
| Rem
|
||||||
|
| Rem_un
|
||||||
|
| Neg
|
||||||
|
| Not
|
||||||
| Shr
|
| Shr
|
||||||
| Shr_un
|
| Shr_un
|
||||||
| Shl
|
| Shl
|
||||||
|
| Conv_ovf_i
|
||||||
|
| Conv_ovf_u
|
||||||
| And
|
| And
|
||||||
| Or
|
| Or
|
||||||
| Xor
|
| Xor
|
||||||
@@ -70,6 +226,63 @@ type NullaryIlOp =
|
|||||||
| Endfinally
|
| Endfinally
|
||||||
| Rethrow
|
| Rethrow
|
||||||
| Throw
|
| Throw
|
||||||
|
| Localloc
|
||||||
|
| Ldind_ref
|
||||||
|
| Stind_ref
|
||||||
|
| Stind_I
|
||||||
|
| Stind_I1
|
||||||
|
| Stind_I2
|
||||||
|
| Stind_I4
|
||||||
|
| Stind_I8
|
||||||
|
| Stind_R4
|
||||||
|
| Stind_R8
|
||||||
|
| Ldind_i
|
||||||
|
| Ldind_i1
|
||||||
|
| Ldind_i2
|
||||||
|
| Ldind_i4
|
||||||
|
| Ldind_i8
|
||||||
|
| Ldind_u1
|
||||||
|
| Ldind_u2
|
||||||
|
| Ldind_u4
|
||||||
|
| Ldind_u8
|
||||||
|
| Ldind_r4
|
||||||
|
| Ldind_r8
|
||||||
|
| Volatile
|
||||||
|
| Tail
|
||||||
|
| Conv_ovf_i_un
|
||||||
|
| Conv_ovf_u_un
|
||||||
|
| Conv_ovf_i1_un
|
||||||
|
| Conv_ovf_u1_un
|
||||||
|
| Conv_ovf_i2_un
|
||||||
|
| Conv_ovf_u2_un
|
||||||
|
| Conv_ovf_i4_un
|
||||||
|
| Conv_ovf_u4_un
|
||||||
|
| Conv_ovf_i8_un
|
||||||
|
| Conv_ovf_u8_un
|
||||||
|
| Ldelem_i
|
||||||
|
| Ldelem_i1
|
||||||
|
| Ldelem_u1
|
||||||
|
| Ldelem_i2
|
||||||
|
| Ldelem_u2
|
||||||
|
| Ldelem_i4
|
||||||
|
| Ldelem_u4
|
||||||
|
| Ldelem_i8
|
||||||
|
| Ldelem_u8
|
||||||
|
| Ldelem_r4
|
||||||
|
| Ldelem_r8
|
||||||
|
| Ldelem_ref
|
||||||
|
| Stelem_i
|
||||||
|
| Stelem_i1
|
||||||
|
| Stelem_u1
|
||||||
|
| Stelem_i2
|
||||||
|
| Stelem_u2
|
||||||
|
| Stelem_i4
|
||||||
|
| Stelem_u4
|
||||||
|
| Stelem_i8
|
||||||
|
| Stelem_u8
|
||||||
|
| Stelem_r4
|
||||||
|
| Stelem_r8
|
||||||
|
| Stelem_ref
|
||||||
|
|
||||||
type UnaryConstIlOp =
|
type UnaryConstIlOp =
|
||||||
| Stloc of uint16
|
| Stloc of uint16
|
||||||
@@ -88,6 +301,11 @@ type UnaryConstIlOp =
|
|||||||
| Ble_s of int8
|
| Ble_s of int8
|
||||||
| Bgt_s of int8
|
| Bgt_s of int8
|
||||||
| Bge_s of int8
|
| Bge_s of int8
|
||||||
|
| Beq of int32
|
||||||
|
| Blt of int32
|
||||||
|
| Ble of int32
|
||||||
|
| Bgt of int32
|
||||||
|
| Bge of int32
|
||||||
| Bne_un_s of int8
|
| Bne_un_s of int8
|
||||||
| Bge_un_s of int8
|
| Bge_un_s of int8
|
||||||
| Bgt_un_s of int8
|
| Bgt_un_s of int8
|
||||||
@@ -122,16 +340,20 @@ type UnaryMetadataTokenIlOp =
|
|||||||
| Ldfld
|
| Ldfld
|
||||||
| Ldflda
|
| Ldflda
|
||||||
| Ldsfld
|
| Ldsfld
|
||||||
|
| Ldsflda
|
||||||
| Unbox_Any
|
| Unbox_Any
|
||||||
| Stelem
|
| Stelem
|
||||||
| Ldelem
|
| Ldelem
|
||||||
|
| Initobj
|
||||||
|
| Ldftn
|
||||||
|
| Stobj
|
||||||
|
| Constrained
|
||||||
|
| Ldtoken
|
||||||
|
| Cpobj
|
||||||
|
| Ldobj
|
||||||
|
|
||||||
type UnaryStringTokenIlOp = | Ldstr
|
type UnaryStringTokenIlOp = | Ldstr
|
||||||
|
|
||||||
/// A four-byte metadata token.
|
|
||||||
type MetadataToken = EntityHandle
|
|
||||||
type StringToken = StringHandle
|
|
||||||
|
|
||||||
type IlOp =
|
type IlOp =
|
||||||
| Nullary of NullaryIlOp
|
| Nullary of NullaryIlOp
|
||||||
| UnaryConst of UnaryConstIlOp
|
| UnaryConst of UnaryConstIlOp
|
||||||
|
169
WoofWare.PawPrint/TypeDefn.fs
Normal file
169
WoofWare.PawPrint/TypeDefn.fs
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
namespace WoofWare.PawPrint
|
||||||
|
|
||||||
|
open System.Collections.Immutable
|
||||||
|
open System.Reflection.Metadata
|
||||||
|
open System.Reflection.Metadata.Ecma335
|
||||||
|
|
||||||
|
type TypeMethodSignature<'Types> =
|
||||||
|
{
|
||||||
|
Header : SignatureHeader
|
||||||
|
ParameterTypes : 'Types list
|
||||||
|
GenericParameterCount : int
|
||||||
|
RequiredParameterCount : int
|
||||||
|
ReturnType : 'Types
|
||||||
|
}
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module TypeMethodSignature =
|
||||||
|
let make<'T> (p : MethodSignature<'T>) : TypeMethodSignature<'T> =
|
||||||
|
{
|
||||||
|
Header = p.Header
|
||||||
|
ReturnType = p.ReturnType
|
||||||
|
ParameterTypes = List.ofSeq p.ParameterTypes
|
||||||
|
GenericParameterCount = p.GenericParameterCount
|
||||||
|
RequiredParameterCount = p.RequiredParameterCount
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type PrimitiveType =
|
||||||
|
| Void
|
||||||
|
| Boolean
|
||||||
|
| Char
|
||||||
|
| SByte
|
||||||
|
| Byte
|
||||||
|
| Int16
|
||||||
|
| UInt16
|
||||||
|
| Int32
|
||||||
|
| UInt32
|
||||||
|
| Int64
|
||||||
|
| UInt64
|
||||||
|
| Single
|
||||||
|
| Double
|
||||||
|
| String
|
||||||
|
| TypedReference
|
||||||
|
| IntPtr
|
||||||
|
| UIntPtr
|
||||||
|
| Object
|
||||||
|
|
||||||
|
static member OfEnum (ptc : PrimitiveTypeCode) : PrimitiveType =
|
||||||
|
match ptc with
|
||||||
|
| PrimitiveTypeCode.Void -> PrimitiveType.Void
|
||||||
|
| PrimitiveTypeCode.Boolean -> PrimitiveType.Boolean
|
||||||
|
| PrimitiveTypeCode.Char -> PrimitiveType.Char
|
||||||
|
| PrimitiveTypeCode.SByte -> PrimitiveType.SByte
|
||||||
|
| PrimitiveTypeCode.Byte -> PrimitiveType.Byte
|
||||||
|
| PrimitiveTypeCode.Int16 -> PrimitiveType.Int16
|
||||||
|
| PrimitiveTypeCode.UInt16 -> PrimitiveType.UInt16
|
||||||
|
| PrimitiveTypeCode.Int32 -> PrimitiveType.Int32
|
||||||
|
| PrimitiveTypeCode.UInt32 -> PrimitiveType.UInt32
|
||||||
|
| PrimitiveTypeCode.Int64 -> PrimitiveType.Int64
|
||||||
|
| PrimitiveTypeCode.UInt64 -> PrimitiveType.UInt64
|
||||||
|
| PrimitiveTypeCode.Single -> PrimitiveType.Single
|
||||||
|
| PrimitiveTypeCode.Double -> PrimitiveType.Double
|
||||||
|
| PrimitiveTypeCode.String -> PrimitiveType.String
|
||||||
|
| PrimitiveTypeCode.TypedReference -> PrimitiveType.TypedReference
|
||||||
|
| PrimitiveTypeCode.IntPtr -> PrimitiveType.IntPtr
|
||||||
|
| PrimitiveTypeCode.UIntPtr -> PrimitiveType.UIntPtr
|
||||||
|
| PrimitiveTypeCode.Object -> PrimitiveType.Object
|
||||||
|
| x -> failwithf $"Unrecognised primitive type code: %O{x}"
|
||||||
|
|
||||||
|
type TypeDefn =
|
||||||
|
| PrimitiveType of PrimitiveType
|
||||||
|
| Pinned of TypeDefn
|
||||||
|
| Pointer of TypeDefn
|
||||||
|
| Byref of TypeDefn
|
||||||
|
| OneDimensionalArrayLowerBoundZero of elements : TypeDefn
|
||||||
|
| Modified of original : TypeDefn * afterMod : TypeDefn * modificationRequired : bool
|
||||||
|
| FromReference of SignatureTypeKind
|
||||||
|
| FromDefinition of SignatureTypeKind
|
||||||
|
| GenericInstantiation of generic : TypeDefn * args : ImmutableArray<TypeDefn>
|
||||||
|
| FunctionPointer of TypeMethodSignature<TypeDefn>
|
||||||
|
| GenericTypeParameter of index : int
|
||||||
|
| GenericMethodParameter of index : int
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module TypeDefn =
|
||||||
|
let fromTypeCode (s : SignatureTypeCode) : TypeDefn =
|
||||||
|
match s with
|
||||||
|
| SignatureTypeCode.Invalid -> failwith "todo"
|
||||||
|
| SignatureTypeCode.Void -> TypeDefn.PrimitiveType PrimitiveType.Void
|
||||||
|
| SignatureTypeCode.Boolean -> TypeDefn.PrimitiveType PrimitiveType.Boolean
|
||||||
|
| SignatureTypeCode.Char -> TypeDefn.PrimitiveType PrimitiveType.Char
|
||||||
|
| SignatureTypeCode.SByte -> TypeDefn.PrimitiveType PrimitiveType.SByte
|
||||||
|
| SignatureTypeCode.Byte -> TypeDefn.PrimitiveType PrimitiveType.Byte
|
||||||
|
| SignatureTypeCode.Int16 -> TypeDefn.PrimitiveType PrimitiveType.Int16
|
||||||
|
| SignatureTypeCode.UInt16 -> TypeDefn.PrimitiveType PrimitiveType.UInt16
|
||||||
|
| SignatureTypeCode.Int32 -> TypeDefn.PrimitiveType PrimitiveType.Int32
|
||||||
|
| SignatureTypeCode.UInt32 -> TypeDefn.PrimitiveType PrimitiveType.UInt32
|
||||||
|
| SignatureTypeCode.Int64 -> TypeDefn.PrimitiveType PrimitiveType.Int64
|
||||||
|
| SignatureTypeCode.UInt64 -> TypeDefn.PrimitiveType PrimitiveType.UInt64
|
||||||
|
| SignatureTypeCode.Single -> TypeDefn.PrimitiveType PrimitiveType.Single
|
||||||
|
| SignatureTypeCode.Double -> TypeDefn.PrimitiveType PrimitiveType.Double
|
||||||
|
| SignatureTypeCode.String -> TypeDefn.PrimitiveType PrimitiveType.String
|
||||||
|
| SignatureTypeCode.Pointer -> failwith "todo"
|
||||||
|
| SignatureTypeCode.ByReference -> failwith "TODO"
|
||||||
|
| SignatureTypeCode.GenericTypeParameter -> failwith "todo"
|
||||||
|
| SignatureTypeCode.Array -> failwith "todo"
|
||||||
|
| SignatureTypeCode.GenericTypeInstance -> failwith "todo"
|
||||||
|
| SignatureTypeCode.TypedReference -> TypeDefn.PrimitiveType PrimitiveType.TypedReference
|
||||||
|
| SignatureTypeCode.IntPtr -> TypeDefn.PrimitiveType PrimitiveType.IntPtr
|
||||||
|
| SignatureTypeCode.UIntPtr -> failwith "todo"
|
||||||
|
| SignatureTypeCode.FunctionPointer -> failwith "todo"
|
||||||
|
| SignatureTypeCode.Object -> failwith "todo"
|
||||||
|
| SignatureTypeCode.SZArray -> failwith "todo"
|
||||||
|
| SignatureTypeCode.GenericMethodParameter -> failwith "todo"
|
||||||
|
| SignatureTypeCode.RequiredModifier -> failwith "todo"
|
||||||
|
| SignatureTypeCode.OptionalModifier -> failwith "todo"
|
||||||
|
| SignatureTypeCode.TypeHandle -> failwith "todo"
|
||||||
|
| SignatureTypeCode.Sentinel -> failwith "todo"
|
||||||
|
| SignatureTypeCode.Pinned -> failwith "todo"
|
||||||
|
| x -> failwith $"Unrecognised type code: {x}"
|
||||||
|
|
||||||
|
let typeProvider =
|
||||||
|
{ new ISignatureTypeProvider<TypeDefn, unit> with
|
||||||
|
member this.GetArrayType (elementType : TypeDefn, shape : ArrayShape) : TypeDefn = failwith "TODO"
|
||||||
|
member this.GetByReferenceType (elementType : TypeDefn) : TypeDefn = TypeDefn.Byref elementType
|
||||||
|
|
||||||
|
member this.GetSZArrayType (elementType : TypeDefn) : TypeDefn =
|
||||||
|
TypeDefn.OneDimensionalArrayLowerBoundZero elementType
|
||||||
|
|
||||||
|
member this.GetPrimitiveType (elementType : PrimitiveTypeCode) : TypeDefn =
|
||||||
|
PrimitiveType.OfEnum elementType |> TypeDefn.PrimitiveType
|
||||||
|
|
||||||
|
member this.GetGenericInstantiation
|
||||||
|
(generic : TypeDefn, typeArguments : ImmutableArray<TypeDefn>)
|
||||||
|
: TypeDefn
|
||||||
|
=
|
||||||
|
TypeDefn.GenericInstantiation (generic, typeArguments)
|
||||||
|
|
||||||
|
member this.GetTypeFromDefinition
|
||||||
|
(reader : MetadataReader, handle : TypeDefinitionHandle, rawTypeKind : byte)
|
||||||
|
: TypeDefn
|
||||||
|
=
|
||||||
|
let handle : EntityHandle = TypeDefinitionHandle.op_Implicit handle
|
||||||
|
let typeKind = reader.ResolveSignatureTypeKind (handle, rawTypeKind)
|
||||||
|
|
||||||
|
TypeDefn.FromDefinition typeKind
|
||||||
|
|
||||||
|
member this.GetTypeFromReference
|
||||||
|
(reader : MetadataReader, handle : TypeReferenceHandle, rawTypeKind : byte)
|
||||||
|
: TypeDefn
|
||||||
|
=
|
||||||
|
let handle : EntityHandle = TypeReferenceHandle.op_Implicit handle
|
||||||
|
let typeKind = reader.ResolveSignatureTypeKind (handle, rawTypeKind)
|
||||||
|
TypeDefn.FromReference typeKind
|
||||||
|
|
||||||
|
member this.GetPointerType (typeCode : TypeDefn) : TypeDefn = TypeDefn.Pointer typeCode
|
||||||
|
|
||||||
|
member this.GetFunctionPointerType (signature) =
|
||||||
|
TypeDefn.FunctionPointer (TypeMethodSignature.make signature)
|
||||||
|
|
||||||
|
member this.GetGenericMethodParameter (genericContext, index) = TypeDefn.GenericMethodParameter index
|
||||||
|
member this.GetGenericTypeParameter (genericContext, index) = TypeDefn.GenericTypeParameter index
|
||||||
|
|
||||||
|
member this.GetModifiedType (modifier, unmodifiedType, isRequired) =
|
||||||
|
TypeDefn.Modified (unmodifiedType, modifier, isRequired)
|
||||||
|
|
||||||
|
member this.GetPinnedType (elementType) = TypeDefn.Pinned elementType
|
||||||
|
member this.GetTypeFromSpecification (reader, genericContext, handle, rawTypeKind) = failwith "todo"
|
||||||
|
}
|
@@ -3,7 +3,9 @@ namespace WoofWare.PawPrint
|
|||||||
#nowarn "9"
|
#nowarn "9"
|
||||||
|
|
||||||
open System
|
open System
|
||||||
|
open System.Collections.Generic
|
||||||
open System.Collections.Immutable
|
open System.Collections.Immutable
|
||||||
|
open System.Reflection
|
||||||
open System.Reflection.Metadata
|
open System.Reflection.Metadata
|
||||||
open System.Reflection.Metadata.Ecma335
|
open System.Reflection.Metadata.Ecma335
|
||||||
open System.Reflection.PortableExecutable
|
open System.Reflection.PortableExecutable
|
||||||
@@ -22,83 +24,19 @@ type GenericParameter =
|
|||||||
SequenceNumber : int
|
SequenceNumber : int
|
||||||
}
|
}
|
||||||
|
|
||||||
type TypeMethodSignature<'Types> =
|
type MethodSpec =
|
||||||
{
|
{
|
||||||
Header : SignatureHeader
|
Method : MetadataToken
|
||||||
ParameterTypes : ImmutableArray<'Types>
|
|
||||||
GenericParameterCount : int
|
|
||||||
RequiredParameterCount : int
|
|
||||||
ReturnType : 'Types
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module TypeMethodSignature =
|
module MethodSpec =
|
||||||
let make<'T> (p : MethodSignature<'T>) : TypeMethodSignature<'T> =
|
let make (p : MethodSpecification) : MethodSpec =
|
||||||
{
|
{
|
||||||
Header = p.Header
|
// Horrible abuse to get this as an int
|
||||||
ReturnType = p.ReturnType
|
Method = MetadataToken.ofInt (p.Method.GetHashCode ())
|
||||||
ParameterTypes = p.ParameterTypes
|
|
||||||
GenericParameterCount = p.GenericParameterCount
|
|
||||||
RequiredParameterCount = p.RequiredParameterCount
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PrimitiveType =
|
|
||||||
| Void
|
|
||||||
| Boolean
|
|
||||||
| Char
|
|
||||||
| SByte
|
|
||||||
| Byte
|
|
||||||
| Int16
|
|
||||||
| UInt16
|
|
||||||
| Int32
|
|
||||||
| UInt32
|
|
||||||
| Int64
|
|
||||||
| UInt64
|
|
||||||
| Single
|
|
||||||
| Double
|
|
||||||
| String
|
|
||||||
| TypedReference
|
|
||||||
| IntPtr
|
|
||||||
| UIntPtr
|
|
||||||
| Object
|
|
||||||
|
|
||||||
static member OfEnum (ptc : PrimitiveTypeCode) : PrimitiveType =
|
|
||||||
match ptc with
|
|
||||||
| PrimitiveTypeCode.Void -> PrimitiveType.Void
|
|
||||||
| PrimitiveTypeCode.Boolean -> PrimitiveType.Boolean
|
|
||||||
| PrimitiveTypeCode.Char -> PrimitiveType.Char
|
|
||||||
| PrimitiveTypeCode.SByte -> PrimitiveType.SByte
|
|
||||||
| PrimitiveTypeCode.Byte -> PrimitiveType.Byte
|
|
||||||
| PrimitiveTypeCode.Int16 -> PrimitiveType.Int16
|
|
||||||
| PrimitiveTypeCode.UInt16 -> PrimitiveType.UInt16
|
|
||||||
| PrimitiveTypeCode.Int32 -> PrimitiveType.Int32
|
|
||||||
| PrimitiveTypeCode.UInt32 -> PrimitiveType.UInt32
|
|
||||||
| PrimitiveTypeCode.Int64 -> PrimitiveType.Int64
|
|
||||||
| PrimitiveTypeCode.UInt64 -> PrimitiveType.UInt64
|
|
||||||
| PrimitiveTypeCode.Single -> PrimitiveType.Single
|
|
||||||
| PrimitiveTypeCode.Double -> PrimitiveType.Double
|
|
||||||
| PrimitiveTypeCode.String -> PrimitiveType.String
|
|
||||||
| PrimitiveTypeCode.TypedReference -> PrimitiveType.TypedReference
|
|
||||||
| PrimitiveTypeCode.IntPtr -> PrimitiveType.IntPtr
|
|
||||||
| PrimitiveTypeCode.UIntPtr -> PrimitiveType.UIntPtr
|
|
||||||
| PrimitiveTypeCode.Object -> PrimitiveType.Object
|
|
||||||
| x -> failwithf $"Unrecognised primitive type code: %O{x}"
|
|
||||||
|
|
||||||
type TypeDefn =
|
|
||||||
| PrimitiveType of PrimitiveType
|
|
||||||
| Pinned of TypeDefn
|
|
||||||
| Pointer of TypeDefn
|
|
||||||
| Byref of TypeDefn
|
|
||||||
| OneDimensionalArrayLowerBoundZero of elements : TypeDefn
|
|
||||||
| Modified of original : TypeDefn * afterMod : TypeDefn * modificationRequired : bool
|
|
||||||
| FromReference of SignatureTypeKind
|
|
||||||
| FromDefinition of SignatureTypeKind
|
|
||||||
| GenericInstantiation of generic : TypeDefn * args : ImmutableArray<TypeDefn>
|
|
||||||
| FunctionPointer of TypeMethodSignature<TypeDefn>
|
|
||||||
| GenericTypeParameter of index : int
|
|
||||||
| GenericMethodParameter of index : int
|
|
||||||
|
|
||||||
|
|
||||||
type MethodInfo =
|
type MethodInfo =
|
||||||
{
|
{
|
||||||
Handle : MethodDefinitionHandle
|
Handle : MethodDefinitionHandle
|
||||||
@@ -110,6 +48,8 @@ type MethodInfo =
|
|||||||
Parameters : Parameter ImmutableArray
|
Parameters : Parameter ImmutableArray
|
||||||
Generics : GenericParameter ImmutableArray
|
Generics : GenericParameter ImmutableArray
|
||||||
Signature : TypeMethodSignature<TypeDefn>
|
Signature : TypeMethodSignature<TypeDefn>
|
||||||
|
IsPinvokeImpl : bool
|
||||||
|
LocalsInit : bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type TypeInfo =
|
type TypeInfo =
|
||||||
@@ -117,6 +57,14 @@ type TypeInfo =
|
|||||||
Namespace : string
|
Namespace : string
|
||||||
Name : string
|
Name : string
|
||||||
Methods : MethodInfo list
|
Methods : MethodInfo list
|
||||||
|
MethodImpls : ImmutableDictionary<MethodImplementationHandle, EntityHandle>
|
||||||
|
}
|
||||||
|
|
||||||
|
type TypeRef =
|
||||||
|
{
|
||||||
|
Name : StringToken
|
||||||
|
Namespace : StringToken
|
||||||
|
ResolutionScope : MetadataToken
|
||||||
}
|
}
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
@@ -131,14 +79,23 @@ module TypeInfo =
|
|||||||
LanguagePrimitives.EnumOfValue (uint16 op)
|
LanguagePrimitives.EnumOfValue (uint16 op)
|
||||||
|
|
||||||
let private readMetadataToken (reader : byref<BlobReader>) : MetadataToken =
|
let private readMetadataToken (reader : byref<BlobReader>) : MetadataToken =
|
||||||
reader.ReadUInt32 () |> int |> MetadataTokens.EntityHandle
|
reader.ReadUInt32 () |> int |> MetadataToken.ofInt
|
||||||
|
|
||||||
let private readStringToken (reader : byref<BlobReader>) : StringToken =
|
let private readStringToken (reader : byref<BlobReader>) : StringToken =
|
||||||
reader.ReadUInt32 () |> int |> MetadataTokens.StringHandle
|
let value = reader.ReadUInt32 () |> int
|
||||||
|
StringToken.ofInt value
|
||||||
|
|
||||||
let private readMethodBody (peReader : PEReader) (methodDef : MethodDefinition) : (IlOp * int) list =
|
type private MethodBody =
|
||||||
|
{
|
||||||
|
Instructions : (IlOp * int) list
|
||||||
|
LocalInit : bool
|
||||||
|
MaxStackSize : int
|
||||||
|
ExceptionRegions : ImmutableArray<ExceptionRegion>
|
||||||
|
}
|
||||||
|
|
||||||
|
let private readMethodBody (peReader : PEReader) (methodDef : MethodDefinition) : MethodBody option =
|
||||||
if methodDef.RelativeVirtualAddress = 0 then
|
if methodDef.RelativeVirtualAddress = 0 then
|
||||||
[]
|
None
|
||||||
else
|
else
|
||||||
let methodBody = peReader.GetMethodBody methodDef.RelativeVirtualAddress
|
let methodBody = peReader.GetMethodBody methodDef.RelativeVirtualAddress
|
||||||
let ilBytes = methodBody.GetILBytes ()
|
let ilBytes = methodBody.GetILBytes ()
|
||||||
@@ -213,11 +170,11 @@ module TypeInfo =
|
|||||||
| ILOpCode.Br -> IlOp.UnaryConst (UnaryConstIlOp.Br (reader.ReadInt32 ()))
|
| ILOpCode.Br -> IlOp.UnaryConst (UnaryConstIlOp.Br (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Brfalse -> IlOp.UnaryConst (UnaryConstIlOp.Brfalse (reader.ReadInt32 ()))
|
| ILOpCode.Brfalse -> IlOp.UnaryConst (UnaryConstIlOp.Brfalse (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Brtrue -> IlOp.UnaryConst (UnaryConstIlOp.Brtrue (reader.ReadInt32 ()))
|
| ILOpCode.Brtrue -> IlOp.UnaryConst (UnaryConstIlOp.Brtrue (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Beq -> failwith "todo"
|
| ILOpCode.Beq -> IlOp.UnaryConst (UnaryConstIlOp.Beq (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Bge -> failwith "todo"
|
| ILOpCode.Bge -> IlOp.UnaryConst (UnaryConstIlOp.Bge (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Bgt -> failwith "todo"
|
| ILOpCode.Bgt -> IlOp.UnaryConst (UnaryConstIlOp.Bgt (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Ble -> failwith "todo"
|
| ILOpCode.Ble -> IlOp.UnaryConst (UnaryConstIlOp.Ble (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Blt -> failwith "todo"
|
| ILOpCode.Blt -> IlOp.UnaryConst (UnaryConstIlOp.Blt (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Bne_un -> IlOp.UnaryConst (UnaryConstIlOp.Bne_un (reader.ReadInt32 ()))
|
| ILOpCode.Bne_un -> IlOp.UnaryConst (UnaryConstIlOp.Bne_un (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Bge_un -> IlOp.UnaryConst (UnaryConstIlOp.Bge_un (reader.ReadInt32 ()))
|
| ILOpCode.Bge_un -> IlOp.UnaryConst (UnaryConstIlOp.Bge_un (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Bgt_un -> IlOp.UnaryConst (UnaryConstIlOp.Bgt_un (reader.ReadInt32 ()))
|
| ILOpCode.Bgt_un -> IlOp.UnaryConst (UnaryConstIlOp.Bgt_un (reader.ReadInt32 ()))
|
||||||
@@ -236,39 +193,39 @@ module TypeInfo =
|
|||||||
result.Add (reader.ReadInt32 ())
|
result.Add (reader.ReadInt32 ())
|
||||||
|
|
||||||
IlOp.Switch (result.ToImmutable ())
|
IlOp.Switch (result.ToImmutable ())
|
||||||
| ILOpCode.Ldind_i1 -> failwith "todo"
|
| ILOpCode.Ldind_i -> IlOp.Nullary NullaryIlOp.Ldind_i
|
||||||
| ILOpCode.Ldind_u1 -> failwith "todo"
|
| ILOpCode.Ldind_i1 -> IlOp.Nullary NullaryIlOp.Ldind_i1
|
||||||
| ILOpCode.Ldind_i2 -> failwith "todo"
|
| ILOpCode.Ldind_u1 -> IlOp.Nullary NullaryIlOp.Ldind_u1
|
||||||
| ILOpCode.Ldind_u2 -> failwith "todo"
|
| ILOpCode.Ldind_i2 -> IlOp.Nullary NullaryIlOp.Ldind_i2
|
||||||
| ILOpCode.Ldind_i4 -> failwith "todo"
|
| ILOpCode.Ldind_u2 -> IlOp.Nullary NullaryIlOp.Ldind_u2
|
||||||
| ILOpCode.Ldind_u4 -> failwith "todo"
|
| ILOpCode.Ldind_i4 -> IlOp.Nullary NullaryIlOp.Ldind_i4
|
||||||
| ILOpCode.Ldind_i8 -> failwith "todo"
|
| ILOpCode.Ldind_u4 -> IlOp.Nullary NullaryIlOp.Ldind_u4
|
||||||
| ILOpCode.Ldind_i -> failwith "todo"
|
| ILOpCode.Ldind_i8 -> IlOp.Nullary NullaryIlOp.Ldind_i8
|
||||||
| ILOpCode.Ldind_r4 -> failwith "todo"
|
| ILOpCode.Ldind_r4 -> IlOp.Nullary NullaryIlOp.Ldind_r4
|
||||||
| ILOpCode.Ldind_r8 -> failwith "todo"
|
| ILOpCode.Ldind_r8 -> IlOp.Nullary NullaryIlOp.Ldind_r8
|
||||||
| ILOpCode.Ldind_ref -> failwith "todo"
|
| ILOpCode.Ldind_ref -> IlOp.Nullary NullaryIlOp.Ldind_ref
|
||||||
| ILOpCode.Stind_ref -> failwith "todo"
|
| ILOpCode.Stind_ref -> IlOp.Nullary NullaryIlOp.Stind_ref
|
||||||
| ILOpCode.Stind_i1 -> failwith "todo"
|
| ILOpCode.Stind_i1 -> IlOp.Nullary NullaryIlOp.Stind_I1
|
||||||
| ILOpCode.Stind_i2 -> failwith "todo"
|
| ILOpCode.Stind_i2 -> IlOp.Nullary NullaryIlOp.Stind_I2
|
||||||
| ILOpCode.Stind_i4 -> failwith "todo"
|
| ILOpCode.Stind_i4 -> IlOp.Nullary NullaryIlOp.Stind_I4
|
||||||
| ILOpCode.Stind_i8 -> failwith "todo"
|
| ILOpCode.Stind_i8 -> IlOp.Nullary NullaryIlOp.Stind_I8
|
||||||
| ILOpCode.Stind_r4 -> failwith "todo"
|
| ILOpCode.Stind_r4 -> IlOp.Nullary NullaryIlOp.Stind_R4
|
||||||
| ILOpCode.Stind_r8 -> failwith "todo"
|
| ILOpCode.Stind_r8 -> IlOp.Nullary NullaryIlOp.Stind_R8
|
||||||
| ILOpCode.Add -> IlOp.Nullary NullaryIlOp.Add
|
| ILOpCode.Add -> IlOp.Nullary NullaryIlOp.Add
|
||||||
| ILOpCode.Sub -> IlOp.Nullary NullaryIlOp.Sub
|
| ILOpCode.Sub -> IlOp.Nullary NullaryIlOp.Sub
|
||||||
| ILOpCode.Mul -> IlOp.Nullary NullaryIlOp.Mul
|
| ILOpCode.Mul -> IlOp.Nullary NullaryIlOp.Mul
|
||||||
| ILOpCode.Div -> IlOp.Nullary NullaryIlOp.Div
|
| ILOpCode.Div -> IlOp.Nullary NullaryIlOp.Div
|
||||||
| ILOpCode.Div_un -> IlOp.Nullary NullaryIlOp.Div_un
|
| ILOpCode.Div_un -> IlOp.Nullary NullaryIlOp.Div_un
|
||||||
| ILOpCode.Rem -> failwith "todo"
|
| ILOpCode.Rem -> IlOp.Nullary NullaryIlOp.Rem
|
||||||
| ILOpCode.Rem_un -> failwith "todo"
|
| ILOpCode.Rem_un -> IlOp.Nullary NullaryIlOp.Rem_un
|
||||||
| ILOpCode.And -> IlOp.Nullary NullaryIlOp.And
|
| ILOpCode.And -> IlOp.Nullary NullaryIlOp.And
|
||||||
| ILOpCode.Or -> IlOp.Nullary NullaryIlOp.Or
|
| ILOpCode.Or -> IlOp.Nullary NullaryIlOp.Or
|
||||||
| ILOpCode.Xor -> IlOp.Nullary NullaryIlOp.Xor
|
| ILOpCode.Xor -> IlOp.Nullary NullaryIlOp.Xor
|
||||||
| ILOpCode.Shl -> IlOp.Nullary NullaryIlOp.Shl
|
| ILOpCode.Shl -> IlOp.Nullary NullaryIlOp.Shl
|
||||||
| ILOpCode.Shr -> IlOp.Nullary NullaryIlOp.Shr
|
| ILOpCode.Shr -> IlOp.Nullary NullaryIlOp.Shr
|
||||||
| ILOpCode.Shr_un -> IlOp.Nullary NullaryIlOp.Shr_un
|
| ILOpCode.Shr_un -> IlOp.Nullary NullaryIlOp.Shr_un
|
||||||
| ILOpCode.Neg -> failwith "todo"
|
| ILOpCode.Neg -> IlOp.Nullary NullaryIlOp.Neg
|
||||||
| ILOpCode.Not -> failwith "todo"
|
| ILOpCode.Not -> IlOp.Nullary NullaryIlOp.Not
|
||||||
| ILOpCode.Conv_i1 -> IlOp.Nullary NullaryIlOp.Conv_I1
|
| ILOpCode.Conv_i1 -> IlOp.Nullary NullaryIlOp.Conv_I1
|
||||||
| ILOpCode.Conv_i2 -> IlOp.Nullary NullaryIlOp.Conv_I2
|
| ILOpCode.Conv_i2 -> IlOp.Nullary NullaryIlOp.Conv_I2
|
||||||
| ILOpCode.Conv_i4 -> IlOp.Nullary NullaryIlOp.Conv_I4
|
| ILOpCode.Conv_i4 -> IlOp.Nullary NullaryIlOp.Conv_I4
|
||||||
@@ -279,8 +236,10 @@ module TypeInfo =
|
|||||||
| ILOpCode.Conv_u8 -> IlOp.Nullary NullaryIlOp.Conv_U8
|
| ILOpCode.Conv_u8 -> IlOp.Nullary NullaryIlOp.Conv_U8
|
||||||
| ILOpCode.Callvirt ->
|
| ILOpCode.Callvirt ->
|
||||||
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Callvirt, readMetadataToken &reader)
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Callvirt, readMetadataToken &reader)
|
||||||
| ILOpCode.Cpobj -> failwith "todo"
|
| ILOpCode.Cpobj ->
|
||||||
| ILOpCode.Ldobj -> failwith "todo"
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Cpobj, readMetadataToken &reader)
|
||||||
|
| ILOpCode.Ldobj ->
|
||||||
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Ldobj, readMetadataToken &reader)
|
||||||
| ILOpCode.Ldstr -> IlOp.UnaryStringToken (UnaryStringTokenIlOp.Ldstr, readStringToken &reader)
|
| ILOpCode.Ldstr -> IlOp.UnaryStringToken (UnaryStringTokenIlOp.Ldstr, readStringToken &reader)
|
||||||
| ILOpCode.Newobj ->
|
| ILOpCode.Newobj ->
|
||||||
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Newobj, readMetadataToken &reader)
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Newobj, readMetadataToken &reader)
|
||||||
@@ -299,20 +258,22 @@ module TypeInfo =
|
|||||||
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Stfld, readMetadataToken &reader)
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Stfld, readMetadataToken &reader)
|
||||||
| ILOpCode.Ldsfld ->
|
| ILOpCode.Ldsfld ->
|
||||||
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Ldsfld, readMetadataToken &reader)
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Ldsfld, readMetadataToken &reader)
|
||||||
| ILOpCode.Ldsflda -> failwith "todo"
|
| ILOpCode.Ldsflda ->
|
||||||
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Ldsflda, readMetadataToken &reader)
|
||||||
| ILOpCode.Stsfld ->
|
| ILOpCode.Stsfld ->
|
||||||
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Stsfld, readMetadataToken &reader)
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Stsfld, readMetadataToken &reader)
|
||||||
| ILOpCode.Stobj -> failwith "todo"
|
| ILOpCode.Stobj ->
|
||||||
| ILOpCode.Conv_ovf_i1_un -> failwith "todo"
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Stobj, readMetadataToken &reader)
|
||||||
| ILOpCode.Conv_ovf_i2_un -> failwith "todo"
|
| ILOpCode.Conv_ovf_i_un -> IlOp.Nullary NullaryIlOp.Conv_ovf_i_un
|
||||||
| ILOpCode.Conv_ovf_i4_un -> failwith "todo"
|
| ILOpCode.Conv_ovf_i1_un -> IlOp.Nullary NullaryIlOp.Conv_ovf_i1_un
|
||||||
| ILOpCode.Conv_ovf_i8_un -> failwith "todo"
|
| ILOpCode.Conv_ovf_i2_un -> IlOp.Nullary NullaryIlOp.Conv_ovf_i2_un
|
||||||
| ILOpCode.Conv_ovf_u1_un -> failwith "todo"
|
| ILOpCode.Conv_ovf_i4_un -> IlOp.Nullary NullaryIlOp.Conv_ovf_i4_un
|
||||||
| ILOpCode.Conv_ovf_u2_un -> failwith "todo"
|
| ILOpCode.Conv_ovf_i8_un -> IlOp.Nullary NullaryIlOp.Conv_ovf_i8_un
|
||||||
| ILOpCode.Conv_ovf_u4_un -> failwith "todo"
|
| ILOpCode.Conv_ovf_u_un -> IlOp.Nullary NullaryIlOp.Conv_ovf_u_un
|
||||||
| ILOpCode.Conv_ovf_u8_un -> failwith "todo"
|
| ILOpCode.Conv_ovf_u1_un -> IlOp.Nullary NullaryIlOp.Conv_ovf_u1_un
|
||||||
| ILOpCode.Conv_ovf_i_un -> failwith "todo"
|
| ILOpCode.Conv_ovf_u2_un -> IlOp.Nullary NullaryIlOp.Conv_ovf_u2_un
|
||||||
| ILOpCode.Conv_ovf_u_un -> failwith "todo"
|
| ILOpCode.Conv_ovf_u4_un -> IlOp.Nullary NullaryIlOp.Conv_ovf_u4_un
|
||||||
|
| ILOpCode.Conv_ovf_u8_un -> IlOp.Nullary NullaryIlOp.Conv_ovf_u8_un
|
||||||
| ILOpCode.Box ->
|
| ILOpCode.Box ->
|
||||||
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Box, readMetadataToken &reader)
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Box, readMetadataToken &reader)
|
||||||
| ILOpCode.Newarr ->
|
| ILOpCode.Newarr ->
|
||||||
@@ -320,25 +281,25 @@ module TypeInfo =
|
|||||||
| ILOpCode.Ldlen -> IlOp.Nullary NullaryIlOp.LdLen
|
| ILOpCode.Ldlen -> IlOp.Nullary NullaryIlOp.LdLen
|
||||||
| ILOpCode.Ldelema ->
|
| ILOpCode.Ldelema ->
|
||||||
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Ldelema, readMetadataToken &reader)
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Ldelema, readMetadataToken &reader)
|
||||||
| ILOpCode.Ldelem_i1 -> failwith "todo"
|
| ILOpCode.Ldelem_i1 -> IlOp.Nullary NullaryIlOp.Ldelem_i1
|
||||||
| ILOpCode.Ldelem_u1 -> failwith "todo"
|
| ILOpCode.Ldelem_u1 -> IlOp.Nullary NullaryIlOp.Ldelem_u1
|
||||||
| ILOpCode.Ldelem_i2 -> failwith "todo"
|
| ILOpCode.Ldelem_i2 -> IlOp.Nullary NullaryIlOp.Ldelem_i2
|
||||||
| ILOpCode.Ldelem_u2 -> failwith "todo"
|
| ILOpCode.Ldelem_u2 -> IlOp.Nullary NullaryIlOp.Ldelem_u2
|
||||||
| ILOpCode.Ldelem_i4 -> failwith "todo"
|
| ILOpCode.Ldelem_i4 -> IlOp.Nullary NullaryIlOp.Ldelem_i4
|
||||||
| ILOpCode.Ldelem_u4 -> failwith "todo"
|
| ILOpCode.Ldelem_u4 -> IlOp.Nullary NullaryIlOp.Ldelem_u4
|
||||||
| ILOpCode.Ldelem_i8 -> failwith "todo"
|
| ILOpCode.Ldelem_i8 -> IlOp.Nullary NullaryIlOp.Ldelem_i8
|
||||||
| ILOpCode.Ldelem_i -> failwith "todo"
|
| ILOpCode.Ldelem_i -> IlOp.Nullary NullaryIlOp.Ldelem_i
|
||||||
| ILOpCode.Ldelem_r4 -> failwith "todo"
|
| ILOpCode.Ldelem_r4 -> IlOp.Nullary NullaryIlOp.Ldelem_r4
|
||||||
| ILOpCode.Ldelem_r8 -> failwith "todo"
|
| ILOpCode.Ldelem_r8 -> IlOp.Nullary NullaryIlOp.Ldelem_r8
|
||||||
| ILOpCode.Ldelem_ref -> failwith "todo"
|
| ILOpCode.Ldelem_ref -> IlOp.Nullary NullaryIlOp.Ldelem_ref
|
||||||
| ILOpCode.Stelem_i -> failwith "todo"
|
| ILOpCode.Stelem_i -> IlOp.Nullary NullaryIlOp.Stelem_i
|
||||||
| ILOpCode.Stelem_i1 -> failwith "todo"
|
| ILOpCode.Stelem_i1 -> IlOp.Nullary NullaryIlOp.Stelem_i1
|
||||||
| ILOpCode.Stelem_i2 -> failwith "todo"
|
| ILOpCode.Stelem_i2 -> IlOp.Nullary NullaryIlOp.Stelem_i2
|
||||||
| ILOpCode.Stelem_i4 -> failwith "todo"
|
| ILOpCode.Stelem_i4 -> IlOp.Nullary NullaryIlOp.Stelem_i4
|
||||||
| ILOpCode.Stelem_i8 -> failwith "todo"
|
| ILOpCode.Stelem_i8 -> IlOp.Nullary NullaryIlOp.Stelem_i8
|
||||||
| ILOpCode.Stelem_r4 -> failwith "todo"
|
| ILOpCode.Stelem_r4 -> IlOp.Nullary NullaryIlOp.Stelem_r4
|
||||||
| ILOpCode.Stelem_r8 -> failwith "todo"
|
| ILOpCode.Stelem_r8 -> IlOp.Nullary NullaryIlOp.Stelem_r8
|
||||||
| ILOpCode.Stelem_ref -> failwith "todo"
|
| ILOpCode.Stelem_ref -> IlOp.Nullary NullaryIlOp.Stelem_ref
|
||||||
| ILOpCode.Ldelem ->
|
| ILOpCode.Ldelem ->
|
||||||
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Ldelem, readMetadataToken &reader)
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Ldelem, readMetadataToken &reader)
|
||||||
| ILOpCode.Stelem ->
|
| ILOpCode.Stelem ->
|
||||||
@@ -356,30 +317,32 @@ module TypeInfo =
|
|||||||
| ILOpCode.Refanyval -> failwith "todo"
|
| ILOpCode.Refanyval -> failwith "todo"
|
||||||
| ILOpCode.Ckfinite -> failwith "todo"
|
| ILOpCode.Ckfinite -> failwith "todo"
|
||||||
| ILOpCode.Mkrefany -> failwith "todo"
|
| ILOpCode.Mkrefany -> failwith "todo"
|
||||||
| ILOpCode.Ldtoken -> failwith "todo"
|
| ILOpCode.Ldtoken ->
|
||||||
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Ldtoken, readMetadataToken &reader)
|
||||||
| ILOpCode.Conv_u2 -> IlOp.Nullary NullaryIlOp.Conv_U2
|
| ILOpCode.Conv_u2 -> IlOp.Nullary NullaryIlOp.Conv_U2
|
||||||
| ILOpCode.Conv_u1 -> IlOp.Nullary NullaryIlOp.Conv_U1
|
| ILOpCode.Conv_u1 -> IlOp.Nullary NullaryIlOp.Conv_U1
|
||||||
| ILOpCode.Conv_i -> IlOp.Nullary NullaryIlOp.Conv_I
|
| ILOpCode.Conv_i -> IlOp.Nullary NullaryIlOp.Conv_I
|
||||||
| ILOpCode.Conv_ovf_i -> failwith "todo"
|
| ILOpCode.Conv_ovf_i -> IlOp.Nullary NullaryIlOp.Conv_ovf_i
|
||||||
| ILOpCode.Conv_ovf_u -> failwith "todo"
|
| ILOpCode.Conv_ovf_u -> IlOp.Nullary NullaryIlOp.Conv_ovf_u
|
||||||
| ILOpCode.Add_ovf -> failwith "todo"
|
| ILOpCode.Add_ovf -> IlOp.Nullary NullaryIlOp.Add_ovf
|
||||||
| ILOpCode.Add_ovf_un -> failwith "todo"
|
| ILOpCode.Add_ovf_un -> IlOp.Nullary NullaryIlOp.Add_ovf_un
|
||||||
| ILOpCode.Mul_ovf -> failwith "todo"
|
| ILOpCode.Mul_ovf -> IlOp.Nullary NullaryIlOp.Mul_ovf
|
||||||
| ILOpCode.Mul_ovf_un -> failwith "todo"
|
| ILOpCode.Mul_ovf_un -> IlOp.Nullary NullaryIlOp.Mul_ovf_un
|
||||||
| ILOpCode.Sub_ovf -> failwith "todo"
|
| ILOpCode.Sub_ovf -> IlOp.Nullary NullaryIlOp.Sub_ovf
|
||||||
| ILOpCode.Sub_ovf_un -> failwith "todo"
|
| ILOpCode.Sub_ovf_un -> IlOp.Nullary NullaryIlOp.Sub_ovf_un
|
||||||
| ILOpCode.Endfinally -> IlOp.Nullary NullaryIlOp.Endfinally
|
| ILOpCode.Endfinally -> IlOp.Nullary NullaryIlOp.Endfinally
|
||||||
| ILOpCode.Leave -> IlOp.UnaryConst (UnaryConstIlOp.Leave (reader.ReadInt32 ()))
|
| ILOpCode.Leave -> IlOp.UnaryConst (UnaryConstIlOp.Leave (reader.ReadInt32 ()))
|
||||||
| ILOpCode.Leave_s -> IlOp.UnaryConst (UnaryConstIlOp.Leave_s (reader.ReadSByte ()))
|
| ILOpCode.Leave_s -> IlOp.UnaryConst (UnaryConstIlOp.Leave_s (reader.ReadSByte ()))
|
||||||
| ILOpCode.Stind_i -> failwith "todo"
|
| ILOpCode.Stind_i -> failwith "todo"
|
||||||
| ILOpCode.Conv_u -> failwith "todo"
|
| ILOpCode.Conv_u -> IlOp.Nullary NullaryIlOp.Conv_U
|
||||||
| ILOpCode.Arglist -> failwith "todo"
|
| ILOpCode.Arglist -> failwith "todo"
|
||||||
| ILOpCode.Ceq -> IlOp.Nullary NullaryIlOp.Ceq
|
| ILOpCode.Ceq -> IlOp.Nullary NullaryIlOp.Ceq
|
||||||
| ILOpCode.Cgt -> IlOp.Nullary NullaryIlOp.Cgt
|
| ILOpCode.Cgt -> IlOp.Nullary NullaryIlOp.Cgt
|
||||||
| ILOpCode.Cgt_un -> IlOp.Nullary NullaryIlOp.Cgt_un
|
| ILOpCode.Cgt_un -> IlOp.Nullary NullaryIlOp.Cgt_un
|
||||||
| ILOpCode.Clt -> IlOp.Nullary NullaryIlOp.Clt
|
| ILOpCode.Clt -> IlOp.Nullary NullaryIlOp.Clt
|
||||||
| ILOpCode.Clt_un -> IlOp.Nullary NullaryIlOp.Clt_un
|
| ILOpCode.Clt_un -> IlOp.Nullary NullaryIlOp.Clt_un
|
||||||
| ILOpCode.Ldftn -> failwith "todo"
|
| ILOpCode.Ldftn ->
|
||||||
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Ldftn, readMetadataToken &reader)
|
||||||
| ILOpCode.Ldvirtftn -> failwith "todo"
|
| ILOpCode.Ldvirtftn -> failwith "todo"
|
||||||
| ILOpCode.Ldarg -> failwith "todo"
|
| ILOpCode.Ldarg -> failwith "todo"
|
||||||
| ILOpCode.Ldarga -> failwith "todo"
|
| ILOpCode.Ldarga -> failwith "todo"
|
||||||
@@ -387,13 +350,15 @@ module TypeInfo =
|
|||||||
| ILOpCode.Ldloc -> failwith "todo"
|
| ILOpCode.Ldloc -> failwith "todo"
|
||||||
| ILOpCode.Ldloca -> failwith "todo"
|
| ILOpCode.Ldloca -> failwith "todo"
|
||||||
| ILOpCode.Stloc -> IlOp.UnaryConst (UnaryConstIlOp.Stloc (reader.ReadUInt16 ()))
|
| ILOpCode.Stloc -> IlOp.UnaryConst (UnaryConstIlOp.Stloc (reader.ReadUInt16 ()))
|
||||||
| ILOpCode.Localloc -> failwith "todo"
|
| ILOpCode.Localloc -> IlOp.Nullary NullaryIlOp.Localloc
|
||||||
| ILOpCode.Endfilter -> IlOp.Nullary NullaryIlOp.Endfilter
|
| ILOpCode.Endfilter -> IlOp.Nullary NullaryIlOp.Endfilter
|
||||||
| ILOpCode.Unaligned -> failwith "todo"
|
| ILOpCode.Unaligned -> failwith "todo"
|
||||||
| ILOpCode.Volatile -> failwith "todo"
|
| ILOpCode.Volatile -> IlOp.Nullary NullaryIlOp.Volatile
|
||||||
| ILOpCode.Tail -> failwith "todo"
|
| ILOpCode.Tail -> IlOp.Nullary NullaryIlOp.Tail
|
||||||
| ILOpCode.Initobj -> failwith "todo"
|
| ILOpCode.Initobj ->
|
||||||
| ILOpCode.Constrained -> failwith "todo"
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Initobj, readMetadataToken &reader)
|
||||||
|
| ILOpCode.Constrained ->
|
||||||
|
IlOp.UnaryMetadataToken (UnaryMetadataTokenIlOp.Constrained, readMetadataToken &reader)
|
||||||
| ILOpCode.Cpblk -> failwith "todo"
|
| ILOpCode.Cpblk -> failwith "todo"
|
||||||
| ILOpCode.Initblk -> failwith "todo"
|
| ILOpCode.Initblk -> failwith "todo"
|
||||||
| ILOpCode.Rethrow -> IlOp.Nullary NullaryIlOp.Rethrow
|
| ILOpCode.Rethrow -> IlOp.Nullary NullaryIlOp.Rethrow
|
||||||
@@ -404,7 +369,15 @@ module TypeInfo =
|
|||||||
|
|
||||||
readInstructions ((opCode, offset) :: acc)
|
readInstructions ((opCode, offset) :: acc)
|
||||||
|
|
||||||
readInstructions []
|
let instructions = readInstructions []
|
||||||
|
|
||||||
|
{
|
||||||
|
Instructions = instructions
|
||||||
|
LocalInit = methodBody.LocalVariablesInitialized
|
||||||
|
MaxStackSize = methodBody.MaxStack
|
||||||
|
ExceptionRegions = methodBody.ExceptionRegions
|
||||||
|
}
|
||||||
|
|> Some
|
||||||
|
|
||||||
let private readMethodParams
|
let private readMethodParams
|
||||||
(metadata : MetadataReader)
|
(metadata : MetadataReader)
|
||||||
@@ -439,65 +412,23 @@ module TypeInfo =
|
|||||||
)
|
)
|
||||||
|> ImmutableArray.CreateRange
|
|> ImmutableArray.CreateRange
|
||||||
|
|
||||||
let private typeProvider =
|
|
||||||
{ new ISignatureTypeProvider<TypeDefn, unit> with
|
|
||||||
member this.GetArrayType (elementType : TypeDefn, shape : ArrayShape) : TypeDefn = failwith "TODO"
|
|
||||||
member this.GetByReferenceType (elementType : TypeDefn) : TypeDefn = TypeDefn.Byref elementType
|
|
||||||
|
|
||||||
member this.GetSZArrayType (elementType : TypeDefn) : TypeDefn =
|
|
||||||
TypeDefn.OneDimensionalArrayLowerBoundZero elementType
|
|
||||||
|
|
||||||
member this.GetPrimitiveType (elementType : PrimitiveTypeCode) : TypeDefn =
|
|
||||||
PrimitiveType.OfEnum elementType |> TypeDefn.PrimitiveType
|
|
||||||
|
|
||||||
member this.GetGenericInstantiation
|
|
||||||
(generic : TypeDefn, typeArguments : ImmutableArray<TypeDefn>)
|
|
||||||
: TypeDefn
|
|
||||||
=
|
|
||||||
TypeDefn.GenericInstantiation (generic, typeArguments)
|
|
||||||
|
|
||||||
member this.GetTypeFromDefinition
|
|
||||||
(reader : MetadataReader, handle : TypeDefinitionHandle, rawTypeKind : byte)
|
|
||||||
: TypeDefn
|
|
||||||
=
|
|
||||||
let handle : EntityHandle = TypeDefinitionHandle.op_Implicit handle
|
|
||||||
let typeKind = reader.ResolveSignatureTypeKind (handle, rawTypeKind)
|
|
||||||
|
|
||||||
TypeDefn.FromDefinition typeKind
|
|
||||||
|
|
||||||
member this.GetTypeFromReference
|
|
||||||
(reader : MetadataReader, handle : TypeReferenceHandle, rawTypeKind : byte)
|
|
||||||
: TypeDefn
|
|
||||||
=
|
|
||||||
let handle : EntityHandle = TypeReferenceHandle.op_Implicit handle
|
|
||||||
let typeKind = reader.ResolveSignatureTypeKind (handle, rawTypeKind)
|
|
||||||
TypeDefn.FromReference typeKind
|
|
||||||
|
|
||||||
member this.GetPointerType (typeCode : TypeDefn) : TypeDefn = TypeDefn.Pointer typeCode
|
|
||||||
|
|
||||||
member this.GetFunctionPointerType (signature) =
|
|
||||||
TypeDefn.FunctionPointer (TypeMethodSignature.make signature)
|
|
||||||
|
|
||||||
member this.GetGenericMethodParameter (genericContext, index) = TypeDefn.GenericMethodParameter index
|
|
||||||
member this.GetGenericTypeParameter (genericContext, index) = TypeDefn.GenericTypeParameter index
|
|
||||||
|
|
||||||
member this.GetModifiedType (modifier, unmodifiedType, isRequired) =
|
|
||||||
TypeDefn.Modified (unmodifiedType, modifier, isRequired)
|
|
||||||
|
|
||||||
member this.GetPinnedType (elementType) = TypeDefn.Pinned elementType
|
|
||||||
member this.GetTypeFromSpecification (reader, genericContext, handle, rawTypeKind) = failwith "todo"
|
|
||||||
}
|
|
||||||
|
|
||||||
let private readMethod
|
let private readMethod
|
||||||
(peReader : PEReader)
|
(peReader : PEReader)
|
||||||
(metadataReader : MetadataReader)
|
(metadataReader : MetadataReader)
|
||||||
(methodHandle : MethodDefinitionHandle)
|
(methodHandle : MethodDefinitionHandle)
|
||||||
: MethodInfo
|
: MethodInfo option
|
||||||
=
|
=
|
||||||
let methodDef = metadataReader.GetMethodDefinition methodHandle
|
let methodDef = metadataReader.GetMethodDefinition methodHandle
|
||||||
let methodName = metadataReader.GetString methodDef.Name
|
let methodName = metadataReader.GetString methodDef.Name
|
||||||
let methodSig = methodDef.DecodeSignature (typeProvider, ())
|
let methodSig = methodDef.DecodeSignature (TypeDefn.typeProvider, ())
|
||||||
let methodBody = readMethodBody peReader methodDef
|
let methodBody = readMethodBody peReader methodDef
|
||||||
|
|
||||||
|
match methodBody with
|
||||||
|
| None ->
|
||||||
|
Console.Error.WriteLine $"[INF] No method body for {metadataReader.GetString methodDef.Name}"
|
||||||
|
None
|
||||||
|
| Some methodBody ->
|
||||||
|
|
||||||
let methodParams = readMethodParams metadataReader (methodDef.GetParameters ())
|
let methodParams = readMethodParams metadataReader (methodDef.GetParameters ())
|
||||||
|
|
||||||
let methodGenericParams =
|
let methodGenericParams =
|
||||||
@@ -506,12 +437,15 @@ module TypeInfo =
|
|||||||
{
|
{
|
||||||
Handle = methodHandle
|
Handle = methodHandle
|
||||||
Name = methodName
|
Name = methodName
|
||||||
Instructions = methodBody
|
Instructions = methodBody.Instructions
|
||||||
Locations = methodBody |> List.map (fun (a, b) -> b, a) |> Map.ofList
|
Locations = methodBody.Instructions |> List.map (fun (a, b) -> b, a) |> Map.ofList
|
||||||
Parameters = methodParams
|
Parameters = methodParams
|
||||||
Generics = methodGenericParams
|
Generics = methodGenericParams
|
||||||
Signature = TypeMethodSignature.make methodSig
|
Signature = TypeMethodSignature.make methodSig
|
||||||
|
IsPinvokeImpl = methodDef.Attributes.HasFlag MethodAttributes.PinvokeImpl
|
||||||
|
LocalsInit = methodBody.LocalInit
|
||||||
}
|
}
|
||||||
|
|> Some
|
||||||
|
|
||||||
let internal read
|
let internal read
|
||||||
(peReader : PEReader)
|
(peReader : PEReader)
|
||||||
@@ -522,8 +456,30 @@ module TypeInfo =
|
|||||||
let typeDef = metadataReader.GetTypeDefinition (typeHandle)
|
let typeDef = metadataReader.GetTypeDefinition (typeHandle)
|
||||||
let methods = typeDef.GetMethods ()
|
let methods = typeDef.GetMethods ()
|
||||||
|
|
||||||
|
let methodImpls =
|
||||||
|
typeDef.GetMethodImplementations ()
|
||||||
|
|> Seq.map (fun handle ->
|
||||||
|
let m = metadataReader.GetMethodImplementation handle
|
||||||
|
|
||||||
|
if not (m.MethodBody.Kind.HasFlag HandleKind.MethodImplementation) then
|
||||||
|
failwith "unexpected kind"
|
||||||
|
|
||||||
|
KeyValuePair (handle, m.MethodBody)
|
||||||
|
)
|
||||||
|
|> ImmutableDictionary.CreateRange
|
||||||
|
|
||||||
{
|
{
|
||||||
Namespace = metadataReader.GetString (typeDef.Namespace)
|
Namespace = metadataReader.GetString (typeDef.Namespace)
|
||||||
Name = metadataReader.GetString (typeDef.Name)
|
Name = metadataReader.GetString (typeDef.Name)
|
||||||
Methods = methods |> Seq.map (readMethod peReader metadataReader) |> Seq.toList
|
Methods =
|
||||||
|
methods
|
||||||
|
|> Seq.choose (fun m ->
|
||||||
|
let result = readMethod peReader metadataReader m
|
||||||
|
|
||||||
|
match result with
|
||||||
|
| None -> None
|
||||||
|
| Some x -> Some x
|
||||||
|
)
|
||||||
|
|> Seq.toList
|
||||||
|
MethodImpls = methodImpls
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BitTwiddling.fs" />
|
<Compile Include="BitTwiddling.fs" />
|
||||||
<None Include="Executable.fs" />
|
<None Include="Executable.fs" />
|
||||||
|
<Compile Include="TypeDefn.fs" />
|
||||||
<Compile Include="IlOp.fs" />
|
<Compile Include="IlOp.fs" />
|
||||||
<Compile Include="TypeInfo.fs" />
|
<Compile Include="TypeInfo.fs" />
|
||||||
<Compile Include="Assembly.fs" />
|
<Compile Include="Assembly.fs" />
|
||||||
|
Reference in New Issue
Block a user