Track addresses of arguments (#53)

This commit is contained in:
Patrick Stevens
2025-06-15 21:34:30 +01:00
committed by GitHub
parent 3b1f916743
commit 2c249edfc7
7 changed files with 71 additions and 7 deletions

View File

@@ -72,7 +72,9 @@ type CliValueType =
| Float64 of float
[<RequireQualifiedAccess>]
type CliRuntimePointerSource = | LocalVariable of sourceThread : ThreadId * methodFrame : int * whichVar : uint16
type CliRuntimePointerSource =
| LocalVariable of sourceThread : ThreadId * methodFrame : int * whichVar : uint16
| Argument of sourceThread : ThreadId * methodFrame : int * whichVar : uint16
type CliRuntimePointer =
| Unmanaged of unit

View File

@@ -4,6 +4,7 @@ open Microsoft.FSharp.Core
type ManagedPointerSource =
| LocalVariable of sourceThread : ThreadId * methodFrame : int * whichVar : uint16
| Argument of sourceThread : ThreadId * methodFrame : int * whichVar : uint16
| Heap of ManagedHeapAddress
| Null
@@ -11,7 +12,10 @@ type ManagedPointerSource =
match this with
| ManagedPointerSource.Null -> "<null pointer>"
| ManagedPointerSource.Heap addr -> $"%O{addr}"
| LocalVariable (source, method, var) -> $"<variable %i{var} in method frame %i{method} of thread %O{source}>"
| ManagedPointerSource.LocalVariable (source, method, var) ->
$"<variable %i{var} in method frame %i{method} of thread %O{source}>"
| ManagedPointerSource.Argument (source, method, var) ->
$"<argument %i{var} in method frame %i{method} of thread %O{source}>"
[<RequireQualifiedAccess>]
type NativeIntSource =
@@ -65,7 +69,9 @@ type EvalStackValue =
| EvalStackValue.Float f -> $"Float(%f{f})"
| EvalStackValue.ManagedPointer managedPointerSource -> $"Pointer(%O{managedPointerSource})"
| EvalStackValue.ObjectRef managedHeapAddress -> $"ObjectRef(%O{managedHeapAddress})"
| EvalStackValue.UserDefinedValueType evalStackValues -> failwith "todo"
| EvalStackValue.UserDefinedValueType evalStackValues ->
let desc = evalStackValues |> List.map string<EvalStackValue> |> String.concat " | "
$"Struct(%s{desc})"
[<RequireQualifiedAccess>]
module EvalStackValue =
@@ -168,6 +174,10 @@ module EvalStackValue =
CliRuntimePointerSource.LocalVariable (sourceThread, methodFrame, whichVar)
|> CliRuntimePointer.Managed
|> CliType.RuntimePointer
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) ->
CliRuntimePointerSource.Argument (sourceThread, methodFrame, whichVar)
|> CliRuntimePointer.Managed
|> CliType.RuntimePointer
| ManagedPointerSource.Heap managedHeapAddress -> CliType.ObjectRef (Some managedHeapAddress)
| ManagedPointerSource.Null -> CliType.ObjectRef None
| EvalStackValue.NativeInt nativeIntSource ->
@@ -175,7 +185,11 @@ module EvalStackValue =
| NativeIntSource.Verbatim 0L -> CliType.ObjectRef None
| NativeIntSource.Verbatim i -> failwith $"refusing to interpret verbatim native int {i} as a pointer"
| NativeIntSource.FunctionPointer _ -> failwith "TODO"
| i -> failwith $"TODO: %O{i}"
| EvalStackValue.UserDefinedValueType fields ->
match fields with
| [ esv ] -> toCliTypeCoerced target esv
| fields -> failwith $"TODO: don't know how to coerce struct of {fields} to a pointer"
| _ -> failwith $"TODO: {popped}"
| CliType.Bool _ ->
match popped with
| EvalStackValue.Int32 i ->
@@ -194,6 +208,10 @@ module EvalStackValue =
CliRuntimePointerSource.LocalVariable (sourceThread, methodFrame, var)
|> CliRuntimePointer.Managed
|> CliType.RuntimePointer
| ManagedPointerSource.Argument (sourceThread, methodFrame, var) ->
CliRuntimePointerSource.Argument (sourceThread, methodFrame, var)
|> CliRuntimePointer.Managed
|> CliType.RuntimePointer
| _ -> failwith $"TODO: %O{popped}"
| CliType.Char _ ->
match popped with
@@ -241,6 +259,9 @@ module EvalStackValue =
| CliRuntimePointerSource.LocalVariable (sourceThread, methodFrame, var) ->
ManagedPointerSource.LocalVariable (sourceThread, methodFrame, var)
|> EvalStackValue.ManagedPointer
| CliRuntimePointerSource.Argument (sourceThread, methodFrame, var) ->
ManagedPointerSource.Argument (sourceThread, methodFrame, var)
|> EvalStackValue.ManagedPointer
| CliType.ValueType fields -> fields |> List.map ofCliType |> EvalStackValue.UserDefinedValueType
type EvalStack =

