mirror of
https://github.com/decompals/wibo.git
synced 2025-12-12 14:46:09 +00:00
x86_64 Linux: Add fallback for CPUs without RDFSBASE/WRFSBASE
This commit is contained in:
46
src/macros.S
46
src/macros.S
@@ -64,6 +64,52 @@ m1632:
|
|||||||
endbr64
|
endbr64
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
.macro READ_FSBASE out_reg teb_reg
|
||||||
|
push rax
|
||||||
|
movzx rax, byte ptr [\teb_reg+TEB_HAS_FSGSBASE]
|
||||||
|
test rax, rax
|
||||||
|
jz 1f
|
||||||
|
rdfsbase \out_reg
|
||||||
|
jmp 2f
|
||||||
|
1:
|
||||||
|
push rdi
|
||||||
|
push rsi
|
||||||
|
push rcx
|
||||||
|
sub rsp, 8
|
||||||
|
mov rsi, rsp # addr
|
||||||
|
mov rdi, 0x1003 # ARCH_GET_FS
|
||||||
|
mov rax, 158 # SYS_arch_prctl
|
||||||
|
syscall
|
||||||
|
pop \out_reg
|
||||||
|
pop rcx
|
||||||
|
pop rsi
|
||||||
|
pop rdi
|
||||||
|
2:
|
||||||
|
pop rax
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro WRITE_FSBASE in_reg teb_reg
|
||||||
|
push rax
|
||||||
|
movzx rax, byte ptr [\teb_reg+TEB_HAS_FSGSBASE]
|
||||||
|
test rax, rax
|
||||||
|
jz 1f
|
||||||
|
wrfsbase \in_reg
|
||||||
|
jmp 2f
|
||||||
|
1:
|
||||||
|
push rdi
|
||||||
|
push rsi
|
||||||
|
push rcx
|
||||||
|
mov rsi, \in_reg # addr
|
||||||
|
mov rdi, 0x1002 # ARCH_SET_FS
|
||||||
|
mov rax, 158 # SYS_arch_prctl
|
||||||
|
syscall
|
||||||
|
pop rcx
|
||||||
|
pop rsi
|
||||||
|
pop rdi
|
||||||
|
2:
|
||||||
|
pop rax
|
||||||
|
.endm
|
||||||
|
|
||||||
#endif // __x86_64__
|
#endif // __x86_64__
|
||||||
|
|
||||||
.macro GET_TEB_HOST reg
|
.macro GET_TEB_HOST reg
|
||||||
|
|||||||
11
src/macros.h
11
src/macros.h
@@ -12,11 +12,12 @@
|
|||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
#define TEB_CS_SEL 0xf9c // CodeSelector
|
#define TEB_CS_SEL 0xf9c // CodeSelector
|
||||||
#define TEB_DS_SEL 0xf9e // DataSelector
|
#define TEB_DS_SEL 0xf9e // DataSelector
|
||||||
#define TEB_SP 0xfa0 // CurrentStackPointer
|
#define TEB_SP 0xfa0 // CurrentStackPointer
|
||||||
#define TEB_FSBASE 0xfa8 // HostFsBase
|
#define TEB_FSBASE 0xfa8 // HostFsBase
|
||||||
#define TEB_GSBASE 0xfb0 // HostGsBase
|
#define TEB_GSBASE 0xfb0 // HostGsBase
|
||||||
|
#define TEB_HAS_FSGSBASE 0xfb8 // HasFsGsBase
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#define CS_32 0x23 // 32-bit code segment (Linux)
|
#define CS_32 0x23 // 32-bit code segment (Linux)
|
||||||
|
|||||||
@@ -11,14 +11,16 @@ namespace {
|
|||||||
std::mutex g_tebSetupMutex;
|
std::mutex g_tebSetupMutex;
|
||||||
int g_entryNumber = -1;
|
int g_entryNumber = -1;
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
constexpr uint16_t createSelector(int entryNumber) {
|
constexpr uint16_t createSelector(int entryNumber) {
|
||||||
return static_cast<uint16_t>((entryNumber << 3) | USER_PRIVILEGE);
|
return static_cast<uint16_t>((entryNumber << 3) | USER_PRIVILEGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
|
|
||||||
|
#include <cpuid.h>
|
||||||
|
|
||||||
// Implemented in setup.S
|
// Implemented in setup.S
|
||||||
extern "C" int tebThreadSetup64(int entryNumber, TEB *teb);
|
extern "C" int tebThreadSetup64(int entryNumber, TEB *teb);
|
||||||
|
|
||||||
@@ -37,6 +39,15 @@ bool tebThreadSetup(TEB *teb) {
|
|||||||
|
|
||||||
teb->CurrentFsSelector = createSelector(ret);
|
teb->CurrentFsSelector = createSelector(ret);
|
||||||
teb->CurrentGsSelector = 0;
|
teb->CurrentGsSelector = 0;
|
||||||
|
|
||||||
|
// Check for FSBASE/GSBASE instruction support
|
||||||
|
unsigned int regs[4];
|
||||||
|
int cpuidMax = __get_cpuid_max(0, nullptr);
|
||||||
|
if (cpuidMax >= 0x7 && __get_cpuid_count(0x7, 0, ®s[0], ®s[1], ®s[2], ®s[3])) {
|
||||||
|
teb->HasFsGsBase = !!(regs[1] & 1);
|
||||||
|
}
|
||||||
|
DEBUG_LOG("setup_linux: FSBASE/GSBASE instruction support: %s\n", teb->HasFsGsBase ? "yes" : "no");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -549,6 +549,7 @@ typedef struct _TEB {
|
|||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
void *HostFsBase;
|
void *HostFsBase;
|
||||||
void *HostGsBase;
|
void *HostGsBase;
|
||||||
|
bool HasFsGsBase;
|
||||||
#endif
|
#endif
|
||||||
} TEB;
|
} TEB;
|
||||||
typedef GUEST_PTR PTEB;
|
typedef GUEST_PTR PTEB;
|
||||||
@@ -575,6 +576,9 @@ static_assert(offsetof(TEB, HostFsBase) == TEB_FSBASE);
|
|||||||
#ifdef TEB_GSBASE
|
#ifdef TEB_GSBASE
|
||||||
static_assert(offsetof(TEB, HostGsBase) == TEB_GSBASE);
|
static_assert(offsetof(TEB, HostGsBase) == TEB_GSBASE);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TEB_HAS_FSGSBASE
|
||||||
|
static_assert(offsetof(TEB, HasFsGsBase) == TEB_HAS_FSGSBASE);
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct _MEMORY_BASIC_INFORMATION {
|
typedef struct _MEMORY_BASIC_INFORMATION {
|
||||||
GUEST_PTR BaseAddress;
|
GUEST_PTR BaseAddress;
|
||||||
|
|||||||
@@ -721,7 +721,7 @@ def emit_cc_thunk64(f: FuncInfo | TypedefInfo, lines: List[str]):
|
|||||||
|
|
||||||
if sys.platform != "darwin":
|
if sys.platform != "darwin":
|
||||||
# Save FS base
|
# Save FS base
|
||||||
lines.append("\trdfsbase r9")
|
lines.append("\tREAD_FSBASE r9, rbx")
|
||||||
lines.append("\tmov qword ptr [rbx+TEB_FSBASE], r9")
|
lines.append("\tmov qword ptr [rbx+TEB_FSBASE], r9")
|
||||||
|
|
||||||
# Save RSP and load guest stack
|
# Save RSP and load guest stack
|
||||||
@@ -782,7 +782,7 @@ def emit_cc_thunk64(f: FuncInfo | TypedefInfo, lines: List[str]):
|
|||||||
if sys.platform != "darwin":
|
if sys.platform != "darwin":
|
||||||
# Restore FS base
|
# Restore FS base
|
||||||
lines.append("\tmov r9, qword ptr [rbx+TEB_FSBASE]")
|
lines.append("\tmov r9, qword ptr [rbx+TEB_FSBASE]")
|
||||||
lines.append("\twrfsbase r9")
|
lines.append("\tWRITE_FSBASE r9, rbx")
|
||||||
|
|
||||||
# Restore host stack
|
# Restore host stack
|
||||||
lines.append("\tmov rsp, qword ptr [rbx+TEB_SP]")
|
lines.append("\tmov rsp, qword ptr [rbx+TEB_SP]")
|
||||||
|
|||||||
Reference in New Issue
Block a user