Partial thread data plumbing.

This commit is contained in:
Ben Vanik 2015-06-16 21:53:40 -07:00
parent aae45515ae
commit b750370759
13 changed files with 288 additions and 31 deletions

View File

@ -312,6 +312,7 @@ namespace Xenia.Debug {
private async Task CompleteRunStateTransition(RunState newRunState) { private async Task CompleteRunStateTransition(RunState newRunState) {
await Task.WhenAll(new Task[] { await Task.WhenAll(new Task[] {
ModuleList.Invalidate(), ModuleList.Invalidate(),
ThreadList.Invalidate(),
}); });
CurrentContext.SetRunState(newRunState); CurrentContext.SetRunState(newRunState);

View File

@ -10,8 +10,21 @@ public sealed class ListThreadsResponse : Table {
public static ListThreadsResponse GetRootAsListThreadsResponse(ByteBuffer _bb, ListThreadsResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } public static ListThreadsResponse GetRootAsListThreadsResponse(ByteBuffer _bb, ListThreadsResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public ListThreadsResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } public ListThreadsResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public Thread GetThread(int j) { return GetThread(new Thread(), j); }
public Thread GetThread(Thread obj, int j) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(__vector(o) + j * 4), bb) : null; }
public int ThreadLength { get { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } }
public static void StartListThreadsResponse(FlatBufferBuilder builder) { builder.StartObject(0); } public static int CreateListThreadsResponse(FlatBufferBuilder builder,
int thread = 0) {
builder.StartObject(1);
ListThreadsResponse.AddThread(builder, thread);
return ListThreadsResponse.EndListThreadsResponse(builder);
}
public static void StartListThreadsResponse(FlatBufferBuilder builder) { builder.StartObject(1); }
public static void AddThread(FlatBufferBuilder builder, int threadOffset) { builder.AddOffset(0, threadOffset, 0); }
public static int CreateThreadVector(FlatBufferBuilder builder, int[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i]); return builder.EndVector(); }
public static void StartThreadVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static int EndListThreadsResponse(FlatBufferBuilder builder) { public static int EndListThreadsResponse(FlatBufferBuilder builder) {
int o = builder.EndObject(); int o = builder.EndObject();
return o; return o;

View File

@ -15,10 +15,11 @@ public enum RequestData : byte
GetModuleRequest = 7, GetModuleRequest = 7,
ListFunctionsRequest = 8, ListFunctionsRequest = 8,
GetFunctionRequest = 9, GetFunctionRequest = 9,
StopRequest = 10, ListThreadsRequest = 10,
BreakRequest = 11, StopRequest = 11,
ContinueRequest = 12, BreakRequest = 12,
StepRequest = 13, ContinueRequest = 13,
StepRequest = 14,
}; };

View File

@ -15,12 +15,13 @@ public enum ResponseData : byte
GetModuleResponse = 7, GetModuleResponse = 7,
ListFunctionsResponse = 8, ListFunctionsResponse = 8,
GetFunctionResponse = 9, GetFunctionResponse = 9,
StopResponse = 10, ListThreadsResponse = 10,
BreakResponse = 11, StopResponse = 11,
ContinueResponse = 12, BreakResponse = 12,
StepResponse = 13, ContinueResponse = 13,
BreakpointEvent = 14, StepResponse = 14,
AccessViolationEvent = 15, BreakpointEvent = 15,
AccessViolationEvent = 16,
}; };

View File

