How VMAware Handles 32-bit and 64-bit System Compatibility
VMAware achieves 32-bit and 64-bit system compatibility through compile-time preprocessor macros that detect the target architecture and conditionally include CPU-specific detection techniques.
VMAware is a cross-platform virtual machine detection library supporting Windows, Linux, and macOS across x86 and ARM processors. Handling 32-bit and 64-bit system compatibility requires strict management of instruction-set differences to prevent illegal operations on incompatible hardware. According to the kernelwernel/vmaware source code, the library solves this entirely at compile-time using architecture detection macros defined in src/vmaware.hpp.
Compile-Time Architecture Detection
The foundation of VMAware's compatibility layer rests on standard compiler-provided macros. In src/vmaware.hpp (lines 281-291), the header checks for __x86_64__, _M_X64, __i386__, and _M_IX86 to determine the target architecture.
If a 64-bit x86 macro is present, the library defines x86_64 as 1; otherwise, it sets x86_32 to 1 for 32-bit targets. This logic creates boolean flags that the entire codebase uses to toggle architecture-specific code paths.
At line 293, a generic x86 flag is defined as the logical OR of x86_32 and x86_64, allowing any x86-compatible CPU to be tested with a single macro while preserving the granularity needed for bit-specific operations.
Conditional Compilation of Detection Techniques
Every detection technique that depends on register size or instruction set availability is wrapped in preprocessor guards. This prevents the compiler from emitting illegal instructions for the target architecture.
32-bit Specific Techniques
Certain x86 instructions are unavailable or behave differently in 64-bit long mode. VMAware wraps these in #if (x86_32) blocks:
- SLDT (Store Local Descriptor Table): Only compiled for 32-bit targets at lines 6655-6661. This instruction does not exist in x86-64 long mode and would cause a crash if executed.
- SMSW (Store Machine Status Word): Restricted to 32-bit builds at lines 6728-6732 for similar compatibility reasons.
64-bit and Shared Techniques
RDTSC-based hypervisor checks are compiled for both architectures, though the 64-bit implementation may use rdtsc-ordered instructions with adjusted register handling. The conditional compilation ensures that a binary built for 64-bit systems never contains 32-bit-only instructions that would trigger an illegal instruction exception at runtime.
ARM Architecture Support
Parallel to the x86 logic, VMAware supports ARM processors through the same macro-based approach. Lines 299-311 define ARM32, ARM64, and ARM using compiler macros like __aarch64__, _M_ARM64, and __arm__. This allows the library to handle ARM-only techniques—such as Apple VZ detection mentioned in src/cli.cpp—while keeping x86 logic untouched and preventing cross-platform instruction-set pollution.
Platform Range Integration
The library defines platform-wide flag ranges (e.g., WINDOWS_START, WINDOWS_END) that automatically respect architecture flags (lines 559-566). When a technique is enabled for Windows, the range includes both x86_32 and x86_64 entries within the Windows block, ensuring consistent API behavior across architectures while maintaining internal separation of concerns.
Runtime Capability Guards
Although most compatibility checks occur at compile-time, VMAware includes runtime safety mechanisms for edge cases. The cpu::is_leaf_supported function (lines 985-1005) queries processor capabilities at runtime, ensuring that a 32-bit binary running on a 64-bit CPU—or other similar scenarios—behaves correctly even when compile-time detection might suggest otherwise.
// Example conditional compilation from vmaware.hpp
// SLDT technique only builds for 32-bit x86
#if (x86_32)
bool technique_sldt() {
unsigned int value = 0;
__asm__ volatile("sldt %0" : "=r"(value));
return (value & 0xFF) == 0xFF; // hypervisor signature check
}
#endif
The x86_32 macro ensures this block is completely omitted from 64-bit builds, preventing runtime crashes on CPUs that do not support the sldt instruction in long mode.
Summary
- VMAware uses preprocessor macros (
__x86_64__,__i386__, etc.) at lines 281-291 ofsrc/vmaware.hppto detect the target architecture during compilation. - Architecture flags (
x86_32,x86_64,ARM32,ARM64) enable conditional compilation of platform-specific code paths. - 32-bit only instructions like SLDT and SMSW are wrapped in
#if (x86_32)guards at lines 6655-6661 and 6728-6732 to prevent illegal instruction exceptions on 64-bit systems. - Platform ranges (lines 559-566) integrate architecture flags into broader platform detection logic for Windows, Linux, and macOS.
- Runtime guards such as
cpu::is_leaf_supported(lines 985-1005) provide additional safety for capability detection at execution time.
Frequently Asked Questions
How does VMAware detect whether to compile for 32-bit or 64-bit systems?
VMAware checks standard compiler-provided macros in src/vmaware.hpp (lines 281-291). It looks for __x86_64__ or _M_X64 to set x86_64=1 for 64-bit targets, or __i386__ and _M_IX86 to set x86_32=1 for 32-bit targets. These definitions occur before any platform-specific code is compiled, ensuring the correct instruction set is used throughout the build.
Why are certain techniques like SLDT restricted to 32-bit builds only?
The SLDT and SMSW x86 instructions are not valid in 64-bit long mode. If compiled into a 64-bit binary, these instructions would generate an illegal instruction exception (SIGILL) when executed. By wrapping these techniques in #if (x86_32) blocks at lines 6655-6661 and 6728-6732, VMAware ensures they only exist in 32-bit executables where the hardware supports them.
Does VMAware support processors other than x86?
Yes. Lines 299-311 of src/vmaware.hpp define parallel architecture flags for ARM processors (ARM32, ARM64, ARM) using macros like __aarch64__ and __arm__. This allows the same conditional compilation strategy to work for ARM-specific detection techniques while maintaining separation from x86 logic, enabling the library to run natively on Apple Silicon and other ARM platforms.
What happens if a 32-bit VMAware binary runs on a 64-bit CPU?
The 32-bit binary contains only instructions compatible with its target architecture due to compile-time filtering. However, if runtime capability detection is needed, the cpu::is_leaf_supported function (lines 985-1005) queries actual processor features at execution time. This ensures correct behavior even when the compile-time target differs from the physical CPU capabilities, preventing false positives in virtual machine detection.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →