Compensate for static TLS when accessing dynamic TLS.

This commit is contained in:
Dr. Chat 2015-12-27 18:35:44 -06:00 committed by Ben Vanik
parent bca5fb5382
commit 5cb591b993
2 changed files with 22 additions and 17 deletions

View File

@ -90,7 +90,7 @@ XThread::~XThread() {
delete thread_state_; delete thread_state_;
} }
kernel_state()->memory()->SystemHeapFree(scratch_address_); kernel_state()->memory()->SystemHeapFree(scratch_address_);
kernel_state()->memory()->SystemHeapFree(tls_address_); kernel_state()->memory()->SystemHeapFree(tls_static_address_);
kernel_state()->memory()->SystemHeapFree(pcr_address_); kernel_state()->memory()->SystemHeapFree(pcr_address_);
FreeStack(); FreeStack();
@ -187,7 +187,7 @@ void XThread::InitializeGuestObject() {
xe::store_and_swap<uint16_t>(p + 0x056, 1); xe::store_and_swap<uint16_t>(p + 0x056, 1);
xe::store_and_swap<uint32_t>(p + 0x05C, stack_base_); xe::store_and_swap<uint32_t>(p + 0x05C, stack_base_);
xe::store_and_swap<uint32_t>(p + 0x060, stack_limit_); xe::store_and_swap<uint32_t>(p + 0x060, stack_limit_);
xe::store_and_swap<uint32_t>(p + 0x068, tls_address_); xe::store_and_swap<uint32_t>(p + 0x068, tls_static_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, guest_object() + 0x074); xe::store_and_swap<uint32_t>(p + 0x074, guest_object() + 0x074);
xe::store_and_swap<uint32_t>(p + 0x078, guest_object() + 0x074); xe::store_and_swap<uint32_t>(p + 0x078, guest_object() + 0x074);
@ -291,23 +291,23 @@ X_STATUS XThread::Create() {
} }
// Allocate both the slots and the extended data. // Allocate both the slots and the extended data.
// HACK: we're currently not using the extra memory allocated for TLS slots // Some TLS is compiled with the binary (declspec(thread)) vars. The game
// and instead relying on native TLS slots, so don't allocate anything for // will directly access those through 0(r13).
// the slots.
uint32_t tls_slot_size = tls_slots * 4; uint32_t tls_slot_size = tls_slots * 4;
tls_total_size_ = tls_slot_size + tls_extended_size; tls_total_size_ = tls_slot_size + tls_extended_size;
tls_address_ = memory()->SystemHeapAlloc(tls_total_size_); tls_static_address_ = memory()->SystemHeapAlloc(tls_total_size_);
if (!tls_address_) { tls_dynamic_address_ = tls_static_address_ + tls_extended_size;
if (!tls_static_address_) {
XELOGW("Unable to allocate thread local storage block"); XELOGW("Unable to allocate thread local storage block");
return X_STATUS_NO_MEMORY; return X_STATUS_NO_MEMORY;
} }
// Zero all of TLS. // Zero all of TLS.
memory()->Fill(tls_address_, tls_total_size_, 0); memory()->Fill(tls_static_address_, tls_total_size_, 0);
if (tls_extended_size) { if (tls_extended_size) {
// If game has extended data, copy in the default values. // If game has extended data, copy in the default values.
assert_not_zero(tls_header->raw_data_address); assert_not_zero(tls_header->raw_data_address);
memory()->Copy(tls_address_, tls_header->raw_data_address, memory()->Copy(tls_static_address_, tls_header->raw_data_address,
tls_header->raw_data_size); tls_header->raw_data_size);
} }
@ -344,7 +344,7 @@ X_STATUS XThread::Create() {
X_KPCR* pcr = memory()->TranslateVirtual<X_KPCR*>(pcr_address_); X_KPCR* pcr = memory()->TranslateVirtual<X_KPCR*>(pcr_address_);
pcr->tls_ptr = tls_address_; pcr->tls_ptr = tls_static_address_;
pcr->pcr_ptr = pcr_address_; pcr->pcr_ptr = pcr_address_;
pcr->current_thread = guest_object(); pcr->current_thread = guest_object();
@ -712,7 +712,7 @@ bool XThread::GetTLSValue(uint32_t slot, uint32_t* value_out) {
return false; return false;
} }
auto mem = memory()->TranslateVirtual(tls_address_ + slot * 4); auto mem = memory()->TranslateVirtual(tls_dynamic_address_ + slot * 4);
*value_out = xe::load_and_swap<uint32_t>(mem); *value_out = xe::load_and_swap<uint32_t>(mem);
return true; return true;
} }
@ -722,7 +722,7 @@ bool XThread::SetTLSValue(uint32_t slot, uint32_t value) {
return false; return false;
} }
auto mem = memory()->TranslateVirtual(tls_address_ + slot * 4); auto mem = memory()->TranslateVirtual(tls_dynamic_address_ + slot * 4);
xe::store_and_swap<uint32_t>(mem, value); xe::store_and_swap<uint32_t>(mem, value);
return true; return true;
} }
@ -1039,7 +1039,8 @@ struct ThreadSavedState {
uint64_t system_time_; uint64_t system_time_;
uint32_t apc_head; uint32_t apc_head;
uint32_t tls_address; uint32_t tls_static_address;
uint32_t tls_dynamic_address;
uint32_t tls_total_size; uint32_t tls_total_size;
uint32_t pcr_address; uint32_t pcr_address;
uint32_t stack_base; // High address uint32_t stack_base; // High address
@ -1095,7 +1096,8 @@ bool XThread::Save(ByteStream* stream) {
state.is_main_thread = main_thread_; state.is_main_thread = main_thread_;
state.is_running = running_; state.is_running = running_;
state.apc_head = apc_list_.head(); state.apc_head = apc_list_.head();
state.tls_address = tls_address_; state.tls_static_address = tls_static_address_;
state.tls_dynamic_address = tls_dynamic_address_;
state.tls_total_size = tls_total_size_; state.tls_total_size = tls_total_size_;
state.pcr_address = pcr_address_; state.pcr_address = pcr_address_;
state.stack_base = stack_base_; state.stack_base = stack_base_;
@ -1159,8 +1161,10 @@ object_ref<XThread> XThread::Restore(KernelState* kernel_state,
stream->Read(&state, sizeof(ThreadSavedState)); stream->Read(&state, sizeof(ThreadSavedState));
thread->thread_id_ = state.thread_id; thread->thread_id_ = state.thread_id;
thread->main_thread_ = state.is_main_thread; thread->main_thread_ = state.is_main_thread;
thread->running_ = state.is_running;
thread->apc_list_.set_head(state.apc_head); thread->apc_list_.set_head(state.apc_head);
thread->tls_address_ = state.tls_address; thread->tls_static_address_ = state.tls_static_address;
thread->tls_dynamic_address_ = state.tls_dynamic_address;
thread->tls_total_size_ = state.tls_total_size; thread->tls_total_size_ = state.tls_total_size;
thread->pcr_address_ = state.pcr_address; thread->pcr_address_ = state.pcr_address;
thread->stack_base_ = state.stack_base; thread->stack_base_ = state.stack_base;

View File

@ -131,7 +131,7 @@ class XThread : public XObject {
static void SetLastError(uint32_t error_code); static void SetLastError(uint32_t error_code);
const CreationParams* creation_params() const { return &creation_params_; } const CreationParams* creation_params() const { return &creation_params_; }
uint32_t tls_ptr() const { return tls_address_; } uint32_t tls_ptr() const { return tls_static_address_; }
uint32_t pcr_ptr() const { return pcr_address_; } uint32_t pcr_ptr() const { return pcr_address_; }
// True if the thread is created by the guest app. // True if the thread is created by the guest app.
bool is_guest_thread() const { return guest_thread_; } bool is_guest_thread() const { return guest_thread_; }
@ -222,7 +222,8 @@ class XThread : public XObject {
std::unique_ptr<xe::threading::Thread> thread_; std::unique_ptr<xe::threading::Thread> thread_;
uint32_t scratch_address_ = 0; uint32_t scratch_address_ = 0;
uint32_t scratch_size_ = 0; uint32_t scratch_size_ = 0;
uint32_t tls_address_ = 0; uint32_t tls_static_address_ = 0;
uint32_t tls_dynamic_address_ = 0;
uint32_t tls_total_size_ = 0; uint32_t tls_total_size_ = 0;
uint32_t pcr_address_ = 0; uint32_t pcr_address_ = 0;
uint32_t stack_alloc_base_ = 0; // Stack alloc base uint32_t stack_alloc_base_ = 0; // Stack alloc base