use core::fmt;
use reverie_syscalls::Sysno;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum VdsoSymbol {
#[cfg(target_arch = "x86_64")]
ClockGettime,
#[cfg(target_arch = "x86_64")]
VdsoClockGettime,
#[cfg(target_arch = "x86_64")]
Gettimeofday,
#[cfg(target_arch = "x86_64")]
VdsoGettimeofday,
#[cfg(target_arch = "x86_64")]
Getcpu,
#[cfg(target_arch = "x86_64")]
VdsoGetcpu,
#[cfg(target_arch = "x86_64")]
Time,
#[cfg(target_arch = "x86_64")]
VdsoTime,
#[cfg(target_arch = "x86_64")]
ClockGetres,
#[cfg(target_arch = "x86_64")]
VdsoClockGetres,
#[cfg(target_arch = "x86_64")]
VdsoSgxEnterEnclave,
#[cfg(target_arch = "x86_64")]
Getrandom,
#[cfg(target_arch = "x86_64")]
VdsoGetrandom,
#[cfg(target_arch = "x86_64")]
VdsoFutexRobustList64TryUnlock,
#[cfg(target_arch = "x86_64")]
VdsoFutexRobustList32TryUnlock,
#[cfg(target_arch = "aarch64")]
KernelRtSigreturn,
#[cfg(target_arch = "aarch64")]
KernelGettimeofday,
#[cfg(target_arch = "aarch64")]
KernelClockGettime,
#[cfg(target_arch = "aarch64")]
KernelClockGetres,
#[cfg(target_arch = "aarch64")]
KernelGetrandom,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum VdsoInput {
HostClock,
HostClockResolution,
HostCpu,
HostEntropy,
GuestMemory,
Enclave,
}
impl VdsoInput {
pub const fn is_deterministic(self) -> bool {
match self {
Self::GuestMemory => true,
Self::HostClock
| Self::HostClockResolution
| Self::HostCpu
| Self::HostEntropy
| Self::Enclave => false,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum VdsoHandling {
Syscall(Sysno),
Enosys,
Native,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct VdsoClass {
pub input: VdsoInput,
pub handling: VdsoHandling,
}
impl VdsoSymbol {
pub const ALL: &'static [Self] = &[
#[cfg(target_arch = "x86_64")]
Self::ClockGettime,
#[cfg(target_arch = "x86_64")]
Self::VdsoClockGettime,
#[cfg(target_arch = "x86_64")]
Self::Gettimeofday,
#[cfg(target_arch = "x86_64")]
Self::VdsoGettimeofday,
#[cfg(target_arch = "x86_64")]
Self::Getcpu,
#[cfg(target_arch = "x86_64")]
Self::VdsoGetcpu,
#[cfg(target_arch = "x86_64")]
Self::Time,
#[cfg(target_arch = "x86_64")]
Self::VdsoTime,
#[cfg(target_arch = "x86_64")]
Self::ClockGetres,
#[cfg(target_arch = "x86_64")]
Self::VdsoClockGetres,
#[cfg(target_arch = "x86_64")]
Self::VdsoSgxEnterEnclave,
#[cfg(target_arch = "x86_64")]
Self::Getrandom,
#[cfg(target_arch = "x86_64")]
Self::VdsoGetrandom,
#[cfg(target_arch = "x86_64")]
Self::VdsoFutexRobustList64TryUnlock,
#[cfg(target_arch = "x86_64")]
Self::VdsoFutexRobustList32TryUnlock,
#[cfg(target_arch = "aarch64")]
Self::KernelRtSigreturn,
#[cfg(target_arch = "aarch64")]
Self::KernelGettimeofday,
#[cfg(target_arch = "aarch64")]
Self::KernelClockGettime,
#[cfg(target_arch = "aarch64")]
Self::KernelClockGetres,
#[cfg(target_arch = "aarch64")]
Self::KernelGetrandom,
];
pub const fn name(self) -> &'static str {
match self {
#[cfg(target_arch = "x86_64")]
Self::ClockGettime => "clock_gettime",
#[cfg(target_arch = "x86_64")]
Self::VdsoClockGettime => "__vdso_clock_gettime",
#[cfg(target_arch = "x86_64")]
Self::Gettimeofday => "gettimeofday",
#[cfg(target_arch = "x86_64")]
Self::VdsoGettimeofday => "__vdso_gettimeofday",
#[cfg(target_arch = "x86_64")]
Self::Getcpu => "getcpu",
#[cfg(target_arch = "x86_64")]
Self::VdsoGetcpu => "__vdso_getcpu",
#[cfg(target_arch = "x86_64")]
Self::Time => "time",
#[cfg(target_arch = "x86_64")]
Self::VdsoTime => "__vdso_time",
#[cfg(target_arch = "x86_64")]
Self::ClockGetres => "clock_getres",
#[cfg(target_arch = "x86_64")]
Self::VdsoClockGetres => "__vdso_clock_getres",
#[cfg(target_arch = "x86_64")]
Self::VdsoSgxEnterEnclave => "__vdso_sgx_enter_enclave",
#[cfg(target_arch = "x86_64")]
Self::Getrandom => "getrandom",
#[cfg(target_arch = "x86_64")]
Self::VdsoGetrandom => "__vdso_getrandom",
#[cfg(target_arch = "x86_64")]
Self::VdsoFutexRobustList64TryUnlock => "__vdso_futex_robust_list64_try_unlock",
#[cfg(target_arch = "x86_64")]
Self::VdsoFutexRobustList32TryUnlock => "__vdso_futex_robust_list32_try_unlock",
#[cfg(target_arch = "aarch64")]
Self::KernelRtSigreturn => "__kernel_rt_sigreturn",
#[cfg(target_arch = "aarch64")]
Self::KernelGettimeofday => "__kernel_gettimeofday",
#[cfg(target_arch = "aarch64")]
Self::KernelClockGettime => "__kernel_clock_gettime",
#[cfg(target_arch = "aarch64")]
Self::KernelClockGetres => "__kernel_clock_getres",
#[cfg(target_arch = "aarch64")]
Self::KernelGetrandom => "__kernel_getrandom",
}
}
pub fn from_name(name: &str) -> Option<Self> {
Self::ALL
.iter()
.copied()
.find(|symbol| symbol.name() == name)
}
pub const fn class(self) -> VdsoClass {
use VdsoHandling::*;
use VdsoInput::*;
let (input, handling) = match self {
#[cfg(target_arch = "x86_64")]
Self::ClockGettime | Self::VdsoClockGettime => {
(HostClock, Syscall(Sysno::clock_gettime))
}
#[cfg(target_arch = "x86_64")]
Self::Gettimeofday | Self::VdsoGettimeofday => {
(HostClock, Syscall(Sysno::gettimeofday))
}
#[cfg(target_arch = "x86_64")]
Self::Getcpu | Self::VdsoGetcpu => (HostCpu, Syscall(Sysno::getcpu)),
#[cfg(target_arch = "x86_64")]
Self::Time | Self::VdsoTime => (HostClock, Syscall(Sysno::time)),
#[cfg(target_arch = "x86_64")]
Self::ClockGetres | Self::VdsoClockGetres => {
(HostClockResolution, Syscall(Sysno::clock_getres))
}
#[cfg(target_arch = "x86_64")]
Self::VdsoSgxEnterEnclave => (Enclave, Enosys),
#[cfg(target_arch = "x86_64")]
Self::Getrandom | Self::VdsoGetrandom => (HostEntropy, Syscall(Sysno::getrandom)),
#[cfg(target_arch = "x86_64")]
Self::VdsoFutexRobustList64TryUnlock | Self::VdsoFutexRobustList32TryUnlock => {
(GuestMemory, Native)
}
#[cfg(target_arch = "aarch64")]
Self::KernelRtSigreturn => (GuestMemory, Syscall(Sysno::rt_sigreturn)),
#[cfg(target_arch = "aarch64")]
Self::KernelGettimeofday => (HostClock, Syscall(Sysno::gettimeofday)),
#[cfg(target_arch = "aarch64")]
Self::KernelClockGettime => (HostClock, Syscall(Sysno::clock_gettime)),
#[cfg(target_arch = "aarch64")]
Self::KernelClockGetres => (HostClockResolution, Syscall(Sysno::clock_getres)),
#[cfg(target_arch = "aarch64")]
Self::KernelGetrandom => (HostEntropy, Syscall(Sysno::getrandom)),
};
VdsoClass { input, handling }
}
}
impl fmt::Display for VdsoSymbol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}
#[cfg(target_arch = "x86_64")]
pub fn c_header() -> String {
let mut entries = String::new();
for symbol in VdsoSymbol::ALL {
let (handling, syscall) = match symbol.class().handling {
VdsoHandling::Syscall(sysno) => ("REVERIE_VDSO_SYSCALL", i64::from(sysno.id())),
VdsoHandling::Enosys => ("REVERIE_VDSO_ENOSYS", -1),
VdsoHandling::Native => ("REVERIE_VDSO_NATIVE", -1),
};
entries.push_str(&format!(
" {{\"{}\", {handling}, {syscall}}},\n",
symbol.name()
));
}
format!(
r#"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
/*
* @generated by `reverie::vdso::c_header()` from `VdsoSymbol::class` in
* reverie/src/vdso.rs, which documents each entry. Do not edit: the test that
* compares this file with the generator rewrites it when run with
* REVERIE_BLESS=1.
*/
#ifndef REVERIE_VDSO_SYMBOLS_H
#define REVERIE_VDSO_SYMBOLS_H
#include <string.h>
/* What a backend that patches the x86_64 vDSO does with an entry point. */
enum reverie_vdso_handling {{
/* Replace it with a stub that issues `syscall`. */
REVERIE_VDSO_SYSCALL,
/* Replace it with a stub that returns -ENOSYS. */
REVERIE_VDSO_ENOSYS,
/* Leave the kernel's code in place. */
REVERIE_VDSO_NATIVE,
}};
struct reverie_vdso_symbol {{
const char* name;
enum reverie_vdso_handling handling;
/* The syscall for REVERIE_VDSO_SYSCALL, otherwise -1. */
long syscall;
}};
/* Every function the x86_64 vDSO exports, by its kernel name. */
static const struct reverie_vdso_symbol reverie_vdso_symbols[] = {{
{entries}}};
/*
* The entry for the vDSO function named `name`, or NULL if it is unknown, in
* which case it is replaced with -ENOSYS like REVERIE_VDSO_ENOSYS.
*/
static inline const struct reverie_vdso_symbol* reverie_vdso_symbol_lookup(
const char* name) {{
for (size_t index = 0;
index < sizeof(reverie_vdso_symbols) / sizeof(reverie_vdso_symbols[0]);
index++) {{
if (strcmp(reverie_vdso_symbols[index].name, name) == 0)
return &reverie_vdso_symbols[index];
}}
return NULL;
}}
#endif /* REVERIE_VDSO_SYMBOLS_H */
"#
)
}