Sharing memory.
This commit is contained in:
parent
576d6492dc
commit
da655d15b3
|
@ -12,7 +12,6 @@ using xe.debug.proto;
|
||||||
using Xenia.Debug.Utilities;
|
using Xenia.Debug.Utilities;
|
||||||
|
|
||||||
namespace Xenia.Debug {
|
namespace Xenia.Debug {
|
||||||
|
|
||||||
public class Debugger {
|
public class Debugger {
|
||||||
private readonly static string kServerHostname = "";
|
private readonly static string kServerHostname = "";
|
||||||
private readonly static int kServerPort = 19000;
|
private readonly static int kServerPort = 19000;
|
||||||
|
@ -35,6 +34,19 @@ namespace Xenia.Debug {
|
||||||
pendingRequests = new ConcurrentDictionary<uint, PendingRequest>();
|
pendingRequests = new ConcurrentDictionary<uint, PendingRequest>();
|
||||||
private uint nextRequestId = 1;
|
private uint nextRequestId = 1;
|
||||||
|
|
||||||
|
private FileMappingHandle memoryHandle;
|
||||||
|
public IntPtr Membase {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe byte* TranslateVirtual(uint address) {
|
||||||
|
return (byte*)Membase.ToPointer() + address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe byte* TranslatePhysical(uint address) {
|
||||||
|
return (byte*)Membase.ToPointer() + 0xFFFFFFFF + address;
|
||||||
|
}
|
||||||
|
|
||||||
public event EventHandler<State> StateChanged;
|
public event EventHandler<State> StateChanged;
|
||||||
|
|
||||||
public State CurrentState {
|
public State CurrentState {
|
||||||
|
@ -126,6 +138,27 @@ namespace Xenia.Debug {
|
||||||
int requestDataOffset = AttachRequest.EndAttachRequest(fbb);
|
int requestDataOffset = AttachRequest.EndAttachRequest(fbb);
|
||||||
var response = await CommitRequest(fbb, RequestData.AttachRequest, requestDataOffset);
|
var response = await CommitRequest(fbb, RequestData.AttachRequest, requestDataOffset);
|
||||||
|
|
||||||
|
System.Diagnostics.Debug.Assert(response.ResponseDataType ==
|
||||||
|
ResponseData.AttachResponse);
|
||||||
|
var attachResponse = new AttachResponse();
|
||||||
|
response.GetResponseData(attachResponse);
|
||||||
|
|
||||||
|
// Open mmap to share memroy.
|
||||||
|
memoryHandle = FileMapping.OpenFileMapping(
|
||||||
|
FileMapAccess.FILE_MAP_ALL_ACCESS, false, attachResponse.MemoryFile);
|
||||||
|
if (memoryHandle.IsInvalid) {
|
||||||
|
System.Diagnostics.Debug.Fail("Unable to open target memory");
|
||||||
|
Detach();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the memory system. This maps the emulator memory into our address
|
||||||
|
// space.
|
||||||
|
if (!Memory.InitializeMapping(memoryHandle)) {
|
||||||
|
Detach();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OnStateChanged(State.Attached);
|
OnStateChanged(State.Attached);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,8 +167,17 @@ namespace Xenia.Debug {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Memory.UninitializeMapping();
|
||||||
|
|
||||||
|
if (memoryHandle != null) {
|
||||||
|
memoryHandle.Close();
|
||||||
|
memoryHandle = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket != null) {
|
||||||
socket.Close();
|
socket.Close();
|
||||||
socket = null;
|
socket = null;
|
||||||
|
}
|
||||||
|
|
||||||
OnStateChanged(State.Detached);
|
OnStateChanged(State.Detached);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,100 @@ using System.Threading.Tasks;
|
||||||
using Xenia.Debug.Utilities;
|
using Xenia.Debug.Utilities;
|
||||||
|
|
||||||
namespace Xenia.Debug {
|
namespace Xenia.Debug {
|
||||||
public class Memory : Changeable {
|
public class Memory : Changeable, IDisposable {
|
||||||
private readonly Debugger debugger;
|
private readonly Debugger debugger;
|
||||||
|
|
||||||
|
private class MapInfo {
|
||||||
|
public ulong virtualAddressStart;
|
||||||
|
public ulong virtualAddressEnd;
|
||||||
|
public ulong targetAddress;
|
||||||
|
public IntPtr ptr;
|
||||||
|
}
|
||||||
|
private MapInfo[] mapInfos = new MapInfo[]{
|
||||||
|
// From memory.cc:
|
||||||
|
new MapInfo(){virtualAddressStart = 0x00000000, virtualAddressEnd = 0x3FFFFFFF,
|
||||||
|
targetAddress = 0x0000000000000000},
|
||||||
|
new MapInfo(){virtualAddressStart = 0x40000000, virtualAddressEnd = 0x7EFFFFFF,
|
||||||
|
targetAddress = 0x0000000040000000},
|
||||||
|
new MapInfo(){virtualAddressStart = 0x7F000000, virtualAddressEnd = 0x7FFFFFFF,
|
||||||
|
targetAddress = 0x0000000100000000},
|
||||||
|
new MapInfo(){virtualAddressStart = 0x80000000, virtualAddressEnd = 0x8FFFFFFF,
|
||||||
|
targetAddress = 0x0000000080000000},
|
||||||
|
new MapInfo(){virtualAddressStart = 0x90000000, virtualAddressEnd = 0x9FFFFFFF,
|
||||||
|
targetAddress = 0x0000000080000000},
|
||||||
|
new MapInfo(){virtualAddressStart = 0xA0000000, virtualAddressEnd = 0xBFFFFFFF,
|
||||||
|
targetAddress = 0x0000000100000000},
|
||||||
|
new MapInfo(){virtualAddressStart = 0xC0000000, virtualAddressEnd = 0xDFFFFFFF,
|
||||||
|
targetAddress = 0x0000000100000000},
|
||||||
|
new MapInfo(){virtualAddressStart = 0xE0000000, virtualAddressEnd = 0xFFFFFFFF,
|
||||||
|
targetAddress = 0x0000000100000000},
|
||||||
|
new MapInfo(){virtualAddressStart = 0x100000000, virtualAddressEnd = 0x11FFFFFFF,
|
||||||
|
targetAddress = 0x0000000100000000},
|
||||||
|
};
|
||||||
|
|
||||||
|
public UIntPtr VirtualMembase;
|
||||||
|
public UIntPtr PhysicalMembase;
|
||||||
|
|
||||||
public Memory(Debugger debugger) {
|
public Memory(Debugger debugger) {
|
||||||
this.debugger = debugger;
|
this.debugger = debugger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool InitializeMapping(FileMappingHandle mappingHandle) {
|
||||||
|
ulong mappingBase = 0x100000000;
|
||||||
|
foreach (MapInfo mapInfo in mapInfos) {
|
||||||
|
uint targetAddressLow = (uint)mapInfo.targetAddress;
|
||||||
|
uint targetAddressHigh = (uint)(mapInfo.targetAddress >> 32);
|
||||||
|
mapInfo.ptr = FileMapping.MapViewOfFileEx(
|
||||||
|
mappingHandle, FileMapAccess.FILE_MAP_ALL_ACCESS,
|
||||||
|
targetAddressHigh, targetAddressLow,
|
||||||
|
mapInfo.virtualAddressEnd - mapInfo.virtualAddressStart + 1,
|
||||||
|
mappingBase + mapInfo.virtualAddressStart);
|
||||||
|
if (mapInfo.ptr == IntPtr.Zero) {
|
||||||
|
System.Diagnostics.Debug.Fail("Unable to place memory at target address");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VirtualMembase = new UIntPtr(mappingBase);
|
||||||
|
PhysicalMembase = new UIntPtr(mappingBase + 0x100000000);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UninitializeMapping() {
|
||||||
|
foreach (MapInfo mapInfo in mapInfos) {
|
||||||
|
FileMapping.UnmapViewOfFile(mapInfo.ptr);
|
||||||
|
mapInfo.ptr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDispose() {
|
||||||
|
UninitializeMapping();
|
||||||
|
}
|
||||||
|
|
||||||
public MemoryView CreateView() {
|
public MemoryView CreateView() {
|
||||||
return new MemoryView(this);
|
return new MemoryView(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Dispose
|
||||||
|
private bool disposed = false;
|
||||||
|
|
||||||
|
~Memory() {
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing) {
|
||||||
|
if (!disposed) {
|
||||||
|
if (disposing) {
|
||||||
|
// TODO: dispose managed state (managed objects).
|
||||||
|
}
|
||||||
|
OnDispose();
|
||||||
|
disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,25 @@ public sealed class AttachResponse : Table {
|
||||||
public static AttachResponse GetRootAsAttachResponse(ByteBuffer _bb, AttachResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
|
public static AttachResponse GetRootAsAttachResponse(ByteBuffer _bb, AttachResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
|
||||||
public AttachResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
|
public AttachResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
|
||||||
|
|
||||||
|
public string MemoryFile { get { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } }
|
||||||
|
public string FunctionsFile { get { int o = __offset(6); return o != 0 ? __string(o + bb_pos) : null; } }
|
||||||
|
public string FunctionsTraceFile { get { int o = __offset(8); return o != 0 ? __string(o + bb_pos) : null; } }
|
||||||
|
|
||||||
public static void StartAttachResponse(FlatBufferBuilder builder) { builder.StartObject(0); }
|
public static int CreateAttachResponse(FlatBufferBuilder builder,
|
||||||
|
int memory_file = 0,
|
||||||
|
int functions_file = 0,
|
||||||
|
int functions_trace_file = 0) {
|
||||||
|
builder.StartObject(3);
|
||||||
|
AttachResponse.AddFunctionsTraceFile(builder, functions_trace_file);
|
||||||
|
AttachResponse.AddFunctionsFile(builder, functions_file);
|
||||||
|
AttachResponse.AddMemoryFile(builder, memory_file);
|
||||||
|
return AttachResponse.EndAttachResponse(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void StartAttachResponse(FlatBufferBuilder builder) { builder.StartObject(3); }
|
||||||
|
public static void AddMemoryFile(FlatBufferBuilder builder, int memoryFileOffset) { builder.AddOffset(0, memoryFileOffset, 0); }
|
||||||
|
public static void AddFunctionsFile(FlatBufferBuilder builder, int functionsFileOffset) { builder.AddOffset(1, functionsFileOffset, 0); }
|
||||||
|
public static void AddFunctionsTraceFile(FlatBufferBuilder builder, int functionsTraceFileOffset) { builder.AddOffset(2, functionsTraceFileOffset, 0); }
|
||||||
public static int EndAttachResponse(FlatBufferBuilder builder) {
|
public static int EndAttachResponse(FlatBufferBuilder builder) {
|
||||||
int o = builder.EndObject();
|
int o = builder.EndObject();
|
||||||
return o;
|
return o;
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Xenia.Debug.Utilities {
|
||||||
|
public class Disposable : IDisposable {
|
||||||
|
private bool disposed = false;
|
||||||
|
|
||||||
|
protected virtual void OnDispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing) {
|
||||||
|
if (!disposed) {
|
||||||
|
if (disposing) {
|
||||||
|
// TODO: dispose managed state (managed objects).
|
||||||
|
}
|
||||||
|
OnDispose();
|
||||||
|
disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Disposable() {
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
using Microsoft.Win32.SafeHandles;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.ConstrainedExecution;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security;
|
||||||
|
using System.Security.Permissions;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Xenia.Debug.Utilities {
|
||||||
|
// From: http://1code.codeplex.com/SourceControl/latest#Visual Studio 2008/CSFileMappingClient/Program.cs
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Access rights for file mapping objects
|
||||||
|
/// http://msdn.microsoft.com/en-us/library/aa366559.aspx
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum FileMapAccess {
|
||||||
|
FILE_MAP_COPY = 0x0001,
|
||||||
|
FILE_MAP_WRITE = 0x0002,
|
||||||
|
FILE_MAP_READ = 0x0004,
|
||||||
|
FILE_MAP_ALL_ACCESS = 0x000F001F
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a wrapper class for a file mapping handle.
|
||||||
|
/// </summary>
|
||||||
|
[SuppressUnmanagedCodeSecurity,
|
||||||
|
HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort = true)]
|
||||||
|
public sealed class FileMappingHandle : SafeHandleZeroOrMinusOneIsInvalid {
|
||||||
|
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
|
||||||
|
private FileMappingHandle()
|
||||||
|
: base(true) {
|
||||||
|
}
|
||||||
|
|
||||||
|
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
|
||||||
|
public FileMappingHandle(IntPtr handle, bool ownsHandle)
|
||||||
|
: base(ownsHandle) {
|
||||||
|
base.SetHandle(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success),
|
||||||
|
DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
private static extern bool CloseHandle(IntPtr handle);
|
||||||
|
|
||||||
|
protected override bool ReleaseHandle() {
|
||||||
|
return CloseHandle(base.handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The class exposes Windows APIs used in this code sample.
|
||||||
|
/// </summary>
|
||||||
|
[SuppressUnmanagedCodeSecurity]
|
||||||
|
public class FileMapping {
|
||||||
|
/// <summary>
|
||||||
|
/// Opens a named file mapping object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dwDesiredAccess">
|
||||||
|
/// The access to the file mapping object. This access is checked against
|
||||||
|
/// any security descriptor on the target file mapping object.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="bInheritHandle">
|
||||||
|
/// If this parameter is TRUE, a process created by the CreateProcess
|
||||||
|
/// function can inherit the handle; otherwise, the handle cannot be
|
||||||
|
/// inherited.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="lpName">
|
||||||
|
/// The name of the file mapping object to be opened.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the function succeeds, the return value is an open handle to the
|
||||||
|
/// specified file mapping object.
|
||||||
|
/// </returns>
|
||||||
|
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||||
|
public static extern FileMappingHandle OpenFileMapping(
|
||||||
|
FileMapAccess dwDesiredAccess, bool bInheritHandle, string lpName);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps a view of a file mapping into the address space of a calling
|
||||||
|
/// process.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hFileMappingObject">
|
||||||
|
/// A handle to a file mapping object. The CreateFileMapping and
|
||||||
|
/// OpenFileMapping functions return this handle.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="dwDesiredAccess">
|
||||||
|
/// The type of access to a file mapping object, which determines the
|
||||||
|
/// protection of the pages.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="dwFileOffsetHigh">
|
||||||
|
/// A high-order DWORD of the file offset where the view begins.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="dwFileOffsetLow">
|
||||||
|
/// A low-order DWORD of the file offset where the view is to begin.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="dwNumberOfBytesToMap">
|
||||||
|
/// The number of bytes of a file mapping to map to the view. All bytes
|
||||||
|
/// must be within the maximum size specified by CreateFileMapping.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the function succeeds, the return value is the starting address
|
||||||
|
/// of the mapped view.
|
||||||
|
/// </returns>
|
||||||
|
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||||
|
public static extern IntPtr MapViewOfFile(
|
||||||
|
FileMappingHandle hFileMappingObject,
|
||||||
|
FileMapAccess dwDesiredAccess,
|
||||||
|
uint dwFileOffsetHigh,
|
||||||
|
uint dwFileOffsetLow,
|
||||||
|
ulong dwNumberOfBytesToMap);
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||||
|
public static extern IntPtr MapViewOfFileEx(
|
||||||
|
FileMappingHandle hFileMappingObject,
|
||||||
|
FileMapAccess dwDesiredAccess,
|
||||||
|
uint dwFileOffsetHigh,
|
||||||
|
uint dwFileOffsetLow,
|
||||||
|
ulong dwNumberOfBytesToMap,
|
||||||
|
ulong lpBaseAddress);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unmaps a mapped view of a file from the calling process's address
|
||||||
|
/// space.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lpBaseAddress">
|
||||||
|
/// A pointer to the base address of the mapped view of a file that
|
||||||
|
/// is to be unmapped.
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||||
<OutputPath>..\..\build\bin\Release\</OutputPath>
|
<OutputPath>..\..\build\bin\Release\</OutputPath>
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
@ -88,6 +90,8 @@
|
||||||
<Compile Include="ThreadList.cs" />
|
<Compile Include="ThreadList.cs" />
|
||||||
<Compile Include="Utilities\Changeable.cs" />
|
<Compile Include="Utilities\Changeable.cs" />
|
||||||
<Compile Include="Utilities\Dispatch.cs" />
|
<Compile Include="Utilities\Dispatch.cs" />
|
||||||
|
<Compile Include="Utilities\Disposable.cs" />
|
||||||
|
<Compile Include="Utilities\FileMapping.cs" />
|
||||||
<Compile Include="Utilities\TaskExtensions.cs" />
|
<Compile Include="Utilities\TaskExtensions.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|
|
@ -60,14 +60,13 @@ Debugger::~Debugger() {
|
||||||
bool Debugger::StartSession() {
|
bool Debugger::StartSession() {
|
||||||
std::wstring session_path = xe::to_wstring(FLAGS_debug_session_path);
|
std::wstring session_path = xe::to_wstring(FLAGS_debug_session_path);
|
||||||
|
|
||||||
std::wstring functions_path = xe::join_paths(session_path, L"functions");
|
functions_path_ = xe::join_paths(session_path, L"functions");
|
||||||
functions_file_ =
|
functions_file_ =
|
||||||
ChunkedMappedMemoryWriter::Open(functions_path, 32 * 1024 * 1024, false);
|
ChunkedMappedMemoryWriter::Open(functions_path_, 32 * 1024 * 1024, false);
|
||||||
|
|
||||||
std::wstring functions_trace_path =
|
functions_trace_path_ = xe::join_paths(session_path, L"functions.trace");
|
||||||
xe::join_paths(session_path, L"functions.trace");
|
|
||||||
functions_trace_file_ = ChunkedMappedMemoryWriter::Open(
|
functions_trace_file_ = ChunkedMappedMemoryWriter::Open(
|
||||||
functions_trace_path, 32 * 1024 * 1024, true);
|
functions_trace_path_, 32 * 1024 * 1024, true);
|
||||||
|
|
||||||
listen_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
listen_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (listen_socket_ < 1) {
|
if (listen_socket_ < 1) {
|
||||||
|
@ -195,9 +194,12 @@ void Debugger::OnMessage(std::vector<uint8_t> buffer) {
|
||||||
case proto::RequestData_AttachRequest: {
|
case proto::RequestData_AttachRequest: {
|
||||||
// Send debug info.
|
// Send debug info.
|
||||||
response_data_type = proto::ResponseData_AttachResponse;
|
response_data_type = proto::ResponseData_AttachResponse;
|
||||||
auto response_data = proto::AttachResponseBuilder(fbb);
|
response_data_offset =
|
||||||
//
|
proto::CreateAttachResponse(
|
||||||
response_data_offset = response_data.Finish().Union();
|
fbb, fbb.CreateString(
|
||||||
|
xe::to_string(emulator()->memory()->file_name())),
|
||||||
|
fbb.CreateString(xe::to_string(functions_path_)),
|
||||||
|
fbb.CreateString(xe::to_string(functions_trace_path_))).Union();
|
||||||
|
|
||||||
// Allow continuation if we were blocked waiting for a client.
|
// Allow continuation if we were blocked waiting for a client.
|
||||||
accept_fence_.Signal();
|
accept_fence_.Signal();
|
||||||
|
|
|
@ -116,7 +116,9 @@ class Debugger {
|
||||||
UINT_PTR client_socket_;
|
UINT_PTR client_socket_;
|
||||||
std::thread receive_thread_;
|
std::thread receive_thread_;
|
||||||
|
|
||||||
|
std::wstring functions_path_;
|
||||||
std::unique_ptr<ChunkedMappedMemoryWriter> functions_file_;
|
std::unique_ptr<ChunkedMappedMemoryWriter> functions_file_;
|
||||||
|
std::wstring functions_trace_path_;
|
||||||
std::unique_ptr<ChunkedMappedMemoryWriter> functions_trace_file_;
|
std::unique_ptr<ChunkedMappedMemoryWriter> functions_trace_file_;
|
||||||
|
|
||||||
std::mutex threads_lock_;
|
std::mutex threads_lock_;
|
||||||
|
|
|
@ -26,8 +26,9 @@ table AttachRequest {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
table AttachResponse {
|
table AttachResponse {
|
||||||
// file paths
|
memory_file:string;
|
||||||
// mmap name
|
functions_file:string;
|
||||||
|
functions_trace_file:string;
|
||||||
}
|
}
|
||||||
|
|
||||||
union RequestData {
|
union RequestData {
|
||||||
|
|
|
@ -167,8 +167,17 @@ inline flatbuffers::Offset<AttachRequest> CreateAttachRequest(flatbuffers::FlatB
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AttachResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct AttachResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
|
const flatbuffers::String *memory_file() const { return GetPointer<const flatbuffers::String *>(4); }
|
||||||
|
const flatbuffers::String *functions_file() const { return GetPointer<const flatbuffers::String *>(6); }
|
||||||
|
const flatbuffers::String *functions_trace_file() const { return GetPointer<const flatbuffers::String *>(8); }
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
|
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* memory_file */) &&
|
||||||
|
verifier.Verify(memory_file()) &&
|
||||||
|
VerifyField<flatbuffers::uoffset_t>(verifier, 6 /* functions_file */) &&
|
||||||
|
verifier.Verify(functions_file()) &&
|
||||||
|
VerifyField<flatbuffers::uoffset_t>(verifier, 8 /* functions_trace_file */) &&
|
||||||
|
verifier.Verify(functions_trace_file()) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -176,16 +185,25 @@ struct AttachResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
struct AttachResponseBuilder {
|
struct AttachResponseBuilder {
|
||||||
flatbuffers::FlatBufferBuilder &fbb_;
|
flatbuffers::FlatBufferBuilder &fbb_;
|
||||||
flatbuffers::uoffset_t start_;
|
flatbuffers::uoffset_t start_;
|
||||||
|
void add_memory_file(flatbuffers::Offset<flatbuffers::String> memory_file) { fbb_.AddOffset(4, memory_file); }
|
||||||
|
void add_functions_file(flatbuffers::Offset<flatbuffers::String> functions_file) { fbb_.AddOffset(6, functions_file); }
|
||||||
|
void add_functions_trace_file(flatbuffers::Offset<flatbuffers::String> functions_trace_file) { fbb_.AddOffset(8, functions_trace_file); }
|
||||||
AttachResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
AttachResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||||
AttachResponseBuilder &operator=(const AttachResponseBuilder &);
|
AttachResponseBuilder &operator=(const AttachResponseBuilder &);
|
||||||
flatbuffers::Offset<AttachResponse> Finish() {
|
flatbuffers::Offset<AttachResponse> Finish() {
|
||||||
auto o = flatbuffers::Offset<AttachResponse>(fbb_.EndTable(start_, 0));
|
auto o = flatbuffers::Offset<AttachResponse>(fbb_.EndTable(start_, 3));
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline flatbuffers::Offset<AttachResponse> CreateAttachResponse(flatbuffers::FlatBufferBuilder &_fbb) {
|
inline flatbuffers::Offset<AttachResponse> CreateAttachResponse(flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
flatbuffers::Offset<flatbuffers::String> memory_file = 0,
|
||||||
|
flatbuffers::Offset<flatbuffers::String> functions_file = 0,
|
||||||
|
flatbuffers::Offset<flatbuffers::String> functions_trace_file = 0) {
|
||||||
AttachResponseBuilder builder_(_fbb);
|
AttachResponseBuilder builder_(_fbb);
|
||||||
|
builder_.add_functions_trace_file(functions_trace_file);
|
||||||
|
builder_.add_functions_file(functions_file);
|
||||||
|
builder_.add_memory_file(memory_file);
|
||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/math.h"
|
#include "xenia/base/math.h"
|
||||||
|
#include "xenia/base/threading.h"
|
||||||
#include "xenia/cpu/mmio_handler.h"
|
#include "xenia/cpu/mmio_handler.h"
|
||||||
|
|
||||||
// TODO(benvanik): move xbox.h out
|
// TODO(benvanik): move xbox.h out
|
||||||
|
@ -114,13 +115,17 @@ Memory::~Memory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Memory::Initialize() {
|
int Memory::Initialize() {
|
||||||
|
wchar_t file_name[256];
|
||||||
|
wsprintf(file_name, L"Local\\xenia_memory_%p", xe::threading::ticks());
|
||||||
|
file_name_ = file_name;
|
||||||
|
|
||||||
// Create main page file-backed mapping. This is all reserved but
|
// Create main page file-backed mapping. This is all reserved but
|
||||||
// uncommitted (so it shouldn't expand page file).
|
// uncommitted (so it shouldn't expand page file).
|
||||||
#if XE_PLATFORM_WIN32
|
#if XE_PLATFORM_WIN32
|
||||||
mapping_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
|
mapping_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
|
||||||
PAGE_READWRITE | SEC_RESERVE,
|
PAGE_READWRITE | SEC_RESERVE,
|
||||||
// entire 4gb space + 512mb physical:
|
// entire 4gb space + 512mb physical:
|
||||||
1, 0x1FFFFFFF, NULL);
|
1, 0x1FFFFFFF, file_name_.c_str());
|
||||||
#else
|
#else
|
||||||
char mapping_path[] = "/xenia/mapping/XXXXXX";
|
char mapping_path[] = "/xenia/mapping/XXXXXX";
|
||||||
mktemp(mapping_path);
|
mktemp(mapping_path);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/base/platform.h"
|
#include "xenia/base/platform.h"
|
||||||
|
@ -158,6 +159,8 @@ class Memory {
|
||||||
|
|
||||||
int Initialize();
|
int Initialize();
|
||||||
|
|
||||||
|
const std::wstring& file_name() const { return file_name_; }
|
||||||
|
|
||||||
inline uint8_t* virtual_membase() const { return virtual_membase_; }
|
inline uint8_t* virtual_membase() const { return virtual_membase_; }
|
||||||
inline uint8_t* TranslateVirtual(uint32_t guest_address) const {
|
inline uint8_t* TranslateVirtual(uint32_t guest_address) const {
|
||||||
return virtual_membase_ + guest_address;
|
return virtual_membase_ + guest_address;
|
||||||
|
@ -211,6 +214,7 @@ class Memory {
|
||||||
void UnmapViews();
|
void UnmapViews();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::wstring file_name_;
|
||||||
uint32_t system_page_size_;
|
uint32_t system_page_size_;
|
||||||
uint8_t* virtual_membase_;
|
uint8_t* virtual_membase_;
|
||||||
uint8_t* physical_membase_;
|
uint8_t* physical_membase_;
|
||||||
|
|
Loading…
Reference in New Issue