Sharing memory.
This commit is contained in:
parent
576d6492dc
commit
da655d15b3
|
@ -12,7 +12,6 @@ using xe.debug.proto;
|
|||
using Xenia.Debug.Utilities;
|
||||
|
||||
namespace Xenia.Debug {
|
||||
|
||||
public class Debugger {
|
||||
private readonly static string kServerHostname = "";
|
||||
private readonly static int kServerPort = 19000;
|
||||
|
@ -35,6 +34,19 @@ namespace Xenia.Debug {
|
|||
pendingRequests = new ConcurrentDictionary<uint, PendingRequest>();
|
||||
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 State CurrentState {
|
||||
|
@ -126,6 +138,27 @@ namespace Xenia.Debug {
|
|||
int requestDataOffset = AttachRequest.EndAttachRequest(fbb);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -134,8 +167,17 @@ namespace Xenia.Debug {
|
|||
return;
|
||||
}
|
||||
|
||||
Memory.UninitializeMapping();
|
||||
|
||||
if (memoryHandle != null) {
|
||||
memoryHandle.Close();
|
||||
memoryHandle = null;
|
||||
}
|
||||
|
||||
if (socket != null) {
|
||||
socket.Close();
|
||||
socket = null;
|
||||
}
|
||||
|
||||
OnStateChanged(State.Detached);
|
||||
}
|
||||
|
|
|
@ -6,15 +6,100 @@ using System.Threading.Tasks;
|
|||
using Xenia.Debug.Utilities;
|
||||
|
||||
namespace Xenia.Debug {
|
||||
public class Memory : Changeable {
|
||||
public class Memory : Changeable, IDisposable {
|
||||
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) {
|
||||
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() {
|
||||
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 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) {
|
||||
int o = builder.EndObject();
|
||||
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>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>..\..\build\bin\Release\</OutputPath>
|
||||
|
@ -31,6 +32,7 @@
|
|||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
|
@ -88,6 +90,8 @@
|
|||
<Compile Include="ThreadList.cs" />
|
||||
<Compile Include="Utilities\Changeable.cs" />
|
||||
<Compile Include="Utilities\Dispatch.cs" />
|
||||
<Compile Include="Utilities\Disposable.cs" />
|
||||
<Compile Include="Utilities\FileMapping.cs" />
|
||||
<Compile Include="Utilities\TaskExtensions.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
|
|
@ -60,14 +60,13 @@ Debugger::~Debugger() {
|
|||
bool Debugger::StartSession() {
|
||||
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_ =
|
||||
ChunkedMappedMemoryWriter::Open(functions_path, 32 * 1024 * 1024, false);
|
||||
ChunkedMappedMemoryWriter::Open(functions_path_, 32 * 1024 * 1024, false);
|
||||
|
||||
std::wstring functions_trace_path =
|
||||
xe::join_paths(session_path, L"functions.trace");
|
||||
functions_trace_path_ = xe::join_paths(session_path, L"functions.trace");
|
||||
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);
|
||||
if (listen_socket_ < 1) {
|
||||
|
@ -195,9 +194,12 @@ void Debugger::OnMessage(std::vector<uint8_t> buffer) {
|
|||
case proto::RequestData_AttachRequest: {
|
||||
// Send debug info.
|
||||
response_data_type = proto::ResponseData_AttachResponse;
|
||||
auto response_data = proto::AttachResponseBuilder(fbb);
|
||||
//
|
||||
response_data_offset = response_data.Finish().Union();
|
||||
response_data_offset =
|
||||
proto::CreateAttachResponse(
|
||||
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.
|
||||
accept_fence_.Signal();
|
||||
|
|
|
@ -116,7 +116,9 @@ class Debugger {
|
|||
UINT_PTR client_socket_;
|
||||
std::thread receive_thread_;
|
||||
|
||||
std::wstring functions_path_;
|
||||
std::unique_ptr<ChunkedMappedMemoryWriter> functions_file_;
|
||||
std::wstring functions_trace_path_;
|
||||
std::unique_ptr<ChunkedMappedMemoryWriter> functions_trace_file_;
|
||||
|
||||
std::mutex threads_lock_;
|
||||
|
|
|
@ -26,8 +26,9 @@ table AttachRequest {
|
|||
//
|
||||
}
|
||||
table AttachResponse {
|
||||
// file paths
|
||||
// mmap name
|
||||
memory_file:string;
|
||||
functions_file:string;
|
||||
functions_trace_file:string;
|
||||
}
|
||||
|
||||
union RequestData {
|
||||
|
|
|
@ -167,8 +167,17 @@ inline flatbuffers::Offset<AttachRequest> CreateAttachRequest(flatbuffers::FlatB
|
|||
}
|
||||
|
||||
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 {
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
@ -176,16 +185,25 @@ struct AttachResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||
struct AttachResponseBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
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 &operator=(const AttachResponseBuilder &);
|
||||
flatbuffers::Offset<AttachResponse> Finish() {
|
||||
auto o = flatbuffers::Offset<AttachResponse>(fbb_.EndTable(start_, 0));
|
||||
auto o = flatbuffers::Offset<AttachResponse>(fbb_.EndTable(start_, 3));
|
||||
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);
|
||||
builder_.add_functions_trace_file(functions_trace_file);
|
||||
builder_.add_functions_file(functions_file);
|
||||
builder_.add_memory_file(memory_file);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/cpu/mmio_handler.h"
|
||||
|
||||
// TODO(benvanik): move xbox.h out
|
||||
|
@ -114,13 +115,17 @@ Memory::~Memory() {
|
|||
}
|
||||
|
||||
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
|
||||
// uncommitted (so it shouldn't expand page file).
|
||||
#if XE_PLATFORM_WIN32
|
||||
mapping_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
|
||||
PAGE_READWRITE | SEC_RESERVE,
|
||||
// entire 4gb space + 512mb physical:
|
||||
1, 0x1FFFFFFF, NULL);
|
||||
1, 0x1FFFFFFF, file_name_.c_str());
|
||||
#else
|
||||
char mapping_path[] = "/xenia/mapping/XXXXXX";
|
||||
mktemp(mapping_path);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
@ -158,6 +159,8 @@ class Memory {
|
|||
|
||||
int Initialize();
|
||||
|
||||
const std::wstring& file_name() const { return file_name_; }
|
||||
|
||||
inline uint8_t* virtual_membase() const { return virtual_membase_; }
|
||||
inline uint8_t* TranslateVirtual(uint32_t guest_address) const {
|
||||
return virtual_membase_ + guest_address;
|
||||
|
@ -211,6 +214,7 @@ class Memory {
|
|||
void UnmapViews();
|
||||
|
||||
private:
|
||||
std::wstring file_name_;
|
||||
uint32_t system_page_size_;
|
||||
uint8_t* virtual_membase_;
|
||||
uint8_t* physical_membase_;
|
||||
|
|
Loading…
Reference in New Issue