@ -13,10 +13,36 @@ public sealed class Thread : Table {
public XObject Object { get { return GetObject(new XObject()); } } public XObject Object { get { return GetObject(new XObject()); } }
public XObject GetObject(XObject obj) { int o = __offset(4); return o != 0 ? obj.__init(o + bb_pos, bb) : null; } public XObject GetObject(XObject obj) { int o = __offset(4); return o != 0 ? obj.__init(o + bb_pos, bb) : null; }
public ThreadType Type { get { int o = __offset(6); return o != 0 ? (ThreadType)bb.GetSbyte(o + bb_pos) : (ThreadType)0; } } public ThreadType Type { get { int o = __offset(6); return o != 0 ? (ThreadType)bb.GetSbyte(o + bb_pos) : (ThreadType)0; } }
public uint StackSize { get { int o = __offset(8); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public uint XapiThreadStartup { get { int o = __offset(10); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public uint StartAddress { get { int o = __offset(12); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public uint StartContext { get { int o = __offset(14); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public uint CreationFlags { get { int o = __offset(16); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public uint TlsAddress { get { int o = __offset(18); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public uint PcrAddress { get { int o = __offset(20); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public uint ThreadStateAddress { get { int o = __offset(22); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public uint ThreadId { get { int o = __offset(24); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public string Name { get { int o = __offset(26); return o != 0 ? __string(o + bb_pos) : null; } }
public uint Priority { get { int o = __offset(28); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public uint Affinity { get { int o = __offset(30); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public uint State { get { int o = __offset(32); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public static void StartThread(FlatBufferBuilder builder) { builder.StartObject(2); } public static void StartThread(FlatBufferBuilder builder) { builder.StartObject(15); }
public static void AddObject(FlatBufferBuilder builder, int objectOffset) { builder.AddStruct(0, objectOffset, 0); } public static void AddObject(FlatBufferBuilder builder, int objectOffset) { builder.AddStruct(0, objectOffset, 0); }
public static void AddType(FlatBufferBuilder builder, ThreadType type) { builder.AddSbyte(1, (sbyte)(type), 0); } public static void AddType(FlatBufferBuilder builder, ThreadType type) { builder.AddSbyte(1, (sbyte)(type), 0); }
public static void AddStackSize(FlatBufferBuilder builder, uint stackSize) { builder.AddUint(2, stackSize, 0); }
public static void AddXapiThreadStartup(FlatBufferBuilder builder, uint xapiThreadStartup) { builder.AddUint(3, xapiThreadStartup, 0); }
public static void AddStartAddress(FlatBufferBuilder builder, uint startAddress) { builder.AddUint(4, startAddress, 0); }
public static void AddStartContext(FlatBufferBuilder builder, uint startContext) { builder.AddUint(5, startContext, 0); }
public static void AddCreationFlags(FlatBufferBuilder builder, uint creationFlags) { builder.AddUint(6, creationFlags, 0); }
public static void AddTlsAddress(FlatBufferBuilder builder, uint tlsAddress) { builder.AddUint(7, tlsAddress, 0); }
public static void AddPcrAddress(FlatBufferBuilder builder, uint pcrAddress) { builder.AddUint(8, pcrAddress, 0); }
public static void AddThreadStateAddress(FlatBufferBuilder builder, uint threadStateAddress) { builder.AddUint(9, threadStateAddress, 0); }
public static void AddThreadId(FlatBufferBuilder builder, uint threadId) { builder.AddUint(10, threadId, 0); }
public static void AddName(FlatBufferBuilder builder, int nameOffset) { builder.AddOffset(11, nameOffset, 0); }
public static void AddPriority(FlatBufferBuilder builder, uint priority) { builder.AddUint(12, priority, 0); }
public static void AddAffinity(FlatBufferBuilder builder, uint affinity) { builder.AddUint(13, affinity, 0); }
public static void AddState(FlatBufferBuilder builder, uint state) { builder.AddUint(14, state, 0); }
public static int EndThread(FlatBufferBuilder builder) { public static int EndThread(FlatBufferBuilder builder) {
int o = builder.EndObject(); int o = builder.EndObject();
return o; return o;

View File

@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using xe.debug.proto;
using Xenia.Debug.Utilities; using Xenia.Debug.Utilities;
namespace Xenia.Debug { namespace Xenia.Debug {
@ -25,6 +26,23 @@ namespace Xenia.Debug {
this.debugger = debugger; this.debugger = debugger;
} }
public async Task Invalidate() {
var fbb = debugger.BeginRequest();
ListThreadsRequest.StartListThreadsRequest(fbb);
int requestDataOffset = ListThreadsRequest.EndListThreadsRequest(fbb);
var response = await debugger.CommitRequest(
fbb, RequestData.ListThreadsRequest, requestDataOffset);
ListThreadsResponse responseData = new ListThreadsResponse();
response.GetResponseData(responseData);
for (int i = 0; i < responseData.ThreadLength; ++i) {
var threadData = responseData.GetThread(i);
// threadData.Name;
}
OnChanged();
}
public int Count { public int Count {
get { get {
return threads.Count; return threads.Count;

View File

@ -35,6 +35,7 @@
#include "xenia/debug/proto/control_generated.h" #include "xenia/debug/proto/control_generated.h"
#include "xenia/debug/proto/messages_generated.h" #include "xenia/debug/proto/messages_generated.h"
#include "xenia/debug/proto/modules_generated.h" #include "xenia/debug/proto/modules_generated.h"
#include "xenia/debug/proto/threads_generated.h"
DEFINE_string(debug_session_path, "", "Debug output path."); DEFINE_string(debug_session_path, "", "Debug output path.");
DEFINE_int32(debug_port, 19000, "Port the debugger listens on."); DEFINE_int32(debug_port, 19000, "Port the debugger listens on.");
@ -400,6 +401,38 @@ void Debugger::OnMessage(std::vector<uint8_t> buffer) {
response_data_offset = response_data.Finish().Union(); response_data_offset = response_data.Finish().Union();
} break; } break;
case proto::RequestData_ListThreadsRequest: {
response_data_type = proto::ResponseData_ListThreadsResponse;
auto threads =
emulator()->kernel_state()->object_table()->GetObjectsByType<XThread>(
XObject::kTypeThread);
std::vector<flatbuffers::Offset<proto::Thread>> thread_list;
for (size_t i = 0; i < threads.size(); ++i) {
auto& thread = threads[i];
auto thread_name_string = fbb.CreateString(thread->name());
auto thread_builder = proto::ThreadBuilder(fbb);
// thread_builder.add_type();
// thread_builder.add_stack_size();
// thread_builder.add_xapi_thread_startup();
// thread_builder.add_start_address();
// thread_builder.add_start_context();
// thread_builder.add_creation_flags();
thread_builder.add_tls_address(thread->tls_ptr());
thread_builder.add_pcr_address(thread->pcr_ptr());
thread_builder.add_thread_state_address(thread->thread_state_ptr());
thread_builder.add_thread_id(thread->thread_id());
thread_builder.add_name(thread_name_string);
thread_builder.add_priority(thread->priority());
thread_builder.add_affinity(thread->affinity());
// thread_builder.add_state(thread->);
thread_list.push_back(thread_builder.Finish());
}
auto threads_offset = fbb.CreateVector(thread_list);
auto response_data = proto::ListThreadsResponseBuilder(fbb);
response_data.add_thread(threads_offset);
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_StopRequest: { case proto::RequestData_StopRequest: {
response_data_type = proto::ResponseData_StopResponse; response_data_type = proto::ResponseData_StopResponse;
auto response_data = proto::StopResponseBuilder(fbb); auto response_data = proto::StopResponseBuilder(fbb);

View File

@ -31,6 +31,8 @@ union RequestData {
ListFunctionsRequest, ListFunctionsRequest,
GetFunctionRequest, GetFunctionRequest,
ListThreadsRequest,
StopRequest, StopRequest,
BreakRequest, BreakRequest,
ContinueRequest, ContinueRequest,
@ -55,6 +57,8 @@ union ResponseData {
ListFunctionsResponse, ListFunctionsResponse,
GetFunctionResponse, GetFunctionResponse,
ListThreadsResponse,
StopResponse, StopResponse,
BreakResponse, BreakResponse,
ContinueResponse, ContinueResponse,

View File

@ -91,14 +91,23 @@ enum RequestData {
RequestData_GetModuleRequest = 7, RequestData_GetModuleRequest = 7,
RequestData_ListFunctionsRequest = 8, RequestData_ListFunctionsRequest = 8,
RequestData_GetFunctionRequest = 9, RequestData_GetFunctionRequest = 9,
RequestData_StopRequest = 10, RequestData_ListThreadsRequest = 10,
RequestData_BreakRequest = 11, RequestData_StopRequest = 11,
RequestData_ContinueRequest = 12, RequestData_BreakRequest = 12,
RequestData_StepRequest = 13 RequestData_ContinueRequest = 13,
RequestData_StepRequest = 14
}; };
inline const char **EnumNamesRequestData() { inline const char **EnumNamesRequestData() {
static const char *names[] = { "NONE", "AttachRequest", "ListBreakpointsRequest", "AddBreakpointsRequest", "UpdateBreakpointsRequest", "RemoveBreakpointsRequest", "ListModulesRequest", "GetModuleRequest", "ListFunctionsRequest", "GetFunctionRequest", "StopRequest", "BreakRequest", "ContinueRequest", "StepRequest", nullptr }; static const char *names[] = {
"NONE", "AttachRequest",
"ListBreakpointsRequest", "AddBreakpointsRequest",
"UpdateBreakpointsRequest", "RemoveBreakpointsRequest",
"ListModulesRequest", "GetModuleRequest",
"ListFunctionsRequest", "GetFunctionRequest",
"ListThreadsRequest", "StopRequest",
"BreakRequest", "ContinueRequest",
"StepRequest", nullptr};
return names; return names;
} }
@ -117,16 +126,26 @@ enum ResponseData {
ResponseData_GetModuleResponse = 7, ResponseData_GetModuleResponse = 7,
ResponseData_ListFunctionsResponse = 8, ResponseData_ListFunctionsResponse = 8,
ResponseData_GetFunctionResponse = 9, ResponseData_GetFunctionResponse = 9,
ResponseData_StopResponse = 10, ResponseData_ListThreadsResponse = 10,
ResponseData_BreakResponse = 11, ResponseData_StopResponse = 11,
ResponseData_ContinueResponse = 12, ResponseData_BreakResponse = 12,
ResponseData_StepResponse = 13, ResponseData_ContinueResponse = 13,
ResponseData_BreakpointEvent = 14, ResponseData_StepResponse = 14,
ResponseData_AccessViolationEvent = 15 ResponseData_BreakpointEvent = 15,
ResponseData_AccessViolationEvent = 16
}; };
inline const char **EnumNamesResponseData() { inline const char **EnumNamesResponseData() {
static const char *names[] = { "NONE", "AttachResponse", "ListBreakpointsResponse", "AddBreakpointsResponse", "UpdateBreakpointsResponse", "RemoveBreakpointsResponse", "ListModulesResponse", "GetModuleResponse", "ListFunctionsResponse", "GetFunctionResponse", "StopResponse", "BreakResponse", "ContinueResponse", "StepResponse", "BreakpointEvent", "AccessViolationEvent", nullptr }; static const char *names[] = {
"NONE", "AttachResponse",
"ListBreakpointsResponse", "AddBreakpointsResponse",
"UpdateBreakpointsResponse", "RemoveBreakpointsResponse",
"ListModulesResponse", "GetModuleResponse",
"ListFunctionsResponse", "GetFunctionResponse",
"ListThreadsResponse", "StopResponse",
"BreakResponse", "ContinueResponse",
"StepResponse", "BreakpointEvent",
"AccessViolationEvent", nullptr};
return names; return names;
} }
@ -304,6 +323,10 @@ inline bool VerifyRequestData(flatbuffers::Verifier &verifier, const void *union
case RequestData_GetModuleRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::GetModuleRequest *>(union_obj)); case RequestData_GetModuleRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::GetModuleRequest *>(union_obj));
case RequestData_ListFunctionsRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ListFunctionsRequest *>(union_obj)); case RequestData_ListFunctionsRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ListFunctionsRequest *>(union_obj));
case RequestData_GetFunctionRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::GetFunctionRequest *>(union_obj)); case RequestData_GetFunctionRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::GetFunctionRequest *>(union_obj));
case RequestData_ListThreadsRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ListThreadsRequest *>(
union_obj));
case RequestData_StopRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::StopRequest *>(union_obj)); case RequestData_StopRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::StopRequest *>(union_obj));
case RequestData_BreakRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::BreakRequest *>(union_obj)); case RequestData_BreakRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::BreakRequest *>(union_obj));
case RequestData_ContinueRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ContinueRequest *>(union_obj)); case RequestData_ContinueRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ContinueRequest *>(union_obj));
@ -324,6 +347,10 @@ inline bool VerifyResponseData(flatbuffers::Verifier &verifier, const void *unio
case ResponseData_GetModuleResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::GetModuleResponse *>(union_obj)); case ResponseData_GetModuleResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::GetModuleResponse *>(union_obj));
case ResponseData_ListFunctionsResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ListFunctionsResponse *>(union_obj)); case ResponseData_ListFunctionsResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ListFunctionsResponse *>(union_obj));
case ResponseData_GetFunctionResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::GetFunctionResponse *>(union_obj)); case ResponseData_GetFunctionResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::GetFunctionResponse *>(union_obj));
case ResponseData_ListThreadsResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ListThreadsResponse *>(
union_obj));
case ResponseData_StopResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::StopResponse *>(union_obj)); case ResponseData_StopResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::StopResponse *>(union_obj));
case ResponseData_BreakResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::BreakResponse *>(union_obj)); case ResponseData_BreakResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::BreakResponse *>(union_obj));
case ResponseData_ContinueResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ContinueResponse *>(union_obj)); case ResponseData_ContinueResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ContinueResponse *>(union_obj));

View File

@ -13,9 +13,26 @@ table Thread {
// module_id:uint; // module_id:uint;
// creation callstack // creation callstack
stack_size:uint;
xapi_thread_startup:uint;
start_address:uint;
start_context:uint;
creation_flags:uint;
tls_address:uint;
pcr_address:uint;
thread_state_address:uint;
thread_id:uint;
name:string;
priority:uint;
affinity:uint;
state:uint;
} }
table ListThreadsRequest { table ListThreadsRequest {
} }
table ListThreadsResponse { table ListThreadsResponse {
thread:[Thread];
} }

View File

@ -36,10 +36,39 @@ inline const char *EnumNameThreadType(ThreadType e) { return EnumNamesThreadType
struct Thread FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Thread FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const xe::debug::proto::XObject *object() const { return GetStruct<const xe::debug::proto::XObject *>(4); } const xe::debug::proto::XObject *object() const { return GetStruct<const xe::debug::proto::XObject *>(4); }
ThreadType type() const { return static_cast<ThreadType>(GetField<int8_t>(6, 0)); } ThreadType type() const { return static_cast<ThreadType>(GetField<int8_t>(6, 0)); }
uint32_t stack_size() const { return GetField<uint32_t>(8, 0); }
uint32_t xapi_thread_startup() const { return GetField<uint32_t>(10, 0); }
uint32_t start_address() const { return GetField<uint32_t>(12, 0); }
uint32_t start_context() const { return GetField<uint32_t>(14, 0); }
uint32_t creation_flags() const { return GetField<uint32_t>(16, 0); }
uint32_t tls_address() const { return GetField<uint32_t>(18, 0); }
uint32_t pcr_address() const { return GetField<uint32_t>(20, 0); }
uint32_t thread_state_address() const { return GetField<uint32_t>(22, 0); }
uint32_t thread_id() const { return GetField<uint32_t>(24, 0); }
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(26);
}
uint32_t priority() const { return GetField<uint32_t>(28, 0); }
uint32_t affinity() const { return GetField<uint32_t>(30, 0); }
uint32_t state() const { return GetField<uint32_t>(32, 0); }
bool Verify(flatbuffers::Verifier &verifier) const { bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) && return VerifyTableStart(verifier) &&
VerifyField<xe::debug::proto::XObject>(verifier, 4 /* object */) && VerifyField<xe::debug::proto::XObject>(verifier, 4 /* object */) &&
VerifyField<int8_t>(verifier, 6 /* type */) && VerifyField<int8_t>(verifier, 6 /* type */) &&
VerifyField<uint32_t>(verifier, 8 /* stack_size */) &&
VerifyField<uint32_t>(verifier, 10 /* xapi_thread_startup */) &&
VerifyField<uint32_t>(verifier, 12 /* start_address */) &&
VerifyField<uint32_t>(verifier, 14 /* start_context */) &&
VerifyField<uint32_t>(verifier, 16 /* creation_flags */) &&
VerifyField<uint32_t>(verifier, 18 /* tls_address */) &&
VerifyField<uint32_t>(verifier, 20 /* pcr_address */) &&
VerifyField<uint32_t>(verifier, 22 /* thread_state_address */) &&
VerifyField<uint32_t>(verifier, 24 /* thread_id */) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 26 /* name */) &&
verifier.Verify(name()) &&
VerifyField<uint32_t>(verifier, 28 /* priority */) &&
VerifyField<uint32_t>(verifier, 30 /* affinity */) &&
VerifyField<uint32_t>(verifier, 32 /* state */) &&
verifier.EndTable(); verifier.EndTable();
} }
}; };
@ -49,18 +78,75 @@ struct ThreadBuilder {
flatbuffers::uoffset_t start_; flatbuffers::uoffset_t start_;
void add_object(const xe::debug::proto::XObject *object) { fbb_.AddStruct(4, object); } void add_object(const xe::debug::proto::XObject *object) { fbb_.AddStruct(4, object); }
void add_type(ThreadType type) { fbb_.AddElement<int8_t>(6, static_cast<int8_t>(type), 0); } void add_type(ThreadType type) { fbb_.AddElement<int8_t>(6, static_cast<int8_t>(type), 0); }
void add_stack_size(uint32_t stack_size) {
fbb_.AddElement<uint32_t>(8, stack_size, 0);
}
void add_xapi_thread_startup(uint32_t xapi_thread_startup) {
fbb_.AddElement<uint32_t>(10, xapi_thread_startup, 0);
}
void add_start_address(uint32_t start_address) {
fbb_.AddElement<uint32_t>(12, start_address, 0);
}
void add_start_context(uint32_t start_context) {
fbb_.AddElement<uint32_t>(14, start_context, 0);
}
void add_creation_flags(uint32_t creation_flags) {
fbb_.AddElement<uint32_t>(16, creation_flags, 0);
}
void add_tls_address(uint32_t tls_address) {
fbb_.AddElement<uint32_t>(18, tls_address, 0);
}
void add_pcr_address(uint32_t pcr_address) {
fbb_.AddElement<uint32_t>(20, pcr_address, 0);
}
void add_thread_state_address(uint32_t thread_state_address) {
fbb_.AddElement<uint32_t>(22, thread_state_address, 0);
}
void add_thread_id(uint32_t thread_id) {
fbb_.AddElement<uint32_t>(24, thread_id, 0);
}
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(26, name);
}
void add_priority(uint32_t priority) {
fbb_.AddElement<uint32_t>(28, priority, 0);
}
void add_affinity(uint32_t affinity) {
fbb_.AddElement<uint32_t>(30, affinity, 0);
}
void add_state(uint32_t state) { fbb_.AddElement<uint32_t>(32, state, 0); }
ThreadBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } ThreadBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
ThreadBuilder &operator=(const ThreadBuilder &); ThreadBuilder &operator=(const ThreadBuilder &);
flatbuffers::Offset<Thread> Finish() { flatbuffers::Offset<Thread> Finish() {
auto o = flatbuffers::Offset<Thread>(fbb_.EndTable(start_, 2)); auto o = flatbuffers::Offset<Thread>(fbb_.EndTable(start_, 15));
return o; return o;
} }
}; };
inline flatbuffers::Offset<Thread> CreateThread(flatbuffers::FlatBufferBuilder &_fbb, inline flatbuffers::Offset<Thread> CreateThread(
const xe::debug::proto::XObject *object = 0, flatbuffers::FlatBufferBuilder &_fbb,
ThreadType type = ThreadType_Kernel) { const xe::debug::proto::XObject *object = 0,
ThreadType type = ThreadType_Kernel, uint32_t stack_size = 0,
uint32_t xapi_thread_startup = 0, uint32_t start_address = 0,
uint32_t start_context = 0, uint32_t creation_flags = 0,
uint32_t tls_address = 0, uint32_t pcr_address = 0,
uint32_t thread_state_address = 0, uint32_t thread_id = 0,
flatbuffers::Offset<flatbuffers::String> name = 0, uint32_t priority = 0,
uint32_t affinity = 0, uint32_t state = 0) {
ThreadBuilder builder_(_fbb); ThreadBuilder builder_(_fbb);
builder_.add_state(state);
builder_.add_affinity(affinity);
builder_.add_priority(priority);
builder_.add_name(name);
builder_.add_thread_id(thread_id);
builder_.add_thread_state_address(thread_state_address);
builder_.add_pcr_address(pcr_address);
builder_.add_tls_address(tls_address);
builder_.add_creation_flags(creation_flags);
builder_.add_start_context(start_context);
builder_.add_start_address(start_address);
builder_.add_xapi_thread_startup(xapi_thread_startup);
builder_.add_stack_size(stack_size);
builder_.add_object(object); builder_.add_object(object);
builder_.add_type(type); builder_.add_type(type);
return builder_.Finish(); return builder_.Finish();
@ -90,25 +176,39 @@ inline flatbuffers::Offset<ListThreadsRequest> CreateListThreadsRequest(flatbuff
} }
struct ListThreadsResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct ListThreadsResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::Vector<flatbuffers::Offset<Thread>> *thread() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Thread>> *>(
4);
}
bool Verify(flatbuffers::Verifier &verifier) const { bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) && return VerifyTableStart(verifier) &&
verifier.EndTable(); VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* thread */) &&
verifier.Verify(thread()) &&
verifier.VerifyVectorOfTables(thread()) && verifier.EndTable();
} }
}; };
struct ListThreadsResponseBuilder { struct ListThreadsResponseBuilder {
flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_; flatbuffers::uoffset_t start_;
void add_thread(flatbuffers::Offset<
flatbuffers::Vector<flatbuffers::Offset<Thread>>> thread) {
fbb_.AddOffset(4, thread);
}
ListThreadsResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } ListThreadsResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
ListThreadsResponseBuilder &operator=(const ListThreadsResponseBuilder &); ListThreadsResponseBuilder &operator=(const ListThreadsResponseBuilder &);
flatbuffers::Offset<ListThreadsResponse> Finish() { flatbuffers::Offset<ListThreadsResponse> Finish() {
auto o = flatbuffers::Offset<ListThreadsResponse>(fbb_.EndTable(start_, 0)); auto o = flatbuffers::Offset<ListThreadsResponse>(fbb_.EndTable(start_, 1));
return o; return o;
} }
}; };
inline flatbuffers::Offset<ListThreadsResponse> CreateListThreadsResponse(flatbuffers::FlatBufferBuilder &_fbb) { inline flatbuffers::Offset<ListThreadsResponse> CreateListThreadsResponse(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Thread>>>
thread = 0) {
ListThreadsResponseBuilder builder_(_fbb); ListThreadsResponseBuilder builder_(_fbb);
builder_.add_thread(thread);
return builder_.Finish(); return builder_.Finish();
} }

View File

@ -46,6 +46,8 @@ XThread::XThread(KernelState* kernel_state, uint32_t stack_size,
pcr_address_(0), pcr_address_(0),
thread_state_address_(0), thread_state_address_(0),
thread_state_(0), thread_state_(0),
priority_(0),
affinity_(0),
irql_(0) { irql_(0) {
creation_params_.stack_size = stack_size; creation_params_.stack_size = stack_size;
creation_params_.xapi_thread_startup = xapi_thread_startup; creation_params_.xapi_thread_startup = xapi_thread_startup;
@ -613,6 +615,7 @@ void XThread::RundownAPCs() {
int32_t XThread::QueryPriority() { return GetThreadPriority(thread_handle_); } int32_t XThread::QueryPriority() { return GetThreadPriority(thread_handle_); }
void XThread::SetPriority(int32_t increment) { void XThread::SetPriority(int32_t increment) {
priority_ = increment;
int target_priority = 0; int target_priority = 0;
if (increment > 0x22) { if (increment > 0x22) {
target_priority = THREAD_PRIORITY_HIGHEST; target_priority = THREAD_PRIORITY_HIGHEST;
@ -647,11 +650,17 @@ void XThread::SetAffinity(uint32_t affinity) {
XELOGW("Too few processors - scheduling will be wonky"); XELOGW("Too few processors - scheduling will be wonky");
} }
SetActiveCpu(GetFakeCpuNumber(affinity)); SetActiveCpu(GetFakeCpuNumber(affinity));
affinity_ = affinity;
if (!FLAGS_ignore_thread_affinities) { if (!FLAGS_ignore_thread_affinities) {
SetThreadAffinityMask(reinterpret_cast<HANDLE>(thread_handle_), affinity); SetThreadAffinityMask(reinterpret_cast<HANDLE>(thread_handle_), affinity);
} }
} }
uint32_t XThread::active_cpu() const {
uint8_t* pcr = memory()->TranslateVirtual(pcr_address_);
return xe::load_and_swap<uint8_t>(pcr + 0x10C);
}
void XThread::SetActiveCpu(uint32_t cpu_index) { void XThread::SetActiveCpu(uint32_t cpu_index) {
uint8_t* pcr = memory()->TranslateVirtual(pcr_address_); uint8_t* pcr = memory()->TranslateVirtual(pcr_address_);
xe::store_and_swap<uint8_t>(pcr + 0x10C, cpu_index); xe::store_and_swap<uint8_t>(pcr + 0x10C, cpu_index);

View File

@ -85,6 +85,7 @@ class XThread : public XObject {
static uint32_t GetCurrentThreadHandle(); static uint32_t GetCurrentThreadHandle();
static uint32_t GetCurrentThreadId(const uint8_t* pcr); static uint32_t GetCurrentThreadId(const uint8_t* pcr);
uint32_t tls_ptr() const { return tls_address_; }
uint32_t pcr_ptr() const { return pcr_address_; } uint32_t pcr_ptr() const { return pcr_address_; }
uint32_t thread_state_ptr() const { return thread_state_address_; } uint32_t thread_state_ptr() const { return thread_state_address_; }
@ -112,9 +113,12 @@ class XThread : public XObject {
void EnqueueApc(uint32_t normal_routine, uint32_t normal_context, void EnqueueApc(uint32_t normal_routine, uint32_t normal_context,
uint32_t arg1, uint32_t arg2); uint32_t arg1, uint32_t arg2);
int32_t priority() const { return priority_; }
int32_t QueryPriority(); int32_t QueryPriority();
void SetPriority(int32_t increment); void SetPriority(int32_t increment);
uint32_t affinity() const { return affinity_; }
void SetAffinity(uint32_t affinity); void SetAffinity(uint32_t affinity);
uint32_t active_cpu() const;
void SetActiveCpu(uint32_t cpu_index); void SetActiveCpu(uint32_t cpu_index);
X_STATUS Resume(uint32_t* out_suspend_count = nullptr); X_STATUS Resume(uint32_t* out_suspend_count = nullptr);
@ -151,6 +155,9 @@ class XThread : public XObject {
std::string name_; std::string name_;
int32_t priority_;
uint32_t affinity_;
std::atomic<uint32_t> irql_; std::atomic<uint32_t> irql_;
xe::mutex apc_lock_; xe::mutex apc_lock_;
NativeList* apc_list_; NativeList* apc_list_;