asm_util/
lib.rs

1// https://github.com/rust-lang/rfcs/blob/master/text/2585-unsafe-block-in-unsafe-fn.md
2#![deny(unsafe_op_in_unsafe_fn)]
3
4// Force cargo to link against crates that aren't (yet) referenced from Rust
5// code (but are referenced from this crate's C code).
6// https://github.com/rust-lang/cargo/issues/9391
7extern crate logger;
8
9/// cbindgen:ignore
10pub mod c_internal {
11    #![allow(non_upper_case_globals)]
12    #![allow(non_camel_case_types)]
13    #![allow(non_snake_case)]
14    // https://github.com/rust-lang/rust/issues/66220
15    #![allow(improper_ctypes)]
16    include!(concat!(env!("OUT_DIR"), "/c_internal.rs"));
17}
18
19pub mod cpuid;
20pub mod tsc;
21
22/// Check whether the memory starting at `ip` starts with the instruction `insn`.
23///
24/// Particularly useful in situations where we can be confident that `ip` points
25/// to a valid instruction, but can't otherwise guarantee how many bytes are
26/// dereferenceable. e.g. for the (perhaps unlikely) situation where `ip` points
27/// to a single-byte instruction, the next byte is not safely dereferenceable,
28/// and `insn` is a multi-byte instruction; i.e. where naively converting `ip`
29/// to a slice of the same size as `insn` would be unsound.
30///
31/// SAFETY: `ip` must be a dereferenceable pointer, pointing to the beginning
32/// of a valid x86_64 instruction, and `insn` must be a valid x86_64 instruction.
33unsafe fn ip_matches(ip: *const u8, insn: &[u8]) -> bool {
34    // SAFETY:
35    // * Caller has guaranteed that `ip` points to some valid instruction.
36    // * Caller has guaranteed that `insn` is a valid instruction.
37    // * No instruction can be a prefix of another, so `insn` can't be a prefix
38    //   of some *other* instruction at `ip`.
39    // * [`std::Iterator::all`] is short-circuiting.
40    //
41    // e.g. consider the case where `ip` points to a 1-byte `ret`
42    // instruction, and the next byte of memory isn't accessible. That
43    // single byte *cannot* match the first byte of `insn`, so we'll never
44    // dereference `ip.offset(1)`, which would be unsound.
45    insn.iter()
46        .enumerate()
47        .all(|(offset, byte)| unsafe { *ip.add(offset) == *byte })
48}