Make XThread use its guest KTHREAD object in the pcr in r13

Shuffle around some code in XThread
This commit is contained in:
Dr. Chat 2015-07-21 22:07:30 -05:00
parent a4849ca83e
commit b646915b77
2 changed files with 73 additions and 65 deletions

View File

@ -106,18 +106,17 @@ uint32_t XThread::GetCurrentThreadHandle() {
return thread->handle(); return thread->handle();
} }
uint32_t XThread::GetCurrentThreadId(const uint8_t* pcr) { uint32_t XThread::GetCurrentThreadId() {
return xe::load_and_swap<uint32_t>(pcr + 0x2D8 + 0x14C); XThread* thread = XThread::GetCurrentThread();
return thread->guest_object<X_KTHREAD>()->thread_id;
} }
uint32_t XThread::last_error() { uint32_t XThread::last_error() {
uint8_t* p = memory()->TranslateVirtual(thread_state_address_); return guest_object<X_KTHREAD>()->last_error;
return xe::load_and_swap<uint32_t>(p + 0x160);
} }
void XThread::set_last_error(uint32_t error_code) { void XThread::set_last_error(uint32_t error_code) {
uint8_t* p = memory()->TranslateVirtual(thread_state_address_); guest_object<X_KTHREAD>()->last_error = error_code;
xe::store_and_swap<uint32_t>(p + 0x160, error_code);
} }
void XThread::set_name(const std::string& name) { void XThread::set_name(const std::string& name) {
@ -129,9 +128,15 @@ void XThread::set_name(const std::string& name) {
} }
} }
uint8_t next_cpu = 0;
uint8_t GetFakeCpuNumber(uint8_t proc_mask) { uint8_t GetFakeCpuNumber(uint8_t proc_mask) {
if (!proc_mask) { if (!proc_mask) {
return 0; // is this reasonable? next_cpu++;
if (next_cpu > 6) {
next_cpu = 0;
}
return next_cpu; // is this reasonable?
} }
assert_false(proc_mask & 0xC0); assert_false(proc_mask & 0xC0);
@ -143,15 +148,12 @@ uint8_t GetFakeCpuNumber(uint8_t proc_mask) {
X_STATUS XThread::Create() { X_STATUS XThread::Create() {
// Thread kernel object // Thread kernel object
// This call will also setup the native pointer for us. // This call will also setup the native pointer for us.
auto guest_object = CreateNative<X_KTHREAD>(sizeof(X_KTHREAD)); auto guest_thread = CreateNative<X_KTHREAD>();
if (!guest_object) { if (!guest_thread) {
XELOGW("Unable to allocate thread object"); XELOGW("Unable to allocate thread object");
return X_STATUS_NO_MEMORY; return X_STATUS_NO_MEMORY;
} }
guest_object->header.type = 6;
StashNative(&guest_object->header, this);
auto module = kernel_state()->GetExecutableModule(); auto module = kernel_state()->GetExecutableModule();
// Allocate thread scratch. // Allocate thread scratch.
@ -210,8 +212,7 @@ X_STATUS XThread::Create() {
// 0x160: last error // 0x160: last error
// So, at offset 0x100 we have a 4b pointer to offset 200, then have the // So, at offset 0x100 we have a 4b pointer to offset 200, then have the
// structure. // structure.
pcr_address_ = memory()->SystemHeapAlloc(0x2D8 + 0xAB0); pcr_address_ = memory()->SystemHeapAlloc(0x2D8);
thread_state_address_ = pcr_address_ + 0x2D8;
if (!pcr_address_) { if (!pcr_address_) {
XELOGW("Unable to allocate thread state block"); XELOGW("Unable to allocate thread state block");
return X_STATUS_NO_MEMORY; return X_STATUS_NO_MEMORY;
@ -232,27 +233,11 @@ X_STATUS XThread::Create() {
uint8_t proc_mask = uint8_t proc_mask =
static_cast<uint8_t>(creation_params_.creation_flags >> 24); static_cast<uint8_t>(creation_params_.creation_flags >> 24);
// Processor Control Region X_KPCR* pcr = memory()->TranslateVirtual<X_KPCR*>(pcr_address_);
struct XPCR {
xe::be<uint32_t> tls_ptr; // 0x0
char unk_04[0x2C]; // 0x4
xe::be<uint32_t> pcr_ptr; // 0x30
char unk_34[0x3C]; // 0x34
xe::be<uint32_t> stack_base_ptr; // 0x70 Stack base address (high addr)
xe::be<uint32_t> stack_end_ptr; // 0x74 Stack end (low addr)
char unk_78[0x88]; // 0x78
xe::be<uint32_t> teb_ptr; // 0x100
char unk_104[0x8]; // 0x104
xe::be<uint8_t> current_cpu; // 0x10C
char unk_10D[0x43]; // 0x10D
xe::be<uint32_t> dpc_active; // 0x150
};
XPCR* pcr = memory()->TranslateVirtual<XPCR*>(pcr_address_);
pcr->tls_ptr = tls_address_; pcr->tls_ptr = tls_address_;
pcr->pcr_ptr = pcr_address_; pcr->pcr_ptr = pcr_address_;
pcr->teb_ptr = thread_state_address_; pcr->current_thread = guest_object();
pcr->stack_base_ptr = pcr->stack_base_ptr =
thread_state_->stack_address() + thread_state_->stack_size(); thread_state_->stack_address() + thread_state_->stack_size();
@ -262,19 +247,16 @@ X_STATUS XThread::Create() {
pcr->dpc_active = 0; // DPC active bool? pcr->dpc_active = 0; // DPC active bool?
// Setup the thread state block (last error/etc). // Setup the thread state block (last error/etc).
// TODO: This is actually a KTHREAD object. Use the one from CreateNative uint8_t* p = memory()->TranslateVirtual(guest_object());
// instead. guest_thread->header.type = 6;
uint8_t* p = memory()->TranslateVirtual(thread_state_address_);
xe::store_and_swap<uint32_t>(p + 0x000, 6);
xe::store_and_swap<uint32_t>(p + 0x008, thread_state_address_ + 0x008);
xe::store_and_swap<uint32_t>(p + 0x00C, thread_state_address_ + 0x008);
xe::store_and_swap<uint32_t>(p + 0x010, thread_state_address_ + 0x010);
xe::store_and_swap<uint32_t>(p + 0x014, thread_state_address_ + 0x010);
xe::store_and_swap<uint32_t>(p + 0x040, thread_state_address_ + 0x018 + 8); xe::store_and_swap<uint32_t>(p + 0x010, guest_object() + 0x010);
xe::store_and_swap<uint32_t>(p + 0x044, thread_state_address_ + 0x018 + 8); xe::store_and_swap<uint32_t>(p + 0x014, guest_object() + 0x010);
xe::store_and_swap<uint32_t>(p + 0x048, thread_state_address_);
xe::store_and_swap<uint32_t>(p + 0x04C, thread_state_address_ + 0x018); xe::store_and_swap<uint32_t>(p + 0x040, guest_object() + 0x018 + 8);
xe::store_and_swap<uint32_t>(p + 0x044, guest_object() + 0x018 + 8);
xe::store_and_swap<uint32_t>(p + 0x048, guest_object());
xe::store_and_swap<uint32_t>(p + 0x04C, guest_object() + 0x018);
xe::store_and_swap<uint16_t>(p + 0x054, 0x102); xe::store_and_swap<uint16_t>(p + 0x054, 0x102);
xe::store_and_swap<uint16_t>(p + 0x056, 1); xe::store_and_swap<uint16_t>(p + 0x056, 1);
@ -283,27 +265,27 @@ X_STATUS XThread::Create() {
xe::store_and_swap<uint32_t>(p + 0x060, thread_state_->stack_address()); xe::store_and_swap<uint32_t>(p + 0x060, thread_state_->stack_address());
xe::store_and_swap<uint32_t>(p + 0x068, tls_address_); xe::store_and_swap<uint32_t>(p + 0x068, tls_address_);
xe::store_and_swap<uint8_t>(p + 0x06C, 0); xe::store_and_swap<uint8_t>(p + 0x06C, 0);
xe::store_and_swap<uint32_t>(p + 0x074, thread_state_address_ + 0x074); xe::store_and_swap<uint32_t>(p + 0x074, guest_object() + 0x074);
xe::store_and_swap<uint32_t>(p + 0x078, thread_state_address_ + 0x074); xe::store_and_swap<uint32_t>(p + 0x078, guest_object() + 0x074);
xe::store_and_swap<uint32_t>(p + 0x07C, thread_state_address_ + 0x07C); xe::store_and_swap<uint32_t>(p + 0x07C, guest_object() + 0x07C);
xe::store_and_swap<uint32_t>(p + 0x080, thread_state_address_ + 0x07C); xe::store_and_swap<uint32_t>(p + 0x080, guest_object() + 0x07C);
xe::store_and_swap<uint32_t>(p + 0x084, xe::store_and_swap<uint32_t>(p + 0x084,
kernel_state_->process_info_block_address()); kernel_state_->process_info_block_address());
xe::store_and_swap<uint8_t>(p + 0x08B, 1); xe::store_and_swap<uint8_t>(p + 0x08B, 1);
// D4 = APC // 0xD4 = APC
// FC = semaphore (ptr, 0, 2) // 0xFC = semaphore (ptr, 0, 2)
// A88 = APC // 0xA88 = APC
// 18 = timer // 0x18 = timer
xe::store_and_swap<uint32_t>(p + 0x09C, 0xFDFFD7FF); xe::store_and_swap<uint32_t>(p + 0x09C, 0xFDFFD7FF);
xe::store_and_swap<uint32_t>( xe::store_and_swap<uint32_t>(
p + 0x0D0, thread_state_->stack_address() + thread_state_->stack_size()); p + 0x0D0, thread_state_->stack_address() + thread_state_->stack_size());
xe::store_and_swap<uint64_t>(p + 0x130, Clock::QueryGuestSystemTime()); xe::store_and_swap<uint64_t>(p + 0x130, Clock::QueryGuestSystemTime());
xe::store_and_swap<uint32_t>(p + 0x144, thread_state_address_ + 0x144); xe::store_and_swap<uint32_t>(p + 0x144, guest_object() + 0x144);
xe::store_and_swap<uint32_t>(p + 0x148, thread_state_address_ + 0x144); xe::store_and_swap<uint32_t>(p + 0x148, guest_object() + 0x144);
xe::store_and_swap<uint32_t>(p + 0x14C, thread_id_); xe::store_and_swap<uint32_t>(p + 0x14C, thread_id_);
xe::store_and_swap<uint32_t>(p + 0x150, creation_params_.start_address); xe::store_and_swap<uint32_t>(p + 0x150, creation_params_.start_address);
xe::store_and_swap<uint32_t>(p + 0x154, thread_state_address_ + 0x154); xe::store_and_swap<uint32_t>(p + 0x154, guest_object() + 0x154);
xe::store_and_swap<uint32_t>(p + 0x158, thread_state_address_ + 0x154); xe::store_and_swap<uint32_t>(p + 0x158, guest_object() + 0x154);
xe::store_and_swap<uint32_t>(p + 0x160, 0); // last error xe::store_and_swap<uint32_t>(p + 0x160, 0); // last error
xe::store_and_swap<uint32_t>(p + 0x16C, creation_params_.creation_flags); xe::store_and_swap<uint32_t>(p + 0x16C, creation_params_.creation_flags);
xe::store_and_swap<uint32_t>(p + 0x17C, 1); xe::store_and_swap<uint32_t>(p + 0x17C, 1);
@ -331,6 +313,7 @@ X_STATUS XThread::Create() {
// Release the self-reference to the thread. // Release the self-reference to the thread.
Release(); Release();
}); });
if (!thread_) { if (!thread_) {
// TODO(benvanik): translate error? // TODO(benvanik): translate error?
XELOGE("CreateThread failed"); XELOGE("CreateThread failed");
@ -520,7 +503,8 @@ void XThread::DeliverAPCs() {
LockApc(); LockApc();
} }
XELOGD("Completed delivery of APC to %.8X", uint32_t(apc->normal_routine)); XELOGD("Completed delivery of APC to %.8X (%.8X, %.8X, %.8X)",
normal_routine, normal_context, arg1, arg2);
// If special, free it. // If special, free it.
if (needs_freeing) { if (needs_freeing) {
@ -614,6 +598,8 @@ void XThread::SetActiveCpu(uint32_t cpu_index) {
} }
X_STATUS XThread::Resume(uint32_t* out_suspend_count) { X_STATUS XThread::Resume(uint32_t* out_suspend_count) {
--guest_object<X_KTHREAD>()->suspend_count;
if (thread_->Resume(out_suspend_count)) { if (thread_->Resume(out_suspend_count)) {
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
} else { } else {
@ -622,6 +608,8 @@ X_STATUS XThread::Resume(uint32_t* out_suspend_count) {
} }
X_STATUS XThread::Suspend(uint32_t* out_suspend_count) { X_STATUS XThread::Suspend(uint32_t* out_suspend_count) {
++guest_object<X_KTHREAD>()->suspend_count;
if (thread_->Suspend(out_suspend_count)) { if (thread_->Suspend(out_suspend_count)) {
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
} else { } else {

View File

@ -65,13 +65,35 @@ struct XAPC {
} }
}; };
// http://www.nirsoft.net/kernel_struct/vista/KTHREAD.html // Processor Control Region
struct X_KPCR {
xe::be<uint32_t> tls_ptr; // 0x0
char unk_04[0x2C]; // 0x4
xe::be<uint32_t> pcr_ptr; // 0x30
char unk_34[0x3C]; // 0x34
xe::be<uint32_t> stack_base_ptr; // 0x70 Stack base address (high addr)
xe::be<uint32_t> stack_end_ptr; // 0x74 Stack end (low addr)
char unk_78[0x88]; // 0x78
xe::be<uint32_t> current_thread; // 0x100
char unk_104[0x8]; // 0x104
xe::be<uint8_t> current_cpu; // 0x10C
char unk_10D[0x43]; // 0x10D
xe::be<uint32_t> dpc_active; // 0x150
};
struct X_KTHREAD { struct X_KTHREAD {
X_DISPATCH_HEADER header; // 0x0 X_DISPATCH_HEADER header; // 0x0
char unk_04[0xAA0]; // 0x4 char unk_10[0xAC]; // 0x10
uint8_t suspend_count; // 0xBC
char unk_BD[0x8F]; // 0xBD
xe::be<uint32_t> thread_id; // 0x14C
char unk_150[0x10]; // 0x150
xe::be<uint32_t> last_error; // 0x160
char unk_164[0x94C]; // 0x164
// This struct is actually quite long... so uh, not filling this out! // This struct is actually quite long... so uh, not filling this out!
}; };
static_assert_size(X_KTHREAD, 0xAB0);
class XThread : public XObject { class XThread : public XObject {
public: public:
@ -83,11 +105,10 @@ class XThread : public XObject {
static bool IsInThread(XThread* other); static bool IsInThread(XThread* other);
static XThread* GetCurrentThread(); static XThread* GetCurrentThread();
static uint32_t GetCurrentThreadHandle(); static uint32_t GetCurrentThreadHandle();
static uint32_t GetCurrentThreadId(const uint8_t* pcr); static uint32_t GetCurrentThreadId();
uint32_t tls_ptr() const { return tls_address_; } 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_; }
bool guest_thread() const { return guest_thread_; } bool guest_thread() const { return guest_thread_; }
bool running() const { return running_; } bool running() const { return running_; }
@ -149,9 +170,8 @@ class XThread : public XObject {
uint32_t scratch_size_ = 0; uint32_t scratch_size_ = 0;
uint32_t tls_address_ = 0; uint32_t tls_address_ = 0;
uint32_t pcr_address_ = 0; uint32_t pcr_address_ = 0;
uint32_t thread_state_address_ = 0;
cpu::ThreadState* thread_state_ = nullptr; cpu::ThreadState* thread_state_ = nullptr;
bool guest_thread_ = false; // Launched into guest code. bool guest_thread_ = false; // Launched into guest code?
bool running_ = false; bool running_ = false;
std::string name_; std::string name_;
@ -159,7 +179,7 @@ class XThread : public XObject {
int32_t priority_ = 0; int32_t priority_ = 0;
uint32_t affinity_ = 0; uint32_t affinity_ = 0;
std::atomic<uint32_t> irql_; std::atomic<uint32_t> irql_ = 0;
xe::mutex apc_lock_; xe::mutex apc_lock_;
NativeList* apc_list_ = nullptr; NativeList* apc_list_ = nullptr;
}; };