tls: Add caching for Windows exception handler.

This commit is contained in:
squidbus 2024-09-17 10:33:46 -07:00
parent c70014a992
commit 69472d79a4

View File

@ -28,26 +28,46 @@ namespace Core {
// Windows // Windows
static DWORD slot = 0; static DWORD slot = 0;
static std::set<void*> known_fs_accesses;
static std::mutex known_fs_accesses_lock;
static ZydisDecoder tls_instr_decoder; static ZydisDecoder tls_instr_decoder;
static std::once_flag slot_alloc_flag; static std::once_flag slot_alloc_flag;
static bool TlsAccessViolationHandler(void* code_address, void* fault_address, bool is_write) { static bool TlsAccessViolationHandler(void* code_address, void* fault_address, bool is_write) {
ZydisDecodedInstruction instruction; bool known;
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; {
const auto status = std::unique_lock lock{known_fs_accesses_lock};
ZydisDecoderDecodeFull(&tls_instr_decoder, code_address, 0x20, &instruction, operands); known = known_fs_accesses.contains(code_address);
if (!ZYAN_SUCCESS(status)) {
return false;
} }
for (u32 i = 0; i < instruction.operand_count_visible; i++) { if (!known) {
if (operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY && ZydisDecodedInstruction instruction;
operands[i].mem.segment == ZYDIS_REGISTER_FS) { ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
// Set the FS register and try again. const auto status =
const auto* tcb_base = GetTcbBase(); ZydisDecoderDecodeFull(&tls_instr_decoder, code_address, 0x20, &instruction, operands);
asm volatile("wrfsbase %0" ::"r"(tcb_base) : "memory"); if (!ZYAN_SUCCESS(status)) {
return true; return false;
} }
for (u32 i = 0; i < instruction.operand_count_visible; i++) {
if (operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY &&
operands[i].mem.segment == ZYDIS_REGISTER_FS) {
known = true;
break;
}
}
if (known) {
std::unique_lock lock{known_fs_accesses_lock};
known_fs_accesses.insert(code_address);
}
}
if (known) {
// Set the FS register and try again.
const auto* tcb_base = GetTcbBase();
asm volatile("wrfsbase %0" ::"r"(tcb_base) : "memory");
return true;
} }
return false; return false;