cross-vendor TLS fix: 0x66 prefixes are forced into 64bit call on AMD

This commit is contained in:
nmzik
2026-09-03 23:01:51 +02:00
parent f27a136430
commit 5b8e3b51b0
2 changed files with 16 additions and 12 deletions
+7 -6
View File
@@ -69,21 +69,22 @@ struct Call9 {
template <class Handler>
void SetFunc(Handler func) {
auto func_addr = reinterpret_cast<int64_t>(reinterpret_cast<void*>(func));
auto rip_addr = reinterpret_cast<int64_t>(&code[5]);
auto rip_addr = reinterpret_cast<int64_t>(&code[6]);
auto offset64 = func_addr - rip_addr;
auto offset32 = static_cast<uint32_t>(static_cast<uint64_t>(offset64) & 0xffffffffu);
*reinterpret_cast<uint32_t*>(&code[1]) = offset32;
*reinterpret_cast<uint32_t*>(&code[2]) = offset32;
}
void SetOutputReg(uint8_t reg) { code[7] = 0xc0u | (reg & 7u); }
void SetOutputReg(uint8_t reg) { code[8] = 0xc0u | (reg & 7u); }
static uint64_t GetSize() { return 9; }
// call func
// rex.w; call func
// mov rax,rax
// nop
uint8_t code[9] = {0xE8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0xC0, 0x90};
// REX.W is required because AMD processors honor a retained 0x66 operand-size
// prefix on a near call and would otherwise execute callw.
uint8_t code[9] = {0x48, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0xC0};
};
struct TlsRegStub {