View File

@@ -83,6 +83,8 @@ module System_Threading_Monitor =
| ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar) ->
state
|> IlMachineState.setLocalVariable sourceThread methodFrame whichVar (CliType.OfBool true)
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) ->
failwith "not really expecting to *edit* an argument..."
| ManagedPointerSource.Heap addr -> failwith "todo: managed heap"
(state, WhatWeDid.Executed) |> ExecutionResult.Stepped

View File

@@ -80,6 +80,8 @@ module NullaryIlOp =
| EvalStackValue.ManagedPointer src ->
match src with
| ManagedPointerSource.Null -> failwith "TODO: throw NullReferenceException"
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) ->
failwith "unexpected - can we really write to an argument?"
| ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar) ->
{ state with
ThreadState =
@@ -668,6 +670,17 @@ module NullaryIlOp =
| EvalStackValue.ManagedPointer src ->
match src with
| ManagedPointerSource.Null -> failwith "unexpected null pointer in Ldind_u1"
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) ->
let methodState =
state.ThreadState.[sourceThread].MethodStates.[methodFrame].Arguments.[int<uint16> whichVar]
match methodState with
| CliType.Bool b -> b
| CliType.Numeric numeric -> failwith $"tried to load a Numeric as a u8: {numeric}"
| CliType.Char _ -> failwith "tried to load a Char as a u8"
| CliType.ObjectRef _ -> failwith "tried to load an ObjectRef as a u8"
| CliType.RuntimePointer _ -> failwith "tried to load a RuntimePointer as a u8"
| CliType.ValueType cliTypes -> failwith "todo"
| ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar) ->
let methodState =
state.ThreadState.[sourceThread].MethodStates.[methodFrame].LocalVariables

View File

@@ -409,9 +409,27 @@ module internal UnaryConstIlOp =
|> IlMachineState.advanceProgramCounter currentThread
state, WhatWeDid.Executed
| Ldarga s -> failwith "TODO: Ldarga unimplemented"
| Ldarga s ->
let executingMethod = state.ThreadState.[currentThread]
let ptr =
ManagedPointerSource.Argument (currentThread, executingMethod.ActiveMethodState, s)
state
|> IlMachineState.pushToEvalStack' (EvalStackValue.ManagedPointer ptr) currentThread
|> IlMachineState.advanceProgramCounter currentThread
|> Tuple.withRight WhatWeDid.Executed
| Ldarga_s b ->
let executingMethod = state.ThreadState.[currentThread]
let ptr =
ManagedPointerSource.Argument (currentThread, executingMethod.ActiveMethodState, uint16<byte> b)
state
|> IlMachineState.pushToEvalStack' (EvalStackValue.ManagedPointer ptr) currentThread
|> IlMachineState.advanceProgramCounter currentThread
|> Tuple.withRight WhatWeDid.Executed
| Ldarg_s b -> failwith "TODO: Ldarg_s unimplemented"
| Ldarga_s b -> failwith "TODO: Ldarga_s unimplemented"
| Leave i -> leave currentThread i state
| Leave_s b -> leave currentThread (int<int8> b) state
| Starg_s b -> failwith "TODO: Starg_s unimplemented"

View File

@@ -408,6 +408,7 @@ module internal UnaryMetadataIlOp =
match source with
| ManagedPointerSource.Null -> failwith "TODO: raise NullReferenceException"
| ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar) -> failwith "todo"
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) -> failwith "todo"
| ManagedPointerSource.Heap addr ->
match state.ManagedHeap.NonArrayObjects.TryGetValue addr with
| false, _ -> failwith $"todo: array {addr}"
@@ -575,7 +576,12 @@ module internal UnaryMetadataIlOp =
state.ThreadState.[sourceThread].MethodStates.[methodFrame].LocalVariables
.[int<uint16> whichVar]
failwith $"todo: local variable {currentValue} {field}"
IlMachineState.pushToEvalStack currentValue thread state
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) ->
let currentValue =
state.ThreadState.[sourceThread].MethodStates.[methodFrame].Arguments.[int<uint16> whichVar]
IlMachineState.pushToEvalStack currentValue thread state
| ManagedPointerSource.Heap managedHeapAddress ->
match state.ManagedHeap.NonArrayObjects.TryGetValue managedHeapAddress with
| false, _ -> failwith $"todo: array {managedHeapAddress}"