diff --git a/src/Core/Echo/Memory/BasicMemorySpace.cs b/src/Core/Echo/Memory/BasicMemorySpace.cs index a0713e0e..ca49413a 100644 --- a/src/Core/Echo/Memory/BasicMemorySpace.cs +++ b/src/Core/Echo/Memory/BasicMemorySpace.cs @@ -8,8 +8,8 @@ namespace Echo.Memory /// public class BasicMemorySpace : IMemorySpace { - private long _baseAddress; - + private AddressRange _addressRange; + /// /// Creates a new memory space. /// @@ -19,7 +19,7 @@ public BasicMemorySpace(int size, bool initialize) : this(new BitVector(size * 8, initialize)) { } - + /// /// Wraps a byte array into a memory space. /// @@ -27,8 +27,9 @@ public BasicMemorySpace(int size, bool initialize) public BasicMemorySpace(byte[] backBuffer) { BackBuffer = new BitVector(backBuffer); + _addressRange = new AddressRange(0, BackBuffer.Count / 8); } - + /// /// Wraps a bit vector into a memory space. /// @@ -36,6 +37,7 @@ public BasicMemorySpace(byte[] backBuffer) public BasicMemorySpace(BitVector backBuffer) { BackBuffer = backBuffer; + _addressRange = new AddressRange(0, BackBuffer.Count / 8); } /// @@ -47,30 +49,33 @@ public BitVector BackBuffer } /// - public AddressRange AddressRange => new(_baseAddress, _baseAddress + BackBuffer.Count / 8); + public AddressRange AddressRange => _addressRange; /// - public bool IsValidAddress(long address) => AddressRange.Contains(address); + public bool IsValidAddress(long address) => _addressRange.Contains(address); /// - public void Rebase(long baseAddress) => _baseAddress = baseAddress; + public void Rebase(long baseAddress) + { + _addressRange = new AddressRange(baseAddress, baseAddress + BackBuffer.Count / 8); + } /// public void Read(long address, BitVectorSpan buffer) { - BackBuffer.AsSpan((int) (address - _baseAddress) * 8, buffer.Count).CopyTo(buffer); + BackBuffer.AsSpan((int) (address - _addressRange.Start) * 8, buffer.Count).CopyTo(buffer); } /// public void Write(long address, BitVectorSpan buffer) { - buffer.CopyTo(BackBuffer.AsSpan((int) (address - _baseAddress) * 8, buffer.Count)); + buffer.CopyTo(BackBuffer.AsSpan((int) (address - _addressRange.Start) * 8, buffer.Count)); } /// public void Write(long address, ReadOnlySpan buffer) { - BackBuffer.AsSpan((int) ((address - _baseAddress) * 8)).Write(buffer); + BackBuffer.AsSpan((int) ((address - _addressRange.Start) * 8)).Write(buffer); } } } \ No newline at end of file diff --git a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Heap/HostObject.cs b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Heap/HostObject.cs index 91fb4962..b3e581d4 100644 --- a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Heap/HostObject.cs +++ b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Heap/HostObject.cs @@ -17,7 +17,7 @@ public class HostObject : IMemorySpace private readonly Dictionary _fields = new(); private readonly CilVirtualMachine _machine; private readonly TypeMemoryLayout _virtualLayout; - private long _baseAddress; + private AddressRange _addressRange; /// /// Creates a new managed object embedding. @@ -29,6 +29,7 @@ public HostObject(object o, CilVirtualMachine machine) Object = o ?? throw new ArgumentNullException(nameof(o)); _virtualLayout = GetLayout(machine.ValueFactory, o); _machine = machine; + _addressRange = new AddressRange(0, machine.ValueFactory.ObjectHeaderSize + _virtualLayout.Size); } /// @@ -44,13 +45,16 @@ public object Object /// /// - public AddressRange AddressRange => new(_baseAddress, _baseAddress + _machine.ValueFactory.ObjectHeaderSize + _virtualLayout.Size); + public AddressRange AddressRange => _addressRange; /// - public bool IsValidAddress(long address) => AddressRange.Contains(address); + public bool IsValidAddress(long address) => _addressRange.Contains(address); /// - public void Rebase(long baseAddress) => _baseAddress = baseAddress; + public void Rebase(long baseAddress) + { + _addressRange = new AddressRange(baseAddress, baseAddress + _machine.ValueFactory.ObjectHeaderSize + _virtualLayout.Size); + } /// public void Read(long address, BitVectorSpan buffer) @@ -58,7 +62,7 @@ public void Read(long address, BitVectorSpan buffer) buffer.MarkFullyUnknown(); // First field in an object is always its method table (i.e., pointer to its type). - uint offset = (uint) (address - _baseAddress); + uint offset = (uint) (address - _addressRange.Start); if (offset == 0) { long methodTable = _machine.ValueFactory.ClrMockMemory.MethodTables.GetAddress(_virtualLayout.Type); @@ -108,7 +112,7 @@ private void ReadFromObject(uint offset, BitVectorSpan buffer) /// public void Write(long address, BitVectorSpan buffer) { - uint offset = (uint) (address - _baseAddress); + uint offset = (uint) (address - _addressRange.Start); if (Object.GetType().IsArray) WriteToArray(offset, buffer); diff --git a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Stack/CallFrame.cs b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Stack/CallFrame.cs index d51642cb..95d69c7e 100644 --- a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Stack/CallFrame.cs +++ b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Stack/CallFrame.cs @@ -30,7 +30,7 @@ public partial class CallFrame : IMemorySpace private readonly List _offsets = new(); private readonly List _exceptionHandlers = new(); private BitVector _localStorage; - private long _baseAddress; + private AddressRange _addressRange; /// /// Constructs a new call stack frame. @@ -89,7 +89,8 @@ internal CallFrame(IMethodDescriptor method, ValueFactory factory, bool isRoot) // Actually reserve space for the entire frame. _localStorage = new BitVector((int) (currentOffset * 8), false); - + _addressRange = new AddressRange(0, _localStorage.ByteCount); + // Initialize locals to zero when method body says we should. if (_initializeLocals) { @@ -172,10 +173,10 @@ void AllocateFrameField(TypeSignature type) public ITypeDescriptor? ConstrainedType { get; set; } /// - public AddressRange AddressRange => new(_baseAddress, _baseAddress + _localStorage.ByteCount); + public AddressRange AddressRange => _addressRange; /// - public bool IsValidAddress(long address) => AddressRange.Contains(address); + public bool IsValidAddress(long address) => _addressRange.Contains(address); /// /// Allocates local stack memory in the stack frame. @@ -189,17 +190,21 @@ public long Allocate(int size) if (size < 0) throw new ArgumentOutOfRangeException(nameof(size)); - long address = AddressRange.End; + long address = _addressRange.End; int originalSize = _localStorage.Count; _localStorage = _localStorage.Resize(originalSize + size * 8, false); if (!_initializeLocals) _localStorage.AsSpan(originalSize, _localStorage.Count - originalSize).MarkFullyUnknown(); - + + _addressRange = new AddressRange(_addressRange.Start, _addressRange.Start + _localStorage.ByteCount); return address; } /// - public void Rebase(long baseAddress) => _baseAddress = baseAddress; + public void Rebase(long baseAddress) + { + _addressRange = new AddressRange(baseAddress, baseAddress + _localStorage.ByteCount); + } /// /// Gets the address (relative to the start of the frame) to a local variable in the frame. @@ -208,7 +213,7 @@ public long Allocate(int size) /// The address /// Occurs when the local index is invalid. public long GetLocalAddress(int index) => index < LocalsCount - ? _baseAddress + _offsets[index] + ? _addressRange.Start + _offsets[index] : throw new ArgumentOutOfRangeException(nameof(index)); /// @@ -251,7 +256,7 @@ public BitVector ReadLocal(int index) /// The address /// Occurs when the argument index is invalid. public long GetArgumentAddress(int index) => index < Method.Signature!.GetTotalParameterCount() - ? _baseAddress + _offsets[LocalsCount + 1 + index] + ? _addressRange.Start + _offsets[LocalsCount + 1 + index] : throw new ArgumentOutOfRangeException(nameof(index)); /// @@ -290,19 +295,19 @@ public BitVector ReadArgument(int index) /// public void Read(long address, BitVectorSpan buffer) { - _localStorage.AsSpan((int) (address - _baseAddress) * 8, buffer.Count).CopyTo(buffer); + _localStorage.AsSpan((int) (address - _addressRange.Start) * 8, buffer.Count).CopyTo(buffer); } /// public void Write(long address, BitVectorSpan buffer) { - buffer.CopyTo(_localStorage.AsSpan((int) (address - _baseAddress) * 8, buffer.Count)); + buffer.CopyTo(_localStorage.AsSpan((int) (address - _addressRange.Start) * 8, buffer.Count)); } /// public void Write(long address, ReadOnlySpan buffer) { - _localStorage.AsSpan((int) (address - _baseAddress) * 8, buffer.Length).Write(buffer); + _localStorage.AsSpan((int) (address - _addressRange.Start) * 8, buffer.Length).Write(buffer); } private void InitializeExceptionHandlerFrames()