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}