diff --git a/.github/builder/Dockerfile-internal b/.github/builder/Dockerfile-internal-6 similarity index 89% rename from .github/builder/Dockerfile-internal rename to .github/builder/Dockerfile-internal-6 index db606595..ec4f0d0d 100644 --- a/.github/builder/Dockerfile-internal +++ b/.github/builder/Dockerfile-internal-6 @@ -12,7 +12,7 @@ COPY .github/builder/rsrc/lld-5.0.2.src.tar.xz /install/lld-5.0.2.src.tar.xz COPY .github/builder/rsrc/cfe-5.0.2.src.tar.xz /install/cfe-5.0.2.src.tar.xz COPY .github/builder/rsrc/llvm-5.0.2.src.tar.xz /install/llvm-5.0.2.src.tar.xz COPY .github/builder/rsrc/rpms /install/rpms -COPY .github/builder/rsrc/simics /simics +COPY .github/builder/rsrc/simics-6 /simics COPY .github/builder/rsrc/ispm /simics/ispm RUN yum -y install /install/rpms/*.rpm && yum clean all @@ -58,7 +58,7 @@ RUN ispm settings install-dir /simics && \ RUN RUSTFLAGS="-C linker=clang -C link-arg=-fuse-ld=$(which ld.lld)" && \ export RUSTFLAGS && \ cargo install cargo-simics-build && \ - SIMICS_PACKAGE_VERSION="$(ispm packages --list | grep 1000 | awk '{print $3}' | cut -d '.' -f1).$(grep -E '^version = ' < Cargo.toml | sed -n '$p' | grep -oE '\"[^\"]+\"' | tr -d '\"' | cut -d'.' -f2-)" && \ + SIMICS_PACKAGE_VERSION="$(ispm packages --list-installed | grep 1000 | awk '{print $3}' | cut -d '.' -f1).$(grep -E '^version = ' < Cargo.toml | sed -n '$p' | grep -oE '\"[^\"]+\"' | tr -d '\"' | cut -d'.' -f2-)" && \ export SIMICS_PACKAGE_VERSION && \ cargo simics-build -r && \ mkdir -p /packages-internal && \ diff --git a/.github/builder/Dockerfile-internal-7 b/.github/builder/Dockerfile-internal-7 new file mode 100644 index 00000000..f4f716fe --- /dev/null +++ b/.github/builder/Dockerfile-internal-7 @@ -0,0 +1,65 @@ +# hadolint global ignore=DL3033,SC3044 +FROM fedora:20 + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +ENV PATH="${PATH}:/root/.cargo/bin/" + +COPY .github/builder/rsrc/rust-nightly-x86_64-unknown-linux-gnu.tar.xz /install/rust-nightly-x86_64-unknown-linux-gnu.tar.xz +COPY .github/builder/rsrc/make-4.4.1.tar.gz /install/make-4.4.1.tar.gz +COPY .github/builder/rsrc/cmake-3.29.3-linux-x86_64.tar.gz /install/cmake-3.29.3-linux-x86_64.tar.gz +COPY .github/builder/rsrc/lld-5.0.2.src.tar.xz /install/lld-5.0.2.src.tar.xz +COPY .github/builder/rsrc/cfe-5.0.2.src.tar.xz /install/cfe-5.0.2.src.tar.xz +COPY .github/builder/rsrc/llvm-5.0.2.src.tar.xz /install/llvm-5.0.2.src.tar.xz +COPY .github/builder/rsrc/rpms /install/rpms +COPY .github/builder/rsrc/simics-7 /simics +COPY .github/builder/rsrc/ispm /simics/ispm + +RUN yum -y install /install/rpms/*.rpm && yum clean all + +RUN tar -C /install -xvf /install/rust-nightly-x86_64-unknown-linux-gnu.tar.xz && \ + /install/rust-nightly-x86_64-unknown-linux-gnu/install.sh && \ + mkdir -p /make && \ + tar -C /make --strip-components=1 -xf /install/make-4.4.1.tar.gz && \ + pushd /make && \ + ./configure && \ + make && \ + make install && \ + make clean && \ + popd && \ + tar -C /usr/local/ --strip-components=1 -xf /install/cmake-3.29.3-linux-x86_64.tar.gz && \ + mkdir -p /llvm/tools/clang && \ + mkdir -p /llvm/tools/lld && \ + tar -C /llvm --strip-components=1 -xf /install/llvm-5.0.2.src.tar.xz && \ + tar -C /llvm/tools/clang --strip-components=1 -xf /install/cfe-5.0.2.src.tar.xz && \ + tar -C /llvm/tools/lld --strip-components=1 -xf /install/lld-5.0.2.src.tar.xz && \ + mkdir -p /llvm/build && \ + pushd /llvm/build && \ + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="MinSizeRel" -DLLVM_TARGETS_TO_BUILD="X86" .. && \ + make -j "$(nproc)" && \ + make install && \ + make clean && \ + rm -rf /llvm/build/ && \ + popd && \ + rm -rf /make /llvm + +WORKDIR / + +ENV PATH="${PATH}:/simics/ispm/" +ENV PATH="${PATH}:/root/.cargo/bin/" + +COPY . /tsffs/ + +WORKDIR /tsffs/ + +RUN ispm settings install-dir /simics && \ + ispm packages --list + +RUN RUSTFLAGS="-C linker=clang -C link-arg=-fuse-ld=$(which ld.lld)" && \ + export RUSTFLAGS && \ + cargo install cargo-simics-build && \ + SIMICS_PACKAGE_VERSION="$(ispm packages --list-installed | grep 1000 | awk '{print $3}' | cut -d '.' -f1).$(grep -E '^version = ' < Cargo.toml | sed -n '$p' | grep -oE '\"[^\"]+\"' | tr -d '\"' | cut -d'.' -f2-)" && \ + export SIMICS_PACKAGE_VERSION && \ + cargo simics-build -r && \ + mkdir -p /packages-internal && \ + cp target/release/*.ispm /packages-internal diff --git a/.github/builder/common.sh b/.github/builder/common.sh index b096683e..ef954800 100755 --- a/.github/builder/common.sh +++ b/.github/builder/common.sh @@ -1,6 +1,7 @@ #!/bin/bash -# NOTE: Do not just copy-paste scripts/build.sh! +# NOTE: The `use-keyboxd` option in ~/.gnupg/common.conf should be disabled for this script's GPG routines to +# work correctly! set -e @@ -233,4 +234,4 @@ download_and_verify_builder_deps() { download_and_verify_cmake download_and_verify_simics download_and_verify_builder_rpms -} \ No newline at end of file +} diff --git a/Cargo.toml b/Cargo.toml index a7c76d15..5f70a094 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ version = "0.2.2" [package.metadata.simics] package-number = 31337 -version = "6.1.4" +version = "6.1.6" [lib] crate-type = ["cdylib", "rlib"] @@ -76,6 +76,33 @@ tracing-subscriber = "0.3.18" tracing = { version = "0.1.40", features = ["log"] } yaxpeax-arm = "0.3.0" chrono = "0.4.38" +vergilius = "0.1.2" +windows-sys = { features = [ + "Win32_Foundation", + "Win32_System_SystemServices", + "Win32_System_Diagnostics_Debug", + "Win32_System_Diagnostics", + "Win32_System_SystemInformation", + "Win32_System_Kernel", +], version = "0.59.0" } +reqwest = { version = "0.12.5", features = [ + "blocking", + # NOTE: rustls is used because native-tls does not build with the + # compatibility builder and we don't need any advanced features + "rustls-tls", +], default-features = false } +pdb = "0.8.0" +intervaltree = "0.2.7" +lending-iterator = "0.1.7" +rustc-demangle = "0.1.24" +cpp_demangle = "0.4.3" +walkdir = "2.5.0" +md5 = "0.7.0" +sha1 = "0.10.6" +sha2 = "0.10.8" +typed-path = "0.9.0" +thiserror = "1.0.63" +lcov2 = "0.1.0" [dev-dependencies] simics-test = "0.1.0" diff --git a/scripts/build-internal.sh b/scripts/build-internal.sh index f864be9b..83ef5a6b 100755 --- a/scripts/build-internal.sh +++ b/scripts/build-internal.sh @@ -11,6 +11,12 @@ set -e +MAJOR_VERSION="${1}" + +if [ -z "${MAJOR_VERSION}" ]; then + MAJOR_VERSION="7" +fi + SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) ROOT_DIR="${SCRIPT_DIR}/../" BUILDER_DIR="${ROOT_DIR}/.github/builder/" @@ -31,32 +37,47 @@ if [ ! -d "${BUILDER_DIR}/rsrc/ispm" ]; then cp -a "${ISPM_DIR}" "${BUILDER_DIR}/rsrc/ispm" fi -if [ ! -d "${BUILDER_DIR}/rsrc/simics" ]; then - echo "Simics packages not found. Installing..." - mkdir -p "${BUILDER_DIR}/rsrc/simics" - ispm packages --install-dir "${BUILDER_DIR}/rsrc/simics" -i \ - 1000-latest \ - 1020-latest \ - 1030-latest \ - 1031-latest \ - 2050-latest \ - 2053-latest \ - 2096-latest \ - 4094-latest \ - 6010-latest \ - 7801-latest \ - 8112-latest \ - 8126-latest \ - 8144-latest \ +install_major_version() { + WANTED_MAJOR_VERSION="${1}" + ispm packages --install-dir "${BUILDER_DIR}/rsrc/simics-${WANTED_MAJOR_VERSION}" -i \ + "1000-${WANTED_MAJOR_VERSION}.latest" \ + "1020-${WANTED_MAJOR_VERSION}.latest" \ + "1030-${WANTED_MAJOR_VERSION}.latest" \ + "1031-${WANTED_MAJOR_VERSION}.latest" \ + "2050-${WANTED_MAJOR_VERSION}.latest" \ + "2053-${WANTED_MAJOR_VERSION}.latest" \ + "2096-${WANTED_MAJOR_VERSION}.latest" \ + "4094-${WANTED_MAJOR_VERSION}.latest" \ + "6010-${WANTED_MAJOR_VERSION}.latest" \ + "7801-${WANTED_MAJOR_VERSION}.latest" \ + "8112-${WANTED_MAJOR_VERSION}.latest" \ + "8126-${WANTED_MAJOR_VERSION}.latest" \ + "8144-${WANTED_MAJOR_VERSION}.latest" \ --non-interactive -fi +} download_and_verify_builder_deps +if [ "${MAJOR_VERSION}" -eq "7" ]; then + DOCKERFILE="${BUILDER_DIR}/Dockerfile-internal-7" + if [ ! -d "${BUILDER_DIR}/rsrc/simics-7" ]; then + echo "Simics 7 packages not found. Installing..." + install_major_version 7 + fi +fi + +if [ "${MAJOR_VERSION}" -eq "6" ]; then + DOCKERFILE="${BUILDER_DIR}/Dockerfile-internal-6" + if [ ! -d "${BUILDER_DIR}/rsrc/simics-6" ]; then + echo "Simics 6 packages not found. Installing..." + install_major_version 6 + fi +fi + unset SIMICS_BASE docker build \ - -t "${IMAGE_NAME}" -f "${BUILDER_DIR}/Dockerfile-internal" "${ROOT_DIR}" + -t "${IMAGE_NAME}" -f "${DOCKERFILE}" "${ROOT_DIR}" docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" bash mkdir -p "${ROOT_DIR}/packages-internal" docker cp "${CONTAINER_NAME}:/packages-internal" "${ROOT_DIR}/" -docker rm -f "${CONTAINER_NAME}" +docker rm -f "${CONTAINER_NAME}" \ No newline at end of file diff --git a/src/haps/mod.rs b/src/haps/mod.rs index a7cce6c4..77370a36 100644 --- a/src/haps/mod.rs +++ b/src/haps/mod.rs @@ -8,6 +8,7 @@ use std::time::SystemTime; use crate::{ arch::ArchitectureOperations, magic::MagicNumber, + os::DebugInfoConfig, state::{SolutionKind, StopReason}, ManualStartInfo, Tsffs, }; @@ -29,6 +30,7 @@ impl Tsffs { let start_processor = self .start_processor() .ok_or_else(|| anyhow!("No start processor"))?; + let start_processor_raw = start_processor.cpu(); let start_info = match magic_number { MagicNumber::StartBufferPtrSizePtr => { @@ -54,6 +56,20 @@ impl Tsffs { .map_err(|_| anyhow!("Failed to set start time"))?; self.coverage_enabled = true; self.save_initial_snapshot()?; + // Collect windows coverage info if enabled + if self.windows && self.symbolic_coverage { + info!(self.as_conf_object(), "Collecting initial coverage info"); + self.windows_os_info.collect( + start_processor_raw, + &self.debuginfo_download_directory, + &mut DebugInfoConfig { + system: self.symbolic_coverage_system, + user_debug_info: &self.debug_info, + coverage: &mut self.coverage, + }, + &self.source_file_cache, + )?; + } self.get_and_write_testcase()?; self.post_timeout_event()?; } @@ -157,6 +173,10 @@ impl Tsffs { self.save_execution_trace()?; } + if self.symbolic_coverage { + self.save_symbolic_coverage()?; + } + debug!(self.as_conf_object(), "Resuming simulation"); run_alone(|| { @@ -204,6 +224,21 @@ impl Tsffs { self.coverage_enabled = true; self.save_initial_snapshot()?; + // Collect windows coverage info if enabled + if self.windows && self.symbolic_coverage { + info!(self.as_conf_object(), "Collecting initial coverage info"); + self.windows_os_info.collect( + processor, + &self.debuginfo_download_directory, + &mut DebugInfoConfig { + system: self.symbolic_coverage_system, + user_debug_info: &self.debug_info, + coverage: &mut self.coverage, + }, + &self.source_file_cache, + )?; + } + self.get_and_write_testcase()?; self.post_timeout_event()?; @@ -236,6 +271,21 @@ impl Tsffs { self.coverage_enabled = true; self.save_initial_snapshot()?; + // Collect windows coverage info if enabled + if self.windows && self.symbolic_coverage { + info!(self.as_conf_object(), "Collecting initial coverage info"); + self.windows_os_info.collect( + processor, + &self.debuginfo_download_directory, + &mut DebugInfoConfig { + system: self.symbolic_coverage_system, + user_debug_info: &self.debug_info, + coverage: &mut self.coverage, + }, + &self.source_file_cache, + )?; + } + self.post_timeout_event()?; } @@ -334,6 +384,10 @@ impl Tsffs { self.save_execution_trace()?; } + if self.symbolic_coverage { + self.save_symbolic_coverage()?; + } + debug!(self.as_conf_object(), "Resuming simulation"); run_alone(|| { @@ -435,6 +489,10 @@ impl Tsffs { self.save_execution_trace()?; } + if self.symbolic_coverage { + self.save_symbolic_coverage()?; + } + debug!(self.as_conf_object(), "Resuming simulation"); run_alone(|| { @@ -571,7 +629,7 @@ impl Tsffs { ) -> Result<()> { trace!( self.as_conf_object(), - "on_magic_instruction({magic_number})" + "Got magic instruction with magic #{magic_number})" ); if object_is_processor(trigger_obj)? { @@ -629,4 +687,15 @@ impl Tsffs { Ok(()) } + + pub fn on_control_register_write( + &mut self, + trigger_obj: *mut ConfObject, + register_nr: i64, + value: i64, + ) -> Result<()> { + self.on_control_register_write_windows_symcov(trigger_obj, register_nr, value)?; + + Ok(()) + } } diff --git a/src/lib.rs b/src/lib.rs index afedc4e2..1b27e0a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,12 +36,14 @@ use anyhow::{anyhow, Result}; use arch::{Architecture, ArchitectureHint, ArchitectureOperations}; use fuzzer::{messages::FuzzerMessage, ShutdownMessage, Testcase}; use indoc::indoc; +use lcov2::Records; use libafl::{inputs::HasBytesVec, prelude::ExitKind}; use libafl_bolts::prelude::OwnedMutSlice; use libafl_targets::AFLppCmpLogMap; use log::LogMessage; use magic::MagicNumber; use num_traits::FromPrimitive as _; +use os::windows::WindowsOsInfo; use serde::{Deserialize, Serialize}; use serde_json::to_writer; use simics::{ @@ -49,9 +51,9 @@ use simics::{ get_processor_number, info, lookup_file, object_clock, run_command, run_python, simics_init, sys::save_flags_t, trace, version_base, warn, write_configuration_to_file, AsConfObject, BreakpointId, ClassCreate, ClassObjectsFinalize, ConfObject, CoreBreakpointMemopHap, - CoreExceptionHap, CoreMagicInstructionHap, CoreSimulationStoppedHap, - CpuInstrumentationSubscribeInterface, Event, EventClassFlag, FromConfObject, HapHandle, - Interface, IntoAttrValueDict, + CoreControlRegisterWriteHap, CoreExceptionHap, CoreMagicInstructionHap, + CoreSimulationStoppedHap, CpuInstrumentationSubscribeInterface, Event, EventClassFlag, + FromConfObject, HapHandle, Interface, }; #[cfg(simics_version_6)] use simics::{ @@ -62,6 +64,7 @@ use simics::{ // which is necessary because this module is compatible with base versions which cross the // deprecation boundary use simics::{restore_snapshot, save_snapshot}; +use source_cov::SourceCache; use state::StopReason; use std::{ alloc::{alloc_zeroed, Layout}, @@ -89,6 +92,8 @@ pub(crate) mod haps; pub(crate) mod interfaces; pub(crate) mod log; pub(crate) mod magic; +pub(crate) mod os; +pub(crate) mod source_cov; pub(crate) mod state; pub(crate) mod tracer; pub(crate) mod traits; @@ -200,8 +205,8 @@ pub(crate) enum ManualStartSize { }, } -#[class(name = "tsffs", skip_objects_finalize, attr_value)] -#[derive(AsConfObject, FromConfObject, Default, IntoAttrValueDict)] +#[class(name = "tsffs", skip_objects_finalize)] +#[derive(AsConfObject, FromConfObject, Default)] /// The main module class for the TSFFS fuzzer, stores state and configuration information pub(crate) struct Tsffs { #[class(attribute(optional, default = false))] @@ -227,7 +232,6 @@ pub(crate) struct Tsffs { /// most processors will generate exceptions during start-up and during normal operation. pub all_exceptions_are_solutions: bool, #[class(attribute(optional))] - #[attr_value(fallible)] /// The set of exceptions which are treated as solutions. For example on x86_64, setting: /// /// @tsffs.exceptions = [14] @@ -235,7 +239,6 @@ pub(crate) struct Tsffs { /// would treat any page fault as a solution. pub exceptions: BTreeSet, #[class(attribute(optional))] - #[attr_value(fallible)] /// The set of breakpoints which are treated as solutions. For example, to set a solution /// breakpoint on the address $addr (note the breakpoint set from the Simics command is /// accessed through the simenv namespace): @@ -268,7 +271,6 @@ pub(crate) struct Tsffs { /// (and they cannot be nested). This only has an effect if `start_on_harness` is set. pub magic_start_index: u64, #[class(attribute(optional, default = vec![0]))] - #[attr_value(fallible)] /// The magic numbers which is passed to the platform-specific magic instruction HAP /// by a compiled-in harness to signal that the fuzzer should stop execution of the current /// iteration. @@ -279,7 +281,6 @@ pub(crate) struct Tsffs { /// This only has an effect if `stop_on_harness` is set. pub magic_stop_indices: Vec, #[class(attribute(optional, default = vec![0]))] - #[attr_value(fallible)] /// The numbers which are passed to the platform-specific magic instruction HAP by a /// compiled-in harness to signal that the fuzzer should stop execution of the /// current iteration and save the testcase as a solution. @@ -297,7 +298,6 @@ pub(crate) struct Tsffs { /// fuzzing loop. pub initial_random_corpus_size: usize, #[class(attribute(optional, default = lookup_file("%simics%")?.join("corpus")))] - #[attr_value(fallible)] /// The directory to load the corpus from and save new corpus items to. This directory /// may be a SIMICS relative path prefixed with "%simics%". It is an error to provide no /// corpus directory when `set_generate_random_corpus(True)` has not been called prior to @@ -306,7 +306,6 @@ pub(crate) struct Tsffs { /// be used by default. pub corpus_directory: PathBuf, #[class(attribute(optional, default = lookup_file("%simics%")?.join("solutions")))] - #[attr_value(fallible)] /// The directory to save solutions to. This directory may be a SIMICS relative path /// prefixed with "%simics%". If not provided, "%simics%/solutions" will be used by /// default. @@ -330,18 +329,15 @@ pub(crate) struct Tsffs { /// be logged. pub coverage_reporting: bool, #[class(attribute(optional))] - #[attr_value(fallible)] /// A set of executable files to tokenize. Tokens will be extracted from these files and /// used to drive token mutations of testcases. pub token_executables: Vec, #[class(attribute(optional))] - #[attr_value(fallible)] /// A set of source files to tokenize. Tokens will be extracted from these files and used /// to drive token mutations of testcases. C source files are expected, and strings and /// tokens will be extracted from strings in the source files. pub token_src_files: Vec, #[class(attribute(optional))] - #[attr_value(fallible)] /// Files in the format of: /// /// x = "hello" @@ -350,18 +346,15 @@ pub(crate) struct Tsffs { /// which will be used to drive token mutations of testcases. pub token_files: Vec, #[class(attribute(optional))] - #[attr_value(fallible)] /// Sets of tokens to use to drive token mutations of testcases. Each token set is a /// bytes which will be randomically inserted into testcases. pub tokens: Vec>, #[class(attribute(optional, default = lookup_file("%simics%")?.join("checkpoint.ckpt")))] - #[attr_value(fallible)] /// The path to the checkpoint saved prior to fuzzing when using snapshots pub checkpoint_path: PathBuf, #[class(attribute(optional, default = true))] pub pre_snapshot_checkpoint: bool, #[class(attribute(optional, default = lookup_file("%simics%")?.join("log.json")))] - #[attr_value(fallible)] /// The path to the log file which will be used to log the fuzzer's output statistics pub log_path: PathBuf, #[class(attribute(optional, default = true))] @@ -394,7 +387,6 @@ pub(crate) struct Tsffs { /// and should only be used for debugging and testing purposes. pub save_all_execution_traces: bool, #[class(attribute(optional, default = lookup_file("%simics%")?.join("execution-traces")))] - #[attr_value(fallible)] /// The directory to save execution traces to, if any are set to be saved. This /// directory may be a SIMICS relative path prefixed with "%simics%". If not /// provided, "%simics%/execution-traces" will be used by default. @@ -409,22 +401,46 @@ pub(crate) struct Tsffs { /// The interval in seconds between heartbeat messages pub heartbeat_interval: u64, - #[attr_value(skip)] + #[class(attribute(optional, default = false))] + /// Whether symbolic coverage should be used during fuzzing + pub symbolic_coverage: bool, + #[class(attribute(optional, default = false))] + /// Whether windows is being run in the simulation + pub windows: bool, + #[class(attribute(optional, default = lookup_file("%simics%")?.join("debuginfo-cache")))] + /// Directory in which to download PDB and EXE files from symbol servers on Windows + pub debuginfo_download_directory: PathBuf, + #[class(attribute(optional))] + /// Mapping of file name (name and extension e.g. fuzzer-app.exe or target.sys) + /// to a tuple of (exe path, debuginfo path) where debuginfo is either a PDB or DWARF + /// file + pub debug_info: HashMap>, + #[class(attribute(optional, default = lookup_file("%simics%")?.join("debuginfo-source")))] + /// Directory in which source files are located. Source files do not need to be arranged in + /// the same directory structure as the compiled source, and are looked up by hash. + pub debuginfo_source_directory: PathBuf, + #[class(attribute(optional, default = false))] + /// Whether symbolic coverage should be collected for system components by downloading + /// executable and debug info files where possible. + pub symbolic_coverage_system: bool, + #[class(attribute(optional, default = lookup_file("%simics%")?.join("symbolic-coverage")))] + /// Directory in which source files are located. Source files do not need to be arranged in + /// the same directory structure as the compiled source, and are looked up by hash. + pub symbolic_coverage_directory: PathBuf, + /// Handle for the core simulation stopped hap stop_hap_handle: HapHandle, - #[attr_value(skip)] /// Handle for the core breakpoint memop hap breakpoint_memop_hap_handle: HapHandle, - #[attr_value(skip)] /// Handle for exception HAP exception_hap_handle: HapHandle, - #[attr_value(skip)] /// The handle for the registered magic HAP, used to /// listen for magic start and stop if `start_on_harness` /// or `stop_on_harness` are set. magic_hap_handle: HapHandle, + /// Handle for the core control register write hap + control_register_write_hap_handle: HapHandle, - #[attr_value(skip)] /// A mapping of architecture hints from CPU index to architecture hint. This architecture /// hint overrides the detected architecture of the CPU core. This is useful when the /// architecture of the CPU core is not detected correctly, or when the architecture of the @@ -432,114 +448,90 @@ pub(crate) struct Tsffs { /// report their architecture as x86_64 can be overridden to x86. pub architecture_hints: HashMap, // Threads and message channels - #[attr_value(skip)] /// Fuzzer thread fuzz_thread: OnceCell>>, - #[attr_value(skip)] /// Message sender to the fuzzer thread. TSFFS sends exit kinds to the fuzzer thread to /// report whether testcases resulted in normal exit, timeout, or solutions. fuzzer_tx: OnceCell>, - #[attr_value(skip)] /// Message receiver from the fuzzer thread. TSFFS receives new testcases and run configuration /// from the fuzzer thread. fuzzer_rx: OnceCell>, - #[attr_value(skip)] /// A message sender to inform the fuzzer thread that it should exit. fuzzer_shutdown: OnceCell>, - #[attr_value(skip)] /// Reciever from the fuzzer thread to receive messages from the fuzzer thread /// including status messages and structured introspection data like new edge findings. fuzzer_messages: OnceCell>, // Fuzzer coverage maps - #[attr_value(skip)] /// The coverage map coverage_map: OnceCell>, - #[attr_value(skip)] /// A pointer to the AFL++ comparison map aflpp_cmp_map_ptr: OnceCell<*mut AFLppCmpLogMap>, - #[attr_value(skip)] /// The owned AFL++ comparison map aflpp_cmp_map: OnceCell<&'static mut AFLppCmpLogMap>, - #[attr_value(skip)] /// The previous location for coverage for calculating the hash of edges. coverage_prev_loc: u64, - #[attr_value(skip)] /// The registered timeout event which is registered and used to detect timeouts in /// virtual time timeout_event: OnceCell, - #[attr_value(skip)] /// The set of edges which have been seen at least once. edges_seen: HashSet, - #[attr_value(skip)] /// A map of the new edges to their AFL indices seen since the last time the fuzzer /// provided an update. This is not cleared every execution. edges_seen_since_last: HashMap, - #[attr_value(skip)] /// The set of PCs comprising the current execution trace. This is cleared every execution. execution_trace: ExecutionTrace, + /// The current line coverage state comprising the total execution. This is not + /// cleared and is persistent across the full campaign until the fuzzer stops. + coverage: Records, - #[attr_value(skip)] /// The name of the fuzz snapshot, if saved snapshot_name: OnceCell, - #[attr_value(skip)] /// The index of the micro checkpoint saved for the fuzzer. Only present if not using /// snapshots. micro_checkpoint_index: OnceCell, - #[attr_value(skip)] /// The reason the current stop occurred stop_reason: Option, - #[attr_value(skip)] /// The buffer and size information, if saved start_info: OnceCell, - #[attr_value(skip)] // #[builder(default = SystemTime::now())] /// The time the fuzzer was started at start_time: OnceCell, - #[attr_value(skip)] // #[builder(default = SystemTime::now())] /// The time the fuzzer was started at last_heartbeat_time: Option, - #[attr_value(skip)] log: OnceCell, - #[attr_value(skip)] /// Whether cmplog is currently enabled coverage_enabled: bool, - #[attr_value(skip)] /// Whether cmplog is currently enabled cmplog_enabled: bool, - #[attr_value(skip)] /// The number of the processor which starts the fuzzing loop (via magic or manual methods) start_processor_number: OnceCell, - #[attr_value(skip)] /// Tracked processors. This always includes the start processor, and may include /// additional processors that are manually added by the user processors: HashMap, - #[attr_value(skip)] /// A testcase to use for repro repro_testcase: Option>, - #[attr_value(skip)] /// Whether a bookmark has been set for repro mode repro_bookmark_set: bool, - #[attr_value(skip)] /// Whether the fuzzer is currently stopped in repro mode stopped_for_repro: bool, - #[attr_value(skip)] /// The number of iterations which have been executed so far iterations: usize, - #[attr_value(skip)] /// Whether snapshots are used. Snapshots are used on Simics 7.0.0 and later. use_snapshots: bool, - #[attr_value(skip)] /// The number of timeouts so far timeouts: usize, - #[attr_value(skip)] /// The number of solutions so far solutions: usize, + + windows_os_info: WindowsOsInfo, + cr3_cache: HashMap, + source_file_cache: SourceCache, } impl ClassObjectsFinalize for Tsffs { @@ -589,6 +581,13 @@ impl ClassObjectsFinalize for Tsffs { .expect("Failed to execute on_magic_instruction callback") } })?; + tsffs.control_register_write_hap_handle = + CoreControlRegisterWriteHap::add_callback(move |trigger_obj, register_nr, value| { + let tsffs: &'static mut Tsffs = instance.into(); + tsffs + .on_control_register_write(trigger_obj, register_nr, value) + .expect("Failed to execute on_control_register_write callback") + })?; tsffs .coverage_map .set(OwnedMutSlice::from(vec![0; Tsffs::COVERAGE_MAP_SIZE])) @@ -725,11 +724,15 @@ impl Tsffs { } // Disable VMP if it is enabled - info!("Disabling VMP"); - + info!(self.as_conf_object(), "Disabling VMP"); if let Err(e) = run_command("disable-vmp") { warn!(self.as_conf_object(), "Failed to disable VMP: {}", e); } + + // Initialize the source cache for source/line lookups + info!(self.as_conf_object(), "Initializing source cache"); + self.source_file_cache = SourceCache::new(&self.debuginfo_source_directory)?; + self.log(LogMessage::startup())?; #[cfg(simics_version_7)] @@ -933,6 +936,28 @@ impl Tsffs { Ok(()) } + pub fn save_symbolic_coverage(&mut self) -> Result<()> { + if self.symbolic_coverage_directory.is_dir() { + create_dir_all(&self.symbolic_coverage_directory)?; + } + + debug!( + self.as_conf_object(), + "Saving symbolic coverage to {}", + self.symbolic_coverage_directory.display() + ); + + self.coverage.to_html(&self.symbolic_coverage_directory)?; + + debug!( + self.as_conf_object(), + "Symbolic coverage saved to {}", + self.symbolic_coverage_directory.display() + ); + + Ok(()) + } + /// Save the current execution trace to a file pub fn save_execution_trace(&mut self) -> Result<()> { let mut hasher = DefaultHasher::new(); @@ -948,11 +973,9 @@ impl Tsffs { .join(format!("{:x}.json", hash)); if !trace_path.exists() { - let trace_file = File::create(trace_path)?; - + let trace_file = File::create(&trace_path)?; to_writer(trace_file, &self.execution_trace)?; } - Ok(()) } } @@ -986,7 +1009,7 @@ fn init() { ) "#}) .map_err(|e| { - error!("{e}"); + error!(tsffs, "{e}"); e }) .expect("Failed to run python"); diff --git a/src/log/mod.rs b/src/log/mod.rs index 991d4cc9..245963ce 100644 --- a/src/log/mod.rs +++ b/src/log/mod.rs @@ -152,6 +152,10 @@ impl Tsffs { if self.save_interesting_execution_traces { self.save_execution_trace()?; } + + if self.symbolic_coverage { + self.save_symbolic_coverage()?; + } } FuzzerMessage::Crash { indices, input } => { info!( @@ -184,6 +188,10 @@ impl Tsffs { if self.save_solution_execution_traces { self.save_execution_trace()?; } + + if self.symbolic_coverage { + self.save_symbolic_coverage()?; + } } FuzzerMessage::Timeout { indices, input } => { info!( @@ -216,6 +224,10 @@ impl Tsffs { if self.save_timeout_execution_traces { self.save_execution_trace()?; } + + if self.symbolic_coverage { + self.save_symbolic_coverage()?; + } } } diff --git a/src/os/mod.rs b/src/os/mod.rs new file mode 100644 index 00000000..577203d5 --- /dev/null +++ b/src/os/mod.rs @@ -0,0 +1,14 @@ +#![allow(unused)] + +use std::{collections::HashMap, path::PathBuf}; + +use lcov2::Records; + +pub mod windows; + +#[derive(Debug)] +pub struct DebugInfoConfig<'a> { + pub system: bool, + pub user_debug_info: &'a HashMap>, + pub coverage: &'a mut Records, +} diff --git a/src/os/windows/debug_info.rs b/src/os/windows/debug_info.rs new file mode 100644 index 00000000..ea619e0b --- /dev/null +++ b/src/os/windows/debug_info.rs @@ -0,0 +1,677 @@ +use anyhow::{anyhow, bail, Result}; +use goblin::pe::PE; +use intervaltree::Element; +use pdb::{FallibleIterator, SymbolData, PDB}; +use reqwest::blocking::get; +use std::{ + collections::{HashMap, HashSet}, + fs::{create_dir_all, File}, + io::{copy, Write}, + path::{Path, PathBuf}, +}; + +use lending_iterator::{windows_mut, LendingIterator}; +use simics::{debug, get_object, info, warn, ConfObject}; +use windows_sys::Win32::System::{ + Diagnostics::Debug::{ + IMAGE_DEBUG_DIRECTORY, IMAGE_DEBUG_TYPE_CODEVIEW, IMAGE_DIRECTORY_ENTRY_DEBUG, + IMAGE_NT_HEADERS64, + }, + SystemServices::{FILE_NOTIFY_FULL_INFORMATION, IMAGE_DOS_HEADER}, +}; + +use crate::{os::DebugInfoConfig, source_cov::SourceCache}; + +use super::{ + pdb::{CvInfoPdb70, Export}, + util::{read_virtual, read_virtual_dtb}, +}; + +#[derive(Debug)] +/// Debug info for an executable (which may be a .exe, .sys, etc) +pub struct DebugInfo<'a> { + /// The path to the executable file on the local system + pub exe_path: PathBuf, + /// The path to the PDB file corresponding to the executable on the local system + pub pdb_path: PathBuf, + /// The contents of the executable file + pub exe_file_contents: Vec, + /// The loaded PDB info + pub pdb: PDB<'a, File>, +} + +impl<'a> DebugInfo<'a> { + /// Instantiate a new debug info for an object + pub fn new

( + processor: *mut ConfObject, + name: &str, + base: u64, + download_directory: P, + not_found_full_name_cache: &mut HashSet, + user_debug_info: &DebugInfoConfig, + ) -> Result> + where + P: AsRef, + { + if let Some(info) = user_debug_info.user_debug_info.get(name) { + debug!( + get_object("tsffs")?, + "Have user-provided debug info for {name}" + ); + let exe_path = info[0].clone(); + let pdb_path = info[1].clone(); + + let exe_file_contents = std::fs::read(&exe_path)?; + + let pdb_file = File::open(&pdb_path)?; + + let pdb = PDB::open(pdb_file)?; + + Ok(Some(Self { + exe_path, + pdb_path, + exe_file_contents, + pdb, + })) + } else if user_debug_info.system { + let dos_header = read_virtual::(processor, base)?; + let nt_header = + read_virtual::(processor, base + dos_header.e_lfanew as u64)?; + let debug_data_directory_offset = nt_header.OptionalHeader.DataDirectory + [IMAGE_DIRECTORY_ENTRY_DEBUG as usize] + .VirtualAddress; + let debug_data_directory_size = + nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG as usize].Size; + let debug_directory = (base + debug_data_directory_offset as u64 + ..base + debug_data_directory_offset as u64 + debug_data_directory_size as u64) + .step_by(std::mem::size_of::()) + .filter_map(|offset| read_virtual::(processor, offset).ok()) + .filter(|dd| dd.Type == IMAGE_DEBUG_TYPE_CODEVIEW) + .take(1) + .next() + .ok_or_else(|| anyhow!("Failed to find debug data directory with codeview type"))?; + + if debug_directory.SizeOfData == 0 || debug_directory.AddressOfRawData == 0 { + bail!("Invalid debug data directory"); + } + + let cv_info_pdb70 = + CvInfoPdb70::new(processor, base + debug_directory.AddressOfRawData as u64)?; + + let exe_guid = format!( + "{:08X}{:05X}", + nt_header.FileHeader.TimeDateStamp, nt_header.OptionalHeader.SizeOfImage + ); + + // Download kernel PDB file + let pdb_url = format!( + "https://msdl.microsoft.com/download/symbols/{}/{}/{}", + cv_info_pdb70.file_name(), + cv_info_pdb70.guid(), + cv_info_pdb70.file_name() + ); + + let exe_url = format!( + "https://msdl.microsoft.com/download/symbols/{}/{}/{}", + name, exe_guid, name + ); + + if !download_directory.as_ref().is_dir() { + create_dir_all(&download_directory)?; + } + + // Download kernel PE file + let exe_path = download_directory + .as_ref() + .join(format!("{}.exe", &exe_guid)); + + if !exe_path.exists() && !not_found_full_name_cache.contains(name) { + info!(get_object("tsffs")?, "Downloading PE file from {}", exe_url); + match get(&exe_url)?.error_for_status() { + Ok(response) => { + let mut file = File::create(&exe_path)?; + copy(&mut response.bytes()?.as_ref(), &mut file)?; + file.flush()?; + } + Err(e) => { + not_found_full_name_cache.insert(name.to_string()); + bail!("Failed to download PE file: {}", e); + } + } + } + + let pdb_path = download_directory + .as_ref() + .join(format!("{}.pdb", cv_info_pdb70.guid())); + + if !pdb_path.exists() && !not_found_full_name_cache.contains(cv_info_pdb70.file_name()) + { + info!( + get_object("tsffs")?, + "Downloading PDB file from {}", pdb_url + ); + match get(&pdb_url)?.error_for_status() { + Ok(response) => { + let mut file = File::create(&pdb_path)?; + copy(&mut response.bytes()?.as_ref(), &mut file)?; + file.flush()?; + } + Err(e) => { + not_found_full_name_cache.insert(cv_info_pdb70.guid().to_string()); + bail!("Failed to download PDB file: {}", e); + } + } + } + + let exe_file_contents = std::fs::read(&exe_path)?; + + let pdb_file = File::open(&pdb_path)?; + + let pdb = PDB::open(pdb_file)?; + + Ok(Some(Self { + exe_path, + pdb_path, + exe_file_contents, + pdb, + })) + } else { + // bail!("No debug info provided for {name}"); + Ok(None) + } + } + + /// Instantiate a new debug info for an object with a specific directory table base + pub fn new_dtb

( + processor: *mut ConfObject, + name: &str, + base: u64, + download_directory: P, + directory_table_base: u64, + not_found_full_name_cache: &mut HashSet, + user_debug_info: DebugInfoConfig, + ) -> Result> + where + P: AsRef, + { + if let Some(info) = user_debug_info.user_debug_info.get(name) { + debug!( + get_object("tsffs")?, + "Have user-provided debug info for {name}" + ); + let exe_path = info[0].clone(); + let pdb_path = info[1].clone(); + + let exe_file_contents = std::fs::read(&exe_path)?; + + let pdb_file = File::open(&pdb_path)?; + + let pdb = PDB::open(pdb_file)?; + + Ok(Some(Self { + exe_path, + pdb_path, + exe_file_contents, + pdb, + })) + } else if user_debug_info.system { + let dos_header = + read_virtual_dtb::(processor, directory_table_base, base)?; + let nt_header = read_virtual_dtb::( + processor, + directory_table_base, + base + dos_header.e_lfanew as u64, + )?; + let debug_data_directory_offset = nt_header.OptionalHeader.DataDirectory + [IMAGE_DIRECTORY_ENTRY_DEBUG as usize] + .VirtualAddress; + let debug_data_directory_size = + nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG as usize].Size; + let debug_directory = (base + debug_data_directory_offset as u64 + ..base + debug_data_directory_offset as u64 + debug_data_directory_size as u64) + .step_by(std::mem::size_of::()) + .filter_map(|offset| { + read_virtual_dtb::( + processor, + directory_table_base, + offset, + ) + .ok() + }) + .filter(|dd| dd.Type == IMAGE_DEBUG_TYPE_CODEVIEW) + .take(1) + .next() + .ok_or_else(|| anyhow!("Failed to find debug data directory with codeview type"))?; + + if debug_directory.SizeOfData == 0 || debug_directory.AddressOfRawData == 0 { + bail!("Invalid debug data directory"); + } + + let cv_info_pdb70 = + CvInfoPdb70::new(processor, base + debug_directory.AddressOfRawData as u64)?; + + let exe_guid = format!( + "{:08X}{:05X}", + nt_header.FileHeader.TimeDateStamp, nt_header.OptionalHeader.SizeOfImage + ); + + // Download kernel PDB file + let pdb_url = format!( + "https://msdl.microsoft.com/download/symbols/{}/{}/{}", + cv_info_pdb70.file_name(), + cv_info_pdb70.guid(), + cv_info_pdb70.file_name() + ); + + let exe_url = format!( + "https://msdl.microsoft.com/download/symbols/{}/{}/{}", + name, exe_guid, name + ); + + if !download_directory.as_ref().is_dir() { + create_dir_all(&download_directory)?; + } + + // Download kernel PE file + let exe_path = download_directory + .as_ref() + .join(format!("{}.exe", &exe_guid)); + + if !exe_path.exists() && !not_found_full_name_cache.contains(name) { + info!(get_object("tsffs")?, "Downloading PE file from {}", exe_url); + match get(&exe_url)?.error_for_status() { + Ok(response) => { + let mut file = File::create(&exe_path)?; + copy(&mut response.bytes()?.as_ref(), &mut file)?; + file.flush()?; + } + Err(e) => { + not_found_full_name_cache.insert(name.to_string()); + bail!("Failed to download PE file: {}", e); + } + } + } + + let exe_file_contents = std::fs::read(&exe_path)?; + + let pdb_path = download_directory + .as_ref() + .join(format!("{}.pdb", cv_info_pdb70.guid())); + + if !pdb_path.exists() && !not_found_full_name_cache.contains(cv_info_pdb70.file_name()) + { + info!( + get_object("tsffs")?, + "Downloading PDB file from {}", pdb_url + ); + match get(&pdb_url)?.error_for_status() { + Ok(response) => { + let mut file = File::create(&pdb_path)?; + copy(&mut response.bytes()?.as_ref(), &mut file)?; + file.flush()?; + } + Err(e) => { + not_found_full_name_cache.insert(cv_info_pdb70.guid().to_string()); + bail!("Failed to download PDB file: {}", e); + } + } + } + + let pdb_file = File::open(&pdb_path)?; + + let pdb = PDB::open(pdb_file)?; + + Ok(Some(Self { + exe_path, + pdb_path, + exe_file_contents, + pdb, + })) + } else { + Ok(None) + } + } + + /// Return the parsed PE file + pub fn exe(&self) -> Result> { + PE::parse(&self.exe_file_contents) + .map_err(move |e| anyhow!("Failed to parse PE file: {}", e)) + } + + /// Get a list of exports from the PE file + pub fn exports(&self) -> Result> { + Ok(self.exe()?.exports.iter().map(Export::from).collect()) + } +} + +#[derive(Debug)] +/// A module (or object) loaded in a specific process +pub struct ProcessModule { + /// The base of the object + pub base: u64, + /// The size of the object + pub size: u64, + /// The full name (typically a path) of the object on disk + pub full_name: String, + /// The base name of the object + pub base_name: String, + /// Loaded debug info for the object + pub debug_info: Option>, +} + +impl ProcessModule { + /// Return lookup intervals for symbols in the process module which can be used to build + /// an interval tree + pub fn intervals( + &mut self, + source_cache: &SourceCache, + ) -> Result>> { + let Some(debug_info) = self.debug_info.as_mut() else { + bail!("No debug info for module {}", self.full_name); + }; + + let string_table = debug_info.pdb.string_table()?; + let address_map = debug_info.pdb.address_map()?; + let symbols = debug_info + .pdb + .debug_information()? + .modules()? + .iterator() + .filter_map(|module| module.ok()) + .filter_map(|module| { + debug_info + .pdb + .module_info(&module) + .ok() + .flatten() + .map(|module_info| (module, module_info)) + }) + .flat_map(|(_module, module_info)| { + let Ok(line_program) = module_info.line_program() else { + return Vec::new(); + }; + + let Ok(symbols) = module_info.symbols() else { + return Vec::new(); + }; + + symbols + .iterator() + .filter_map(|symbol| symbol.ok()) + .filter_map(|symbol| { + symbol.parse().ok().map(|symbol_data| (symbol, symbol_data)) + }) + .filter_map(|(_symbol, symbol_data)| { + let SymbolData::Procedure(procedure_symbol) = symbol_data else { + return None; + }; + let symbol_name = symbol_data.name()?; + let procedure_rva = procedure_symbol.offset.to_rva(&address_map)?; + + let lines = line_program + .lines_for_symbol(procedure_symbol.offset) + .iterator() + .filter_map(|line| line.ok()) + .filter_map(|line_info| { + line_program + .get_file_info(line_info.file_index) + .ok() + .and_then(|line_file_info| { + string_table + .get(line_file_info.name) + .map(|line_file_name| (line_file_info, line_file_name)) + .ok() + }) + .and_then(|(line_file_info, line_file_name)| { + line_info.offset.to_rva(&address_map).map(|line_rva| { + (line_file_info, line_file_name, line_rva, line_info) + }) + }) + .and_then( + |(line_file_info, line_file_name, line_rva, line_info)| { + source_cache + .lookup_pdb( + &line_file_info, + &line_file_name.to_string(), + ) + .ok() + .flatten() + .map(|p| p.to_path_buf()) + .map(|file_path| LineInfo { + rva: line_rva.0 as u64, + size: line_info.length.unwrap_or(1), + file_path, + start_line: line_info.line_start, + end_line: line_info.line_end, + }) + }, + ) + }) + .collect::>(); + let info = SymbolInfo::new( + procedure_rva.0 as u64, + self.base, + procedure_symbol.len as u64, + symbol_name.to_string().to_string(), + self.full_name.clone(), + lines, + ); + + Some(info) + }) + .collect::>() + }) + .collect::>(); + + Ok(symbols + .into_iter() + .map(|s| (self.base + s.rva..self.base + s.rva + s.size, s).into()) + .collect()) + } +} + +#[derive(Debug)] +/// A process +pub struct Process { + /// The unique PID of the process + pub pid: u64, + /// The file name of the process's main object + pub file_name: String, + /// The base address of the process's main object + pub base_address: u64, + /// The list of modules/objects loaded into the process's address space + pub modules: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +/// Information about a line in a source file from a PDB +pub struct LineInfo { + /// The relative virtual address in the executable image + pub rva: u64, + /// The size in bytes of the code this line represents + pub size: u32, + /// The file path of the source file on the *local* filesystem. This path is found by + /// looking up the pdb source path in the source cache on a best-effort approach + pub file_path: PathBuf, + /// The line number in the source file that this line starts at + pub start_line: u32, + /// The line number in the source file that this line ends at + pub end_line: u32, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +/// Information about a symbol in a PDB, including the member lines of the symbol, if any. +pub struct SymbolInfo { + /// The relative virtual address in the executable image + pub rva: u64, + /// The base address of the executable image + pub base: u64, + /// The size of the symbol (e.g. function size) + pub size: u64, + /// The (possibly mangled) name of the symbol + pub name: String, + /// The name of the module the symbol is in + pub module: String, + /// The source lines of code for the symbol + pub lines: Vec, +} + +impl SymbolInfo { + pub fn new( + rva: u64, + base: u64, + size: u64, + name: String, + module: String, + lines: Vec, + ) -> Self { + Self { + rva, + base, + size, + name, + module, + lines, + } + } +} + +#[derive(Debug)] +/// A kernel module/driver +pub struct Module { + /// The base address of the module + pub base: u64, + /// The entrypoint of the module + pub entry: u64, + /// The size of the module + pub size: u64, + /// The full name of the module + pub full_name: String, + /// The base name of the module + pub base_name: String, + /// The loaded debug info for the module + pub debug_info: Option>, +} + +impl Module { + /// Return lookup intervals for symbols in the module which can be used to build an interval tree + pub fn intervals( + &mut self, + source_cache: &SourceCache, + ) -> Result>> { + let Some(debug_info) = self.debug_info.as_mut() else { + bail!("No debug info for module {}", self.full_name); + }; + + let string_table = debug_info.pdb.string_table()?; + let address_map = debug_info.pdb.address_map()?; + let symbols = debug_info + .pdb + .debug_information()? + .modules()? + .iterator() + .filter_map(|module| module.ok()) + .filter_map(|module| { + debug_info + .pdb + .module_info(&module) + .ok() + .flatten() + .map(|module_info| (module, module_info)) + }) + .flat_map(|(_module, module_info)| { + let Ok(line_program) = module_info.line_program() else { + return Vec::new(); + }; + + let Ok(symbols) = module_info.symbols() else { + return Vec::new(); + }; + + symbols + .iterator() + .filter_map(|symbol| symbol.ok()) + .filter_map(|symbol| { + symbol.parse().ok().map(|symbol_data| (symbol, symbol_data)) + }) + .filter_map(|(_symbol, symbol_data)| { + let SymbolData::Procedure(procedure_symbol) = symbol_data else { + return None; + }; + let symbol_name = symbol_data.name()?; + let procedure_rva = procedure_symbol.offset.to_rva(&address_map)?; + + let lines = line_program + .lines_for_symbol(procedure_symbol.offset) + .iterator() + .filter_map(|line| line.ok()) + .filter_map(|line_info| { + let Ok(line_file_info) = + line_program.get_file_info(line_info.file_index) + else { + if let Ok(o) = get_object("tsffs") { + debug!(o, "No file info for line {:?}", line_info); + } + return None; + }; + + let Ok(line_file_name) = string_table.get(line_file_info.name) + else { + if let Ok(o) = get_object("tsffs") { + debug!(o, "No file name for line {:?}", line_file_info); + } + return None; + }; + + let Some(line_rva) = line_info.offset.to_rva(&address_map) else { + if let Ok(o) = get_object("tsffs") { + debug!(o, "No RVA for line {:?}", line_info); + } + return None; + }; + + let Ok(Some(source_file)) = source_cache + .lookup_pdb(&line_file_info, &line_file_name.to_string()) + else { + if let Ok(o) = get_object("tsffs") { + debug!(o, "No source file path for line {:?}", line_info); + } + return None; + }; + + let info = LineInfo { + rva: line_rva.0 as u64, + size: line_info.length.unwrap_or(1), + file_path: source_file.to_path_buf(), + start_line: line_info.line_start, + end_line: line_info.line_end, + }; + if let Ok(o) = get_object("tsffs") { + debug!(o, "Got line info {:?}", line_info); + } + + Some(info) + }) + .collect::>(); + + let info = SymbolInfo::new( + procedure_rva.0 as u64, + self.base, + procedure_symbol.len as u64, + symbol_name.to_string().to_string(), + self.full_name.clone(), + lines, + ); + + Some(info) + }) + .collect::>() + }) + .collect::>(); + + Ok(symbols + .into_iter() + .map(|s| (self.base + s.rva..self.base + s.rva + s.size, s).into()) + .collect()) + } +} diff --git a/src/os/windows/idt.rs b/src/os/windows/idt.rs new file mode 100644 index 00000000..0901bfda --- /dev/null +++ b/src/os/windows/idt.rs @@ -0,0 +1,38 @@ +#[repr(C)] // NOTE: Without repr(C) alignment causes corruption +#[derive(Debug, Clone)] +// NOTE: The vergilius generated struct is incorrectly sized so we use this one +pub struct IdtEntry64 { + offset_low: u16, + selector: u16, + ist: u8, + type_attr: u8, + offset_middle: u16, + offset_high: u32, + _reserved: u32, +} + +impl IdtEntry64 { + pub fn offset(&self) -> u64 { + (self.offset_high as u64) << 32 | (self.offset_middle as u64) << 16 | self.offset_low as u64 + } + + pub fn selector(&self) -> u16 { + self.selector + } + + pub fn ist(&self) -> u8 { + self.ist & 0b111 + } + + pub fn gate_type(&self) -> u8 { + self.type_attr & 0b1111 + } + + pub fn dpl(&self) -> u8 { + (self.type_attr >> 5) & 0b11 + } + + pub fn present(&self) -> bool { + (self.type_attr >> 7) & 1 == 1 + } +} diff --git a/src/os/windows/kernel.rs b/src/os/windows/kernel.rs new file mode 100644 index 00000000..6598a254 --- /dev/null +++ b/src/os/windows/kernel.rs @@ -0,0 +1,527 @@ +use std::{ + collections::{HashMap, HashSet}, + path::{Path, PathBuf}, +}; + +use anyhow::{anyhow, bail, Result}; +use pdb::{FallibleIterator, SymbolData}; +use simics::{debug, get_attribute, get_object, info, ConfObject}; +use vergilius::bindings::*; +use windows_sys::Win32::System::{ + Diagnostics::Debug::{IMAGE_DIRECTORY_ENTRY_EXPORT, IMAGE_NT_HEADERS64}, + Kernel::LIST_ENTRY, + SystemServices::{ + IMAGE_DOS_HEADER, IMAGE_DOS_SIGNATURE, IMAGE_EXPORT_DIRECTORY, IMAGE_NT_SIGNATURE, + }, +}; + +use crate::os::{ + windows::{ + debug_info::DebugInfo, + idt::IdtEntry64, + util::{read_nul_terminated_string, read_unicode_string, read_virtual}, + }, + DebugInfoConfig, +}; + +use super::{ + debug_info::{Module, Process}, + structs::{WindowsEProcess, WindowsKThread, WindowsKpcr, WindowsKprcb}, +}; + +const KUSER_SHARED_DATA_ADDRESS_X86_64: u64 = 0xFFFFF78000000000; + +/// Returns whether the given page is the ntos kernel +pub fn page_is_kernel(processor: *mut ConfObject, address: u64) -> Result { + const OPTIONAL_HEADER_SIGNATURE_PE32: u16 = 0x10b; + const OPTIONAL_HEADER_SIGNATURE_PE32_PLUS: u16 = 0x20b; + + let dos_header = read_virtual::(processor, address)?; + + if dos_header.e_magic != IMAGE_DOS_SIGNATURE { + return Ok(false); + } + + let nt_header = + read_virtual::(processor, address + dos_header.e_lfanew as u64)?; + + if nt_header.Signature != IMAGE_NT_SIGNATURE { + debug!( + "NT Signature {:#x} != {:#x}", + nt_header.Signature, IMAGE_NT_SIGNATURE + ); + return Ok(false); + } + + debug!( + "Found NT signature at {:#x}", + address + dos_header.e_lfanew as u64 + ); + + if nt_header.FileHeader.SizeOfOptionalHeader == 0 { + debug!(get_object("tsffs")?, "Optional header size was 0"); + return Ok(false); + } + + if ![ + OPTIONAL_HEADER_SIGNATURE_PE32, + OPTIONAL_HEADER_SIGNATURE_PE32_PLUS, + ] + .contains(&nt_header.OptionalHeader.Magic) + { + debug!( + "Optional header magic {:#x} unrecognized", + nt_header.OptionalHeader.Magic + ); + return Ok(false); + } + + let image_size = nt_header.OptionalHeader.SizeOfImage as u64; + + debug!(get_object("tsffs")?, "Image size is {:#x}", image_size); + + let export_header_offset = nt_header.OptionalHeader.DataDirectory + [IMAGE_DIRECTORY_ENTRY_EXPORT as usize] + .VirtualAddress as u64; + let export_header_size = + nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT as usize].Size as u64; + + if export_header_offset == 0 || export_header_offset >= image_size { + debug!( + "Export header offset {:#x} invalid for image sized {:#x}", + export_header_offset, image_size + ); + return Ok(false); + } + + if export_header_size == 0 || export_header_offset + export_header_size > image_size { + debug!( + "Export header size {:#x} and offset {:#x} invalid for image sized {:#x}", + export_header_size, export_header_offset, image_size + ); + return Ok(false); + } + + debug!( + "Export header offset {:#x} size {:#x}", + export_header_offset, export_header_size + ); + + let export_directory = + read_virtual::(processor, address + export_header_offset)?; + + let name = read_nul_terminated_string(processor, address + export_directory.Name as u64)?; + + debug!(get_object("tsffs")?, "Read image name {}", name); + + if name == "ntoskrnl.exe" { + return Ok(true); + } + + Ok(false) +} + +/// Search for the ntos kernel within a given address range +pub fn find_kernel(processor: *mut ConfObject, start: u64, step: u64) -> Result { + let mut scan_address = start & !(step - 1); + let stop_address = start & !(0x1000000000000 - 1); + + debug!( + "Scanning for kernel from {:#x}->{:#x}", + stop_address, scan_address + ); + + while scan_address >= stop_address { + if page_is_kernel(processor, scan_address)? { + return Ok(scan_address); + } + + scan_address -= step; + } + + bail!("Kernel not found"); +} + +/// Search for the ntos kernel by using the IDT to determine scan ranges, given a build number +pub fn find_kernel_with_idt(processor: *mut ConfObject, build: u32) -> Result { + let sim_idtr_base: u64 = get_attribute(processor, "idtr_base")?.try_into()?; + + for i in 0..256 { + // try each idtr entry + let idtr_entry0 = read_virtual::( + processor, + sim_idtr_base + (i * std::mem::size_of::() as u64), + )?; + if !idtr_entry0.present() { + debug!(get_object("tsffs")?, "Entry {} not present, skipping", i); + continue; + } + let idtr_entry0_offset = idtr_entry0.offset(); + debug!( + get_object("tsffs")?, + "Got valid IDT entry with offset {:#x}", idtr_entry0_offset + ); + return find_kernel( + processor, + idtr_entry0_offset, + if build >= 19000 { 0x200000 } else { 0x1000 }, + ); + } + + bail!("Kernel not found"); +} + +#[derive(Debug)] +/// Information about the currently running windows kernel +pub struct KernelInfo { + /// The base address of the kernel + pub base: u64, + /// The major version of windows + pub major: u32, + /// The minor version of windows + pub minor: u32, + /// the build number of windows + pub build: u32, + /// The loaded debug information for the kernel + pub debug_info: DebugInfo<'static>, +} + +impl KernelInfo { + /// Create a new kernel info struct + pub fn new

( + processor: *mut ConfObject, + name: &str, + base: u64, + download_directory: P, + not_found_full_name_cache: &mut HashSet, + user_debug_info: &mut DebugInfoConfig, + ) -> Result + where + P: AsRef, + { + let debug_info = DebugInfo::new( + processor, + name, + base, + download_directory, + not_found_full_name_cache, + // NOTE: We override that system must be true for the kernel because we must + // download it + &DebugInfoConfig { + system: true, + user_debug_info: user_debug_info.user_debug_info, + coverage: user_debug_info.coverage, + }, + )? + .ok_or_else(|| anyhow!("Failed to get debug info for kernel"))?; + + let kuser_shared_data = read_virtual::( + processor, + KUSER_SHARED_DATA_ADDRESS_X86_64, + )?; + + Ok(Self { + base, + major: kuser_shared_data.NtMajorVersion, + minor: kuser_shared_data.NtMinorVersion, + build: kuser_shared_data.NtBuildNumber, + debug_info, + }) + } + + fn find_ps_loaded_module_list_address(&mut self) -> Result { + // PsLoadedModuleList is either a public(publicsymbol) in the PDB file, or if it is not + // in the PDB file, we can find it via the export table in the PE file. + let pdb_symbols = self.debug_info.pdb.global_symbols()?; + let pdb_address_map = self.debug_info.pdb.address_map()?; + if let Ok(Some(ps_loaded_module_list_symbol)) = + pdb_symbols.iter().find_map(|symbol| match symbol.parse() { + Ok(symbol) => { + if let SymbolData::Public(public_symbol) = symbol { + if public_symbol.name.to_string() == "PsLoadedModuleList" { + Ok(Some( + public_symbol + .offset + .to_rva(&pdb_address_map) + .ok_or_else(|| pdb::Error::AddressMapNotFound)? + .0 as u64 + + self.base, + )) + } else { + Ok(None) + } + } else { + Ok(None) + } + } + Err(e) => Err(e), + }) + { + Ok(ps_loaded_module_list_symbol) + } else { + self.debug_info + .exports()? + .iter() + .find(|export| { + export + .name + .as_ref() + .is_some_and(|name| name == "PsLoadedModuleList") + }) + .map(|export| export.rva as u64 + self.base) + .ok_or_else(|| anyhow!("PsLoadedModuleList not found")) + } + } + + /// Return the list of currently loaded modules + pub fn loaded_module_list

( + &mut self, + processor: *mut ConfObject, + download_directory: P, + not_found_full_name_cache: &mut HashSet, + user_debug_info: &DebugInfoConfig, + ) -> Result> + where + P: AsRef, + { + let list_address = self.find_ps_loaded_module_list_address()?; + debug!( + get_object("tsffs")?, + "PsLoadedModuleList: {:#x}", list_address + ); + let list = read_virtual::(processor, list_address)?; + let mut modules = Vec::new(); + + let mut current = list.Flink; + + while current != list_address as *mut _ { + // NOTE: _KLDR_DATA_TABLE_ENTRY struct is stable for all versions of 10, *except* for the following fields: + // union + // { + // VOID* Spare; //0x90 + // struct _KLDR_DATA_TABLE_ENTRY* NtDataTableEntry; //0x90 + // }; + // ULONG SizeOfImageNotRounded; //0x98 + // ULONG TimeDateStamp; //0x9c + // + // We don't use these, so it's ok to just use the latest version of this struct instead of generalizing + let ldr_data_table_entry = read_virtual::< + windows_10_0_22631_2428_x64::_KLDR_DATA_TABLE_ENTRY, + >(processor, current as u64)?; + + let base = ldr_data_table_entry.DllBase as u64; + let entry = ldr_data_table_entry.EntryPoint as u64; + let size = ldr_data_table_entry.SizeOfImage as u64; + let full_name = read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + )?; + let base_name = read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + )?; + let debug_info = full_name + .split('\\') + .last() + .ok_or_else(|| anyhow!("Failed to get file name")) + .and_then(|fname| { + // No need for DTB version because kernel is always mapped + DebugInfo::new( + processor, + fname, + base, + download_directory.as_ref(), + not_found_full_name_cache, + user_debug_info, + ) + }) + .ok() + .flatten(); + + modules.push(Module { + base, + entry, + size, + full_name, + base_name, + debug_info, + }); + + current = ldr_data_table_entry.InLoadOrderLinks.Flink as *mut _; + } + + Ok(modules) + } + + fn find_ps_initial_system_process_address(&mut self) -> Result { + // PsInitialSystemProcess is either a public(publicsymbol) in the PDB file, or if it is not + // in the PDB file, we can find it via the export table in the PE file. + let pdb_symbols = self.debug_info.pdb.global_symbols()?; + let pdb_address_map = self.debug_info.pdb.address_map()?; + if let Ok(Some(ps_initial_system_process_symbol)) = + pdb_symbols.iter().find_map(|symbol| match symbol.parse() { + Ok(symbol) => { + if let SymbolData::Public(public_symbol) = symbol { + if public_symbol.name.to_string() == "PsInitialSystemProcess" { + Ok(Some( + public_symbol + .offset + .to_rva(&pdb_address_map) + .ok_or_else(|| pdb::Error::AddressMapNotFound)? + .0 as u64 + + self.base, + )) + } else { + Ok(None) + } + } else { + Ok(None) + } + } + Err(e) => Err(e), + }) + { + Ok(ps_initial_system_process_symbol) + } else { + self.debug_info + .exports()? + .iter() + .find(|export| { + export + .name + .as_ref() + .is_some_and(|name| name == "PsInitialSystemProcess") + }) + .map(|export| export.rva as u64 + self.base) + .ok_or_else(|| anyhow!("PsInitialSystemProcess not found")) + } + } + + /// Return the currently running process + pub fn current_process

( + &mut self, + processor: *mut ConfObject, + download_directory: P, + not_found_full_name_cache: &mut HashSet, + user_debug_info: &DebugInfoConfig, + ) -> Result + where + P: AsRef, + { + let kpcr = WindowsKpcr::new(processor, self.major, self.minor, self.build)?; + let kprcb = WindowsKprcb::new( + processor, + self.major, + self.minor, + self.build, + kpcr.kpcrb_address(), + )?; + let kthread = WindowsKThread::new( + processor, + self.major, + self.minor, + self.build, + kprcb.current_thread(), + )?; + let eprocess = kthread.process(processor, self.major, self.minor, self.build)?; + + Ok(Process { + pid: eprocess.pid(), + file_name: eprocess.file_name(processor)?, + base_address: eprocess.base_address(processor, self.major, self.minor, self.build)?, + modules: eprocess + .modules( + processor, + self.major, + self.minor, + self.build, + download_directory.as_ref(), + not_found_full_name_cache, + user_debug_info, + ) + .unwrap_or_default(), + }) + } + + /// Return the list of loaded processes + pub fn process_list

( + &mut self, + processor: *mut ConfObject, + download_directory: P, + not_found_full_name_cache: &mut HashSet, + user_debug_info: &DebugInfoConfig, + ) -> Result> + where + P: AsRef, + { + let kpcr = WindowsKpcr::new(processor, self.major, self.minor, self.build)?; + let kprcb = WindowsKprcb::new( + processor, + self.major, + self.minor, + self.build, + kpcr.kpcrb_address(), + )?; + let kthread = WindowsKThread::new( + processor, + self.major, + self.minor, + self.build, + kprcb.current_thread(), + )?; + let eprocess = kthread.process(processor, self.major, self.minor, self.build)?; + // Print initial process info + + let mut processes = Vec::new(); + + let mut list_entry = eprocess.active_process_links(); + let last_entry = list_entry.Blink; + + while !list_entry.Flink.is_null() { + let eprocess = WindowsEProcess::new_from_active_process_links_address( + processor, + self.major, + self.minor, + self.build, + list_entry.Flink as u64, + )?; + let pid = eprocess.pid(); + let file_name = eprocess.file_name(processor)?; + let base_address = + eprocess.base_address(processor, self.major, self.minor, self.build)?; + debug!( + get_object("tsffs")?, + "Found process {} at {:#x}", file_name, base_address + ); + let modules = eprocess + .modules( + processor, + self.major, + self.minor, + self.build, + download_directory.as_ref(), + not_found_full_name_cache, + user_debug_info, + ) + .unwrap_or_default(); + debug!(get_object("tsffs")?, "Found {} modules", modules.len()); + + processes.push(Process { + pid, + file_name, + base_address, + modules, + }); + + list_entry = eprocess.active_process_links(); + + if list_entry.Flink == last_entry { + break; + } + } + + Ok(processes) + } +} diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs new file mode 100644 index 00000000..2aaecbac --- /dev/null +++ b/src/os/windows/mod.rs @@ -0,0 +1,287 @@ +use anyhow::{anyhow, ensure, Result}; +use debug_info::{Module, Process, SymbolInfo}; +use ffi::ffi; +use intervaltree::IntervalTree; +use kernel::{find_kernel_with_idt, KernelInfo}; +use raw_cstr::AsRawCstr; +use simics::{ + debug, get_interface, get_object, get_processor_number, info, sys::cpu_cb_handle_t, warn, + ConfObject, CpuInstrumentationSubscribeInterface, IntRegisterInterface, + ProcessorInfoV2Interface, +}; +use std::{ + collections::{hash_map::Entry, HashMap, HashSet}, + ffi::c_void, + path::{Path, PathBuf}, +}; +use structs::WindowsKpcr; +use util::read_virtual; + +use vergilius::bindings::*; + +use crate::{source_cov::SourceCache, Tsffs}; + +use super::DebugInfoConfig; + +pub mod debug_info; +pub mod idt; +pub mod kernel; +pub mod paging; +pub mod pdb; +pub mod structs; +pub mod util; + +const KUSER_SHARED_DATA_ADDRESS_X86_64: u64 = 0xFFFFF78000000000; + +#[derive(Debug)] +pub struct CpuInstrumentationCbHandle(usize); + +impl From<*mut cpu_cb_handle_t> for CpuInstrumentationCbHandle { + fn from(value: *mut cpu_cb_handle_t) -> Self { + Self(value as usize) + } +} + +impl From for *mut cpu_cb_handle_t { + fn from(value: CpuInstrumentationCbHandle) -> Self { + value.0 as *mut _ + } +} + +#[derive(Debug, Default)] +/// Container for various types of information about a running Windows OS +pub struct WindowsOsInfo { + /// Kernel info + pub kernel_info: Option, + /// Per-CPU current process, there may be overlap between them. + pub processes: HashMap, + /// Per-CPU kernel module list, there may be overlap between them. + pub modules: HashMap>, + /// Per-CPU Symbol lookup trees + pub symbol_lookup_trees: HashMap>, + /// Cache of full names of both processes and kernel modules which are not found from + /// the pdb server + pub not_found_full_name_cache: HashSet, + /// Callbacks on instruction to do coverage lookups + pub instruction_callbacks: HashMap, +} + +impl WindowsOsInfo { + /// Collect or refresh OS info. Typically run on new CR3 writes to refresh for + /// possibly-changed address space mappings. + pub fn collect

( + &mut self, + processor: *mut ConfObject, + download_directory: P, + user_debug_info: &mut DebugInfoConfig, + source_cache: &SourceCache, + ) -> Result<()> + where + P: AsRef, + { + info!(get_object("tsffs")?, "Collecting Windows OS information"); + let processor_nr = get_processor_number(processor)?; + let mut processor_info_v2: ProcessorInfoV2Interface = get_interface(processor)?; + + if self.kernel_info.is_none() { + info!(get_object("tsffs")?, "Collecting kernel information"); + // Make sure we're running 64-bit Windows + ensure!( + processor_info_v2.get_logical_address_width()? == 64, + "Only 64-bit Windows is supported" + ); + + let kuser_shared_data = read_virtual::( + processor, + KUSER_SHARED_DATA_ADDRESS_X86_64, + )?; + + let (maj, min, build) = ( + kuser_shared_data.NtMajorVersion, + kuser_shared_data.NtMinorVersion, + kuser_shared_data.NtBuildNumber, + ); + + ensure!(maj == 10, "Only Windows 10/11 is supported"); + + // Initialize the KPCR to make sure we have a valid one at gs_base + let _ = WindowsKpcr::new(processor, maj, min, build)?; + let kernel_base = find_kernel_with_idt(processor, build)?; + + info!(get_object("tsffs")?, "Found kernel base {kernel_base:#x}"); + + self.kernel_info = Some(KernelInfo::new( + processor, + "ntoskrnl.exe", + kernel_base, + download_directory.as_ref(), + &mut self.not_found_full_name_cache, + user_debug_info, + )?); + } + + info!(get_object("tsffs")?, "Collecting process list"); + + self.processes.insert( + processor_nr, + self.kernel_info + .as_mut() + .expect("Kernel Info must be set at this point") + .current_process( + processor, + download_directory.as_ref(), + &mut self.not_found_full_name_cache, + user_debug_info, + )?, + ); + + info!(get_object("tsffs")?, "Collecting module list"); + + self.modules.insert( + processor_nr, + self.kernel_info + .as_mut() + .expect("Kernel Info must be set at this point") + .loaded_module_list( + processor, + download_directory.as_ref(), + &mut self.not_found_full_name_cache, + user_debug_info, + )?, + ); + + let elements = self + .modules + .get_mut(&processor_nr) + .ok_or_else(|| anyhow!("No modules for processor {processor_nr}"))? + .iter_mut() + .filter_map(|m| { + m.intervals(source_cache).ok().or_else(|| { + get_object("tsffs") + .and_then(|obj| { + debug!( + obj, + "Failed (or skipped) getting intervals for module {}", &m.full_name + ); + Err( + anyhow!("Failed to get intervals for module {}", &m.full_name) + .into(), + ) + }) + .ok() + }) + }) + .collect::>() + .into_iter() + .chain( + self.kernel_info + .as_mut() + .expect("Kernel Info must be set at this point") + .current_process( + processor, + download_directory.as_ref(), + &mut self.not_found_full_name_cache, + user_debug_info, + )? + .modules + .iter_mut() + .filter_map(|m| { + m.intervals(source_cache).ok().or_else(|| { + get_object("tsffs") + .and_then(|obj| { + debug!( + obj, + "Failed (or skipped) getting intervals for module {}", + &m.full_name + ); + Err(anyhow!( + "Failed to get intervals for module {}", + &m.full_name + ) + .into()) + }) + .ok() + }) + }) + .collect::>(), + ) + .flatten() + .collect::>(); + + let mut filtered_elements = HashSet::new(); + + // Deduplicate elements by their range + let elements = elements + .into_iter() + .filter(|e| filtered_elements.insert(e.range.clone())) + .collect::>(); + + // Populate elements into the coverage record set + elements.iter().map(|e| &e.value).for_each(|si| { + if let Some(first) = si.lines.first() { + let record = user_debug_info.coverage.get_or_insert_mut(&first.file_path); + record.add_function_if_not_exists( + first.start_line as usize, + si.lines.last().map(|l| l.end_line as usize), + &si.name, + ); + si.lines.iter().for_each(|l| { + (l.start_line..=l.end_line).for_each(|line| { + record.add_line_if_not_exists(line as usize); + }); + }); + } + }); + + self.symbol_lookup_trees.insert( + processor_nr, + elements.iter().cloned().collect::>(), + ); + + Ok(()) + } +} + +impl Tsffs { + /// Triggered on control register write to refresh windows OS information if necessary + pub fn on_control_register_write_windows_symcov( + &mut self, + trigger_obj: *mut ConfObject, + register_nr: i64, + value: i64, + ) -> Result<()> { + let mut int_register: IntRegisterInterface = get_interface(trigger_obj)?; + let processor_nr = get_processor_number(trigger_obj)?; + + if self.processors.contains_key(&processor_nr) + && self.coverage_enabled + && self.windows + && self.symbolic_coverage + && register_nr == int_register.get_number("cr3".as_raw_cstr()?)? as i64 + && self + .cr3_cache + .get(&processor_nr) + .is_some_and(|v| *v != value) + { + info!( + get_object("tsffs")?, + "Got write {value:#x} to CR3 for processor {processor_nr}, refreshing kernel & process mappings" + ); + + self.windows_os_info.collect( + trigger_obj, + &self.debuginfo_download_directory, + &mut DebugInfoConfig { + system: self.symbolic_coverage_system, + user_debug_info: &self.debug_info, + coverage: &mut self.coverage, + }, + &self.source_file_cache, + )?; + + self.cr3_cache.insert(processor_nr, value); + } + + Ok(()) + } +} diff --git a/src/os/windows/paging.rs b/src/os/windows/paging.rs new file mode 100644 index 00000000..2a41ff68 --- /dev/null +++ b/src/os/windows/paging.rs @@ -0,0 +1,2520 @@ +/* automatically generated by rust-bindgen 0.69.1 */ + +#![allow( + non_snake_case, + non_camel_case_types, + non_upper_case_globals, + clippy::useless_transmute, + clippy::unnecessary_cast, + clippy::too_many_arguments, + clippy::upper_case_acronyms, + unused +)] + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { + *byte |= mask; + } else { + *byte &= !mask; + } + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } +} +pub const _STDINT_H: u32 = 1; +pub const _FEATURES_H: u32 = 1; +pub const _DEFAULT_SOURCE: u32 = 1; +pub const __GLIBC_USE_ISOC2X: u32 = 0; +pub const __USE_ISOC11: u32 = 1; +pub const __USE_ISOC99: u32 = 1; +pub const __USE_ISOC95: u32 = 1; +pub const __USE_POSIX_IMPLICITLY: u32 = 1; +pub const _POSIX_SOURCE: u32 = 1; +pub const _POSIX_C_SOURCE: u32 = 200809; +pub const __USE_POSIX: u32 = 1; +pub const __USE_POSIX2: u32 = 1; +pub const __USE_POSIX199309: u32 = 1; +pub const __USE_POSIX199506: u32 = 1; +pub const __USE_XOPEN2K: u32 = 1; +pub const __USE_XOPEN2K8: u32 = 1; +pub const _ATFILE_SOURCE: u32 = 1; +pub const __WORDSIZE: u32 = 64; +pub const __WORDSIZE_TIME64_COMPAT32: u32 = 0; +pub const __TIMESIZE: u32 = 64; +pub const __USE_MISC: u32 = 1; +pub const __USE_ATFILE: u32 = 1; +pub const __USE_FORTIFY_LEVEL: u32 = 0; +pub const __GLIBC_USE_DEPRECATED_GETS: u32 = 0; +pub const __GLIBC_USE_DEPRECATED_SCANF: u32 = 0; +pub const __GLIBC_USE_C2X_STRTOL: u32 = 0; +pub const _STDC_PREDEF_H: u32 = 1; +pub const __STDC_IEC_559__: u32 = 1; +pub const __STDC_IEC_60559_BFP__: u32 = 201404; +pub const __STDC_IEC_559_COMPLEX__: u32 = 1; +pub const __STDC_IEC_60559_COMPLEX__: u32 = 201404; +pub const __STDC_ISO_10646__: u32 = 201706; +pub const __GNU_LIBRARY__: u32 = 6; +pub const __GLIBC__: u32 = 2; +pub const __GLIBC_MINOR__: u32 = 38; +pub const _SYS_CDEFS_H: u32 = 1; +pub const __glibc_c99_flexarr_available: u32 = 1; +pub const __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI: u32 = 0; +pub const __HAVE_GENERIC_SELECTION: u32 = 1; +pub const __GLIBC_USE_LIB_EXT2: u32 = 0; +pub const __GLIBC_USE_IEC_60559_BFP_EXT: u32 = 0; +pub const __GLIBC_USE_IEC_60559_BFP_EXT_C2X: u32 = 0; +pub const __GLIBC_USE_IEC_60559_EXT: u32 = 0; +pub const __GLIBC_USE_IEC_60559_FUNCS_EXT: u32 = 0; +pub const __GLIBC_USE_IEC_60559_FUNCS_EXT_C2X: u32 = 0; +pub const __GLIBC_USE_IEC_60559_TYPES_EXT: u32 = 0; +pub const _BITS_TYPES_H: u32 = 1; +pub const _BITS_TYPESIZES_H: u32 = 1; +pub const __OFF_T_MATCHES_OFF64_T: u32 = 1; +pub const __INO_T_MATCHES_INO64_T: u32 = 1; +pub const __RLIM_T_MATCHES_RLIM64_T: u32 = 1; +pub const __STATFS_MATCHES_STATFS64: u32 = 1; +pub const __FD_SETSIZE: u32 = 1024; +pub const _BITS_TIME64_H: u32 = 1; +pub const _BITS_WCHAR_H: u32 = 1; +pub const _BITS_STDINT_INTN_H: u32 = 1; +pub const _BITS_STDINT_UINTN_H: u32 = 1; +pub const INT8_MIN: i32 = -128; +pub const INT16_MIN: i32 = -32768; +pub const INT32_MIN: i32 = -2147483648; +pub const INT8_MAX: u32 = 127; +pub const INT16_MAX: u32 = 32767; +pub const INT32_MAX: u32 = 2147483647; +pub const UINT8_MAX: u32 = 255; +pub const UINT16_MAX: u32 = 65535; +pub const UINT32_MAX: u32 = 4294967295; +pub const INT_LEAST8_MIN: i32 = -128; +pub const INT_LEAST16_MIN: i32 = -32768; +pub const INT_LEAST32_MIN: i32 = -2147483648; +pub const INT_LEAST8_MAX: u32 = 127; +pub const INT_LEAST16_MAX: u32 = 32767; +pub const INT_LEAST32_MAX: u32 = 2147483647; +pub const UINT_LEAST8_MAX: u32 = 255; +pub const UINT_LEAST16_MAX: u32 = 65535; +pub const UINT_LEAST32_MAX: u32 = 4294967295; +pub const INT_FAST8_MIN: i32 = -128; +pub const INT_FAST16_MIN: i64 = -9223372036854775808; +pub const INT_FAST32_MIN: i64 = -9223372036854775808; +pub const INT_FAST8_MAX: u32 = 127; +pub const INT_FAST16_MAX: u64 = 9223372036854775807; +pub const INT_FAST32_MAX: u64 = 9223372036854775807; +pub const UINT_FAST8_MAX: u32 = 255; +pub const UINT_FAST16_MAX: i32 = -1; +pub const UINT_FAST32_MAX: i32 = -1; +pub const INTPTR_MIN: i64 = -9223372036854775808; +pub const INTPTR_MAX: u64 = 9223372036854775807; +pub const UINTPTR_MAX: i32 = -1; +pub const PTRDIFF_MIN: i64 = -9223372036854775808; +pub const PTRDIFF_MAX: u64 = 9223372036854775807; +pub const SIG_ATOMIC_MIN: i32 = -2147483648; +pub const SIG_ATOMIC_MAX: u32 = 2147483647; +pub const SIZE_MAX: i32 = -1; +pub const WINT_MIN: u32 = 0; +pub const WINT_MAX: u32 = 4294967295; +pub const _LIBC_LIMITS_H_: u32 = 1; +pub const MB_LEN_MAX: u32 = 16; +pub const _BITS_POSIX1_LIM_H: u32 = 1; +pub const _POSIX_AIO_LISTIO_MAX: u32 = 2; +pub const _POSIX_AIO_MAX: u32 = 1; +pub const _POSIX_ARG_MAX: u32 = 4096; +pub const _POSIX_CHILD_MAX: u32 = 25; +pub const _POSIX_DELAYTIMER_MAX: u32 = 32; +pub const _POSIX_HOST_NAME_MAX: u32 = 255; +pub const _POSIX_LINK_MAX: u32 = 8; +pub const _POSIX_LOGIN_NAME_MAX: u32 = 9; +pub const _POSIX_MAX_CANON: u32 = 255; +pub const _POSIX_MAX_INPUT: u32 = 255; +pub const _POSIX_MQ_OPEN_MAX: u32 = 8; +pub const _POSIX_MQ_PRIO_MAX: u32 = 32; +pub const _POSIX_NAME_MAX: u32 = 14; +pub const _POSIX_NGROUPS_MAX: u32 = 8; +pub const _POSIX_OPEN_MAX: u32 = 20; +pub const _POSIX_PATH_MAX: u32 = 256; +pub const _POSIX_PIPE_BUF: u32 = 512; +pub const _POSIX_RE_DUP_MAX: u32 = 255; +pub const _POSIX_RTSIG_MAX: u32 = 8; +pub const _POSIX_SEM_NSEMS_MAX: u32 = 256; +pub const _POSIX_SEM_VALUE_MAX: u32 = 32767; +pub const _POSIX_SIGQUEUE_MAX: u32 = 32; +pub const _POSIX_SSIZE_MAX: u32 = 32767; +pub const _POSIX_STREAM_MAX: u32 = 8; +pub const _POSIX_SYMLINK_MAX: u32 = 255; +pub const _POSIX_SYMLOOP_MAX: u32 = 8; +pub const _POSIX_TIMER_MAX: u32 = 32; +pub const _POSIX_TTY_NAME_MAX: u32 = 9; +pub const _POSIX_TZNAME_MAX: u32 = 6; +pub const _POSIX_CLOCKRES_MIN: u32 = 20000000; +pub const NR_OPEN: u32 = 1024; +pub const NGROUPS_MAX: u32 = 65536; +pub const ARG_MAX: u32 = 131072; +pub const LINK_MAX: u32 = 127; +pub const MAX_CANON: u32 = 255; +pub const MAX_INPUT: u32 = 255; +pub const NAME_MAX: u32 = 255; +pub const PATH_MAX: u32 = 4096; +pub const PIPE_BUF: u32 = 4096; +pub const XATTR_NAME_MAX: u32 = 255; +pub const XATTR_SIZE_MAX: u32 = 65536; +pub const XATTR_LIST_MAX: u32 = 65536; +pub const RTSIG_MAX: u32 = 32; +pub const _POSIX_THREAD_KEYS_MAX: u32 = 128; +pub const PTHREAD_KEYS_MAX: u32 = 1024; +pub const _POSIX_THREAD_DESTRUCTOR_ITERATIONS: u32 = 4; +pub const PTHREAD_DESTRUCTOR_ITERATIONS: u32 = 4; +pub const _POSIX_THREAD_THREADS_MAX: u32 = 64; +pub const AIO_PRIO_DELTA_MAX: u32 = 20; +pub const PTHREAD_STACK_MIN: u32 = 131072; +pub const DELAYTIMER_MAX: u32 = 2147483647; +pub const TTY_NAME_MAX: u32 = 32; +pub const LOGIN_NAME_MAX: u32 = 256; +pub const HOST_NAME_MAX: u32 = 64; +pub const MQ_PRIO_MAX: u32 = 32768; +pub const SEM_VALUE_MAX: u32 = 2147483647; +pub const _BITS_POSIX2_LIM_H: u32 = 1; +pub const _POSIX2_BC_BASE_MAX: u32 = 99; +pub const _POSIX2_BC_DIM_MAX: u32 = 2048; +pub const _POSIX2_BC_SCALE_MAX: u32 = 99; +pub const _POSIX2_BC_STRING_MAX: u32 = 1000; +pub const _POSIX2_COLL_WEIGHTS_MAX: u32 = 2; +pub const _POSIX2_EXPR_NEST_MAX: u32 = 32; +pub const _POSIX2_LINE_MAX: u32 = 2048; +pub const _POSIX2_RE_DUP_MAX: u32 = 255; +pub const _POSIX2_CHARCLASS_NAME_MAX: u32 = 14; +pub const BC_BASE_MAX: u32 = 99; +pub const BC_DIM_MAX: u32 = 2048; +pub const BC_SCALE_MAX: u32 = 99; +pub const BC_STRING_MAX: u32 = 1000; +pub const COLL_WEIGHTS_MAX: u32 = 255; +pub const EXPR_NEST_MAX: u32 = 32; +pub const LINE_MAX: u32 = 2048; +pub const CHARCLASS_NAME_MAX: u32 = 2048; +pub const RE_DUP_MAX: u32 = 32767; +pub const CHAR_MIN: u32 = 0; +pub const PAGE_1GB_SHIFT: u32 = 30; +pub const PAGE_2MB_SHIFT: u32 = 21; +pub const PAGE_4KB_SHIFT: u32 = 12; +pub type __u_char = ::std::os::raw::c_uchar; +pub type __u_short = ::std::os::raw::c_ushort; +pub type __u_int = ::std::os::raw::c_uint; +pub type __u_long = ::std::os::raw::c_ulong; +pub type __int8_t = ::std::os::raw::c_schar; +pub type __uint8_t = ::std::os::raw::c_uchar; +pub type __int16_t = ::std::os::raw::c_short; +pub type __uint16_t = ::std::os::raw::c_ushort; +pub type __int32_t = ::std::os::raw::c_int; +pub type __uint32_t = ::std::os::raw::c_uint; +pub type __int64_t = ::std::os::raw::c_long; +pub type __uint64_t = ::std::os::raw::c_ulong; +pub type __int_least8_t = __int8_t; +pub type __uint_least8_t = __uint8_t; +pub type __int_least16_t = __int16_t; +pub type __uint_least16_t = __uint16_t; +pub type __int_least32_t = __int32_t; +pub type __uint_least32_t = __uint32_t; +pub type __int_least64_t = __int64_t; +pub type __uint_least64_t = __uint64_t; +pub type __quad_t = ::std::os::raw::c_long; +pub type __u_quad_t = ::std::os::raw::c_ulong; +pub type __intmax_t = ::std::os::raw::c_long; +pub type __uintmax_t = ::std::os::raw::c_ulong; +pub type __dev_t = ::std::os::raw::c_ulong; +pub type __uid_t = ::std::os::raw::c_uint; +pub type __gid_t = ::std::os::raw::c_uint; +pub type __ino_t = ::std::os::raw::c_ulong; +pub type __ino64_t = ::std::os::raw::c_ulong; +pub type __mode_t = ::std::os::raw::c_uint; +pub type __nlink_t = ::std::os::raw::c_uint; +pub type __off_t = ::std::os::raw::c_long; +pub type __off64_t = ::std::os::raw::c_long; +pub type __pid_t = ::std::os::raw::c_int; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct __fsid_t { + pub __val: [::std::os::raw::c_int; 2usize], +} +pub type __clock_t = ::std::os::raw::c_long; +pub type __rlim_t = ::std::os::raw::c_ulong; +pub type __rlim64_t = ::std::os::raw::c_ulong; +pub type __id_t = ::std::os::raw::c_uint; +pub type __time_t = ::std::os::raw::c_long; +pub type __useconds_t = ::std::os::raw::c_uint; +pub type __suseconds_t = ::std::os::raw::c_long; +pub type __suseconds64_t = ::std::os::raw::c_long; +pub type __daddr_t = ::std::os::raw::c_int; +pub type __key_t = ::std::os::raw::c_int; +pub type __clockid_t = ::std::os::raw::c_int; +pub type __timer_t = *mut ::std::os::raw::c_void; +pub type __blksize_t = ::std::os::raw::c_int; +pub type __blkcnt_t = ::std::os::raw::c_long; +pub type __blkcnt64_t = ::std::os::raw::c_long; +pub type __fsblkcnt_t = ::std::os::raw::c_ulong; +pub type __fsblkcnt64_t = ::std::os::raw::c_ulong; +pub type __fsfilcnt_t = ::std::os::raw::c_ulong; +pub type __fsfilcnt64_t = ::std::os::raw::c_ulong; +pub type __fsword_t = ::std::os::raw::c_long; +pub type __ssize_t = ::std::os::raw::c_long; +pub type __syscall_slong_t = ::std::os::raw::c_long; +pub type __syscall_ulong_t = ::std::os::raw::c_ulong; +pub type __loff_t = __off64_t; +pub type __caddr_t = *mut ::std::os::raw::c_char; +pub type __intptr_t = ::std::os::raw::c_long; +pub type __socklen_t = ::std::os::raw::c_uint; +pub type __sig_atomic_t = ::std::os::raw::c_int; +pub type int_least8_t = __int_least8_t; +pub type int_least16_t = __int_least16_t; +pub type int_least32_t = __int_least32_t; +pub type int_least64_t = __int_least64_t; +pub type uint_least8_t = __uint_least8_t; +pub type uint_least16_t = __uint_least16_t; +pub type uint_least32_t = __uint_least32_t; +pub type uint_least64_t = __uint_least64_t; +pub type int_fast8_t = ::std::os::raw::c_schar; +pub type int_fast16_t = ::std::os::raw::c_long; +pub type int_fast32_t = ::std::os::raw::c_long; +pub type int_fast64_t = ::std::os::raw::c_long; +pub type uint_fast8_t = ::std::os::raw::c_uchar; +pub type uint_fast16_t = ::std::os::raw::c_ulong; +pub type uint_fast32_t = ::std::os::raw::c_ulong; +pub type uint_fast64_t = ::std::os::raw::c_ulong; +pub type intmax_t = __intmax_t; +pub type uintmax_t = __uintmax_t; +#[repr(C)] +#[derive(Copy, Clone)] +pub union _VIRTUAL_MEMORY_ADDRESS { + pub Bits: _VIRTUAL_MEMORY_ADDRESS__bindgen_ty_1, + pub All: u64, +} +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct _VIRTUAL_MEMORY_ADDRESS__bindgen_ty_1 { + pub _bitfield_align_1: [u16; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +impl _VIRTUAL_MEMORY_ADDRESS__bindgen_ty_1 { + #[inline] + pub fn PageIndex(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 12u8) as u64) } + } + #[inline] + pub fn set_PageIndex(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 12u8, val as u64) + } + } + #[inline] + pub fn PtIndex(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 9u8) as u64) } + } + #[inline] + pub fn set_PtIndex(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 9u8, val as u64) + } + } + #[inline] + pub fn PdIndex(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(21usize, 9u8) as u64) } + } + #[inline] + pub fn set_PdIndex(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(21usize, 9u8, val as u64) + } + } + #[inline] + pub fn PdptIndex(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(30usize, 9u8) as u64) } + } + #[inline] + pub fn set_PdptIndex(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(30usize, 9u8, val as u64) + } + } + #[inline] + pub fn Pml4Index(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(39usize, 9u8) as u64) } + } + #[inline] + pub fn set_Pml4Index(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(39usize, 9u8, val as u64) + } + } + #[inline] + pub fn Unused(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(48usize, 16u8) as u64) } + } + #[inline] + pub fn set_Unused(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(48usize, 16u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + PageIndex: u64, + PtIndex: u64, + PdIndex: u64, + PdptIndex: u64, + Pml4Index: u64, + Unused: u64, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 12u8, { + let PageIndex: u64 = unsafe { ::std::mem::transmute(PageIndex) }; + PageIndex as u64 + }); + __bindgen_bitfield_unit.set(12usize, 9u8, { + let PtIndex: u64 = unsafe { ::std::mem::transmute(PtIndex) }; + PtIndex as u64 + }); + __bindgen_bitfield_unit.set(21usize, 9u8, { + let PdIndex: u64 = unsafe { ::std::mem::transmute(PdIndex) }; + PdIndex as u64 + }); + __bindgen_bitfield_unit.set(30usize, 9u8, { + let PdptIndex: u64 = unsafe { ::std::mem::transmute(PdptIndex) }; + PdptIndex as u64 + }); + __bindgen_bitfield_unit.set(39usize, 9u8, { + let Pml4Index: u64 = unsafe { ::std::mem::transmute(Pml4Index) }; + Pml4Index as u64 + }); + __bindgen_bitfield_unit.set(48usize, 16u8, { + let Unused: u64 = unsafe { ::std::mem::transmute(Unused) }; + Unused as u64 + }); + __bindgen_bitfield_unit + } +} +impl Default for _VIRTUAL_MEMORY_ADDRESS { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for _VIRTUAL_MEMORY_ADDRESS { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "_VIRTUAL_MEMORY_ADDRESS {{ union }}") + } +} +pub type VIRTUAL_ADDRESS = _VIRTUAL_MEMORY_ADDRESS; +pub type PVIRTUAL_ADDRESS = *mut _VIRTUAL_MEMORY_ADDRESS; +#[repr(C)] +#[derive(Copy, Clone)] +pub union _DIRECTORY_TABLE_BASE { + pub Bits: _DIRECTORY_TABLE_BASE__bindgen_ty_1, + pub All: u64, +} +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct _DIRECTORY_TABLE_BASE__bindgen_ty_1 { + pub _bitfield_align_1: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +impl _DIRECTORY_TABLE_BASE__bindgen_ty_1 { + #[inline] + pub fn Ignored0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u64) } + } + #[inline] + pub fn set_Ignored0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 3u8, val as u64) + } + } + #[inline] + pub fn PageWriteThrough(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageWriteThrough(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageCacheDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageCacheDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Ignored1(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 7u8) as u64) } + } + #[inline] + pub fn set__Ignored1(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 7u8, val as u64) + } + } + #[inline] + pub fn PhysicalAddress(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 36u8) as u64) } + } + #[inline] + pub fn set_PhysicalAddress(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 36u8, val as u64) + } + } + #[inline] + pub fn _Reserved0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(48usize, 16u8) as u64) } + } + #[inline] + pub fn set__Reserved0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(48usize, 16u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + Ignored0: u64, + PageWriteThrough: u64, + PageCacheDisable: u64, + _Ignored1: u64, + PhysicalAddress: u64, + _Reserved0: u64, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 3u8, { + let Ignored0: u64 = unsafe { ::std::mem::transmute(Ignored0) }; + Ignored0 as u64 + }); + __bindgen_bitfield_unit.set(3usize, 1u8, { + let PageWriteThrough: u64 = unsafe { ::std::mem::transmute(PageWriteThrough) }; + PageWriteThrough as u64 + }); + __bindgen_bitfield_unit.set(4usize, 1u8, { + let PageCacheDisable: u64 = unsafe { ::std::mem::transmute(PageCacheDisable) }; + PageCacheDisable as u64 + }); + __bindgen_bitfield_unit.set(5usize, 7u8, { + let _Ignored1: u64 = unsafe { ::std::mem::transmute(_Ignored1) }; + _Ignored1 as u64 + }); + __bindgen_bitfield_unit.set(12usize, 36u8, { + let PhysicalAddress: u64 = unsafe { ::std::mem::transmute(PhysicalAddress) }; + PhysicalAddress as u64 + }); + __bindgen_bitfield_unit.set(48usize, 16u8, { + let _Reserved0: u64 = unsafe { ::std::mem::transmute(_Reserved0) }; + _Reserved0 as u64 + }); + __bindgen_bitfield_unit + } +} +impl Default for _DIRECTORY_TABLE_BASE { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for _DIRECTORY_TABLE_BASE { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "_DIRECTORY_TABLE_BASE {{ union }}") + } +} +pub type CR3 = _DIRECTORY_TABLE_BASE; +pub type DIR_TABLE_BASE = _DIRECTORY_TABLE_BASE; +#[repr(C)] +#[derive(Copy, Clone)] +pub union _PML4_ENTRY { + pub Bits: _PML4_ENTRY__bindgen_ty_1, + pub All: u64, +} +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct _PML4_ENTRY__bindgen_ty_1 { + pub _bitfield_align_1: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +impl _PML4_ENTRY__bindgen_ty_1 { + #[inline] + pub fn Present(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u64) } + } + #[inline] + pub fn set_Present(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub fn ReadWrite(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u64) } + } + #[inline] + pub fn set_ReadWrite(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub fn UserSupervisor(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u64) } + } + #[inline] + pub fn set_UserSupervisor(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageWriteThrough(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageWriteThrough(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageCacheDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageCacheDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub fn Accessed(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u64) } + } + #[inline] + pub fn set_Accessed(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Ignored0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u64) } + } + #[inline] + pub fn set__Ignored0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Reserved0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u64) } + } + #[inline] + pub fn set__Reserved0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Ignored1(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 4u8) as u64) } + } + #[inline] + pub fn set__Ignored1(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 4u8, val as u64) + } + } + #[inline] + pub fn PhysicalAddress(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 40u8) as u64) } + } + #[inline] + pub fn set_PhysicalAddress(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 40u8, val as u64) + } + } + #[inline] + pub fn _Ignored2(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(52usize, 11u8) as u64) } + } + #[inline] + pub fn set__Ignored2(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(52usize, 11u8, val as u64) + } + } + #[inline] + pub fn ExecuteDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(63usize, 1u8) as u64) } + } + #[inline] + pub fn set_ExecuteDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(63usize, 1u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + Present: u64, + ReadWrite: u64, + UserSupervisor: u64, + PageWriteThrough: u64, + PageCacheDisable: u64, + Accessed: u64, + _Ignored0: u64, + _Reserved0: u64, + _Ignored1: u64, + PhysicalAddress: u64, + _Ignored2: u64, + ExecuteDisable: u64, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 1u8, { + let Present: u64 = unsafe { ::std::mem::transmute(Present) }; + Present as u64 + }); + __bindgen_bitfield_unit.set(1usize, 1u8, { + let ReadWrite: u64 = unsafe { ::std::mem::transmute(ReadWrite) }; + ReadWrite as u64 + }); + __bindgen_bitfield_unit.set(2usize, 1u8, { + let UserSupervisor: u64 = unsafe { ::std::mem::transmute(UserSupervisor) }; + UserSupervisor as u64 + }); + __bindgen_bitfield_unit.set(3usize, 1u8, { + let PageWriteThrough: u64 = unsafe { ::std::mem::transmute(PageWriteThrough) }; + PageWriteThrough as u64 + }); + __bindgen_bitfield_unit.set(4usize, 1u8, { + let PageCacheDisable: u64 = unsafe { ::std::mem::transmute(PageCacheDisable) }; + PageCacheDisable as u64 + }); + __bindgen_bitfield_unit.set(5usize, 1u8, { + let Accessed: u64 = unsafe { ::std::mem::transmute(Accessed) }; + Accessed as u64 + }); + __bindgen_bitfield_unit.set(6usize, 1u8, { + let _Ignored0: u64 = unsafe { ::std::mem::transmute(_Ignored0) }; + _Ignored0 as u64 + }); + __bindgen_bitfield_unit.set(7usize, 1u8, { + let _Reserved0: u64 = unsafe { ::std::mem::transmute(_Reserved0) }; + _Reserved0 as u64 + }); + __bindgen_bitfield_unit.set(8usize, 4u8, { + let _Ignored1: u64 = unsafe { ::std::mem::transmute(_Ignored1) }; + _Ignored1 as u64 + }); + __bindgen_bitfield_unit.set(12usize, 40u8, { + let PhysicalAddress: u64 = unsafe { ::std::mem::transmute(PhysicalAddress) }; + PhysicalAddress as u64 + }); + __bindgen_bitfield_unit.set(52usize, 11u8, { + let _Ignored2: u64 = unsafe { ::std::mem::transmute(_Ignored2) }; + _Ignored2 as u64 + }); + __bindgen_bitfield_unit.set(63usize, 1u8, { + let ExecuteDisable: u64 = unsafe { ::std::mem::transmute(ExecuteDisable) }; + ExecuteDisable as u64 + }); + __bindgen_bitfield_unit + } +} +impl Default for _PML4_ENTRY { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for _PML4_ENTRY { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "_PML4_ENTRY {{ union }}") + } +} +pub type PML4E = _PML4_ENTRY; +#[repr(C)] +#[derive(Copy, Clone)] +pub union _PDPT_ENTRY_LARGE { + pub Bits: _PDPT_ENTRY_LARGE__bindgen_ty_1, + pub All: u64, +} +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct _PDPT_ENTRY_LARGE__bindgen_ty_1 { + pub _bitfield_align_1: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +impl _PDPT_ENTRY_LARGE__bindgen_ty_1 { + #[inline] + pub fn Present(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u64) } + } + #[inline] + pub fn set_Present(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub fn ReadWrite(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u64) } + } + #[inline] + pub fn set_ReadWrite(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub fn UserSupervisor(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u64) } + } + #[inline] + pub fn set_UserSupervisor(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageWriteThrough(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageWriteThrough(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageCacheDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageCacheDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub fn Accessed(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u64) } + } + #[inline] + pub fn set_Accessed(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub fn Dirty(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u64) } + } + #[inline] + pub fn set_Dirty(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageSize(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageSize(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub fn Global(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u64) } + } + #[inline] + pub fn set_Global(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Ignored0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 3u8) as u64) } + } + #[inline] + pub fn set__Ignored0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 3u8, val as u64) + } + } + #[inline] + pub fn PageAttributeTable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageAttributeTable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Reserved0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(13usize, 17u8) as u64) } + } + #[inline] + pub fn set__Reserved0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(13usize, 17u8, val as u64) + } + } + #[inline] + pub fn PhysicalAddress(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(30usize, 22u8) as u64) } + } + #[inline] + pub fn set_PhysicalAddress(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(30usize, 22u8, val as u64) + } + } + #[inline] + pub fn _Ignored1(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(52usize, 7u8) as u64) } + } + #[inline] + pub fn set__Ignored1(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(52usize, 7u8, val as u64) + } + } + #[inline] + pub fn ProtectionKey(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(59usize, 4u8) as u64) } + } + #[inline] + pub fn set_ProtectionKey(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(59usize, 4u8, val as u64) + } + } + #[inline] + pub fn ExecuteDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(63usize, 1u8) as u64) } + } + #[inline] + pub fn set_ExecuteDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(63usize, 1u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + Present: u64, + ReadWrite: u64, + UserSupervisor: u64, + PageWriteThrough: u64, + PageCacheDisable: u64, + Accessed: u64, + Dirty: u64, + PageSize: u64, + Global: u64, + _Ignored0: u64, + PageAttributeTable: u64, + _Reserved0: u64, + PhysicalAddress: u64, + _Ignored1: u64, + ProtectionKey: u64, + ExecuteDisable: u64, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 1u8, { + let Present: u64 = unsafe { ::std::mem::transmute(Present) }; + Present as u64 + }); + __bindgen_bitfield_unit.set(1usize, 1u8, { + let ReadWrite: u64 = unsafe { ::std::mem::transmute(ReadWrite) }; + ReadWrite as u64 + }); + __bindgen_bitfield_unit.set(2usize, 1u8, { + let UserSupervisor: u64 = unsafe { ::std::mem::transmute(UserSupervisor) }; + UserSupervisor as u64 + }); + __bindgen_bitfield_unit.set(3usize, 1u8, { + let PageWriteThrough: u64 = unsafe { ::std::mem::transmute(PageWriteThrough) }; + PageWriteThrough as u64 + }); + __bindgen_bitfield_unit.set(4usize, 1u8, { + let PageCacheDisable: u64 = unsafe { ::std::mem::transmute(PageCacheDisable) }; + PageCacheDisable as u64 + }); + __bindgen_bitfield_unit.set(5usize, 1u8, { + let Accessed: u64 = unsafe { ::std::mem::transmute(Accessed) }; + Accessed as u64 + }); + __bindgen_bitfield_unit.set(6usize, 1u8, { + let Dirty: u64 = unsafe { ::std::mem::transmute(Dirty) }; + Dirty as u64 + }); + __bindgen_bitfield_unit.set(7usize, 1u8, { + let PageSize: u64 = unsafe { ::std::mem::transmute(PageSize) }; + PageSize as u64 + }); + __bindgen_bitfield_unit.set(8usize, 1u8, { + let Global: u64 = unsafe { ::std::mem::transmute(Global) }; + Global as u64 + }); + __bindgen_bitfield_unit.set(9usize, 3u8, { + let _Ignored0: u64 = unsafe { ::std::mem::transmute(_Ignored0) }; + _Ignored0 as u64 + }); + __bindgen_bitfield_unit.set(12usize, 1u8, { + let PageAttributeTable: u64 = unsafe { ::std::mem::transmute(PageAttributeTable) }; + PageAttributeTable as u64 + }); + __bindgen_bitfield_unit.set(13usize, 17u8, { + let _Reserved0: u64 = unsafe { ::std::mem::transmute(_Reserved0) }; + _Reserved0 as u64 + }); + __bindgen_bitfield_unit.set(30usize, 22u8, { + let PhysicalAddress: u64 = unsafe { ::std::mem::transmute(PhysicalAddress) }; + PhysicalAddress as u64 + }); + __bindgen_bitfield_unit.set(52usize, 7u8, { + let _Ignored1: u64 = unsafe { ::std::mem::transmute(_Ignored1) }; + _Ignored1 as u64 + }); + __bindgen_bitfield_unit.set(59usize, 4u8, { + let ProtectionKey: u64 = unsafe { ::std::mem::transmute(ProtectionKey) }; + ProtectionKey as u64 + }); + __bindgen_bitfield_unit.set(63usize, 1u8, { + let ExecuteDisable: u64 = unsafe { ::std::mem::transmute(ExecuteDisable) }; + ExecuteDisable as u64 + }); + __bindgen_bitfield_unit + } +} +impl Default for _PDPT_ENTRY_LARGE { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for _PDPT_ENTRY_LARGE { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "_PDPT_ENTRY_LARGE {{ union }}") + } +} +pub type PDPTE_LARGE = _PDPT_ENTRY_LARGE; +#[repr(C)] +#[derive(Copy, Clone)] +pub union _PDPT_ENTRY { + pub Bits: _PDPT_ENTRY__bindgen_ty_1, + pub All: u64, +} +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct _PDPT_ENTRY__bindgen_ty_1 { + pub _bitfield_align_1: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +impl _PDPT_ENTRY__bindgen_ty_1 { + #[inline] + pub fn Present(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u64) } + } + #[inline] + pub fn set_Present(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub fn ReadWrite(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u64) } + } + #[inline] + pub fn set_ReadWrite(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub fn UserSupervisor(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u64) } + } + #[inline] + pub fn set_UserSupervisor(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageWriteThrough(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageWriteThrough(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageCacheDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageCacheDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub fn Accessed(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u64) } + } + #[inline] + pub fn set_Accessed(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Ignored0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u64) } + } + #[inline] + pub fn set__Ignored0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageSize(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageSize(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Ignored1(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 4u8) as u64) } + } + #[inline] + pub fn set__Ignored1(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 4u8, val as u64) + } + } + #[inline] + pub fn PhysicalAddress(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 40u8) as u64) } + } + #[inline] + pub fn set_PhysicalAddress(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 40u8, val as u64) + } + } + #[inline] + pub fn _Ignored2(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(52usize, 11u8) as u64) } + } + #[inline] + pub fn set__Ignored2(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(52usize, 11u8, val as u64) + } + } + #[inline] + pub fn ExecuteDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(63usize, 1u8) as u64) } + } + #[inline] + pub fn set_ExecuteDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(63usize, 1u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + Present: u64, + ReadWrite: u64, + UserSupervisor: u64, + PageWriteThrough: u64, + PageCacheDisable: u64, + Accessed: u64, + _Ignored0: u64, + PageSize: u64, + _Ignored1: u64, + PhysicalAddress: u64, + _Ignored2: u64, + ExecuteDisable: u64, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 1u8, { + let Present: u64 = unsafe { ::std::mem::transmute(Present) }; + Present as u64 + }); + __bindgen_bitfield_unit.set(1usize, 1u8, { + let ReadWrite: u64 = unsafe { ::std::mem::transmute(ReadWrite) }; + ReadWrite as u64 + }); + __bindgen_bitfield_unit.set(2usize, 1u8, { + let UserSupervisor: u64 = unsafe { ::std::mem::transmute(UserSupervisor) }; + UserSupervisor as u64 + }); + __bindgen_bitfield_unit.set(3usize, 1u8, { + let PageWriteThrough: u64 = unsafe { ::std::mem::transmute(PageWriteThrough) }; + PageWriteThrough as u64 + }); + __bindgen_bitfield_unit.set(4usize, 1u8, { + let PageCacheDisable: u64 = unsafe { ::std::mem::transmute(PageCacheDisable) }; + PageCacheDisable as u64 + }); + __bindgen_bitfield_unit.set(5usize, 1u8, { + let Accessed: u64 = unsafe { ::std::mem::transmute(Accessed) }; + Accessed as u64 + }); + __bindgen_bitfield_unit.set(6usize, 1u8, { + let _Ignored0: u64 = unsafe { ::std::mem::transmute(_Ignored0) }; + _Ignored0 as u64 + }); + __bindgen_bitfield_unit.set(7usize, 1u8, { + let PageSize: u64 = unsafe { ::std::mem::transmute(PageSize) }; + PageSize as u64 + }); + __bindgen_bitfield_unit.set(8usize, 4u8, { + let _Ignored1: u64 = unsafe { ::std::mem::transmute(_Ignored1) }; + _Ignored1 as u64 + }); + __bindgen_bitfield_unit.set(12usize, 40u8, { + let PhysicalAddress: u64 = unsafe { ::std::mem::transmute(PhysicalAddress) }; + PhysicalAddress as u64 + }); + __bindgen_bitfield_unit.set(52usize, 11u8, { + let _Ignored2: u64 = unsafe { ::std::mem::transmute(_Ignored2) }; + _Ignored2 as u64 + }); + __bindgen_bitfield_unit.set(63usize, 1u8, { + let ExecuteDisable: u64 = unsafe { ::std::mem::transmute(ExecuteDisable) }; + ExecuteDisable as u64 + }); + __bindgen_bitfield_unit + } +} +impl Default for _PDPT_ENTRY { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for _PDPT_ENTRY { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "_PDPT_ENTRY {{ union }}") + } +} +pub type PDPTE = _PDPT_ENTRY; +#[repr(C)] +#[derive(Copy, Clone)] +pub union _PD_ENTRY_LARGE { + pub Bits: _PD_ENTRY_LARGE__bindgen_ty_1, + pub All: u64, +} +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct _PD_ENTRY_LARGE__bindgen_ty_1 { + pub _bitfield_align_1: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +impl _PD_ENTRY_LARGE__bindgen_ty_1 { + #[inline] + pub fn Present(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u64) } + } + #[inline] + pub fn set_Present(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub fn ReadWrite(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u64) } + } + #[inline] + pub fn set_ReadWrite(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub fn UserSupervisor(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u64) } + } + #[inline] + pub fn set_UserSupervisor(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageWriteThrough(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageWriteThrough(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageCacheDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageCacheDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub fn Accessed(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u64) } + } + #[inline] + pub fn set_Accessed(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub fn Dirty(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u64) } + } + #[inline] + pub fn set_Dirty(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageSize(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageSize(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub fn Global(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u64) } + } + #[inline] + pub fn set_Global(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Ignored0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 3u8) as u64) } + } + #[inline] + pub fn set__Ignored0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 3u8, val as u64) + } + } + #[inline] + pub fn PageAttributeTalbe(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageAttributeTalbe(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Reserved0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(13usize, 8u8) as u64) } + } + #[inline] + pub fn set__Reserved0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(13usize, 8u8, val as u64) + } + } + #[inline] + pub fn PhysicalAddress(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(21usize, 29u8) as u64) } + } + #[inline] + pub fn set_PhysicalAddress(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(21usize, 29u8, val as u64) + } + } + #[inline] + pub fn _Reserved1(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(50usize, 2u8) as u64) } + } + #[inline] + pub fn set__Reserved1(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(50usize, 2u8, val as u64) + } + } + #[inline] + pub fn _Ignored1(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(52usize, 7u8) as u64) } + } + #[inline] + pub fn set__Ignored1(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(52usize, 7u8, val as u64) + } + } + #[inline] + pub fn ProtectionKey(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(59usize, 4u8) as u64) } + } + #[inline] + pub fn set_ProtectionKey(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(59usize, 4u8, val as u64) + } + } + #[inline] + pub fn ExecuteDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(63usize, 1u8) as u64) } + } + #[inline] + pub fn set_ExecuteDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(63usize, 1u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + Present: u64, + ReadWrite: u64, + UserSupervisor: u64, + PageWriteThrough: u64, + PageCacheDisable: u64, + Accessed: u64, + Dirty: u64, + PageSize: u64, + Global: u64, + _Ignored0: u64, + PageAttributeTalbe: u64, + _Reserved0: u64, + PhysicalAddress: u64, + _Reserved1: u64, + _Ignored1: u64, + ProtectionKey: u64, + ExecuteDisable: u64, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 1u8, { + let Present: u64 = unsafe { ::std::mem::transmute(Present) }; + Present as u64 + }); + __bindgen_bitfield_unit.set(1usize, 1u8, { + let ReadWrite: u64 = unsafe { ::std::mem::transmute(ReadWrite) }; + ReadWrite as u64 + }); + __bindgen_bitfield_unit.set(2usize, 1u8, { + let UserSupervisor: u64 = unsafe { ::std::mem::transmute(UserSupervisor) }; + UserSupervisor as u64 + }); + __bindgen_bitfield_unit.set(3usize, 1u8, { + let PageWriteThrough: u64 = unsafe { ::std::mem::transmute(PageWriteThrough) }; + PageWriteThrough as u64 + }); + __bindgen_bitfield_unit.set(4usize, 1u8, { + let PageCacheDisable: u64 = unsafe { ::std::mem::transmute(PageCacheDisable) }; + PageCacheDisable as u64 + }); + __bindgen_bitfield_unit.set(5usize, 1u8, { + let Accessed: u64 = unsafe { ::std::mem::transmute(Accessed) }; + Accessed as u64 + }); + __bindgen_bitfield_unit.set(6usize, 1u8, { + let Dirty: u64 = unsafe { ::std::mem::transmute(Dirty) }; + Dirty as u64 + }); + __bindgen_bitfield_unit.set(7usize, 1u8, { + let PageSize: u64 = unsafe { ::std::mem::transmute(PageSize) }; + PageSize as u64 + }); + __bindgen_bitfield_unit.set(8usize, 1u8, { + let Global: u64 = unsafe { ::std::mem::transmute(Global) }; + Global as u64 + }); + __bindgen_bitfield_unit.set(9usize, 3u8, { + let _Ignored0: u64 = unsafe { ::std::mem::transmute(_Ignored0) }; + _Ignored0 as u64 + }); + __bindgen_bitfield_unit.set(12usize, 1u8, { + let PageAttributeTalbe: u64 = unsafe { ::std::mem::transmute(PageAttributeTalbe) }; + PageAttributeTalbe as u64 + }); + __bindgen_bitfield_unit.set(13usize, 8u8, { + let _Reserved0: u64 = unsafe { ::std::mem::transmute(_Reserved0) }; + _Reserved0 as u64 + }); + __bindgen_bitfield_unit.set(21usize, 29u8, { + let PhysicalAddress: u64 = unsafe { ::std::mem::transmute(PhysicalAddress) }; + PhysicalAddress as u64 + }); + __bindgen_bitfield_unit.set(50usize, 2u8, { + let _Reserved1: u64 = unsafe { ::std::mem::transmute(_Reserved1) }; + _Reserved1 as u64 + }); + __bindgen_bitfield_unit.set(52usize, 7u8, { + let _Ignored1: u64 = unsafe { ::std::mem::transmute(_Ignored1) }; + _Ignored1 as u64 + }); + __bindgen_bitfield_unit.set(59usize, 4u8, { + let ProtectionKey: u64 = unsafe { ::std::mem::transmute(ProtectionKey) }; + ProtectionKey as u64 + }); + __bindgen_bitfield_unit.set(63usize, 1u8, { + let ExecuteDisable: u64 = unsafe { ::std::mem::transmute(ExecuteDisable) }; + ExecuteDisable as u64 + }); + __bindgen_bitfield_unit + } +} +impl Default for _PD_ENTRY_LARGE { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for _PD_ENTRY_LARGE { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "_PD_ENTRY_LARGE {{ union }}") + } +} +pub type PDE_LARGE = _PD_ENTRY_LARGE; +#[repr(C)] +#[derive(Copy, Clone)] +pub union _PD_ENTRY { + pub Bits: _PD_ENTRY__bindgen_ty_1, + pub All: u64, +} +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct _PD_ENTRY__bindgen_ty_1 { + pub _bitfield_align_1: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +impl _PD_ENTRY__bindgen_ty_1 { + #[inline] + pub fn Present(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u64) } + } + #[inline] + pub fn set_Present(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub fn ReadWrite(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u64) } + } + #[inline] + pub fn set_ReadWrite(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub fn UserSupervisor(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u64) } + } + #[inline] + pub fn set_UserSupervisor(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageWriteThrough(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageWriteThrough(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageCacheDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageCacheDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub fn Accessed(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u64) } + } + #[inline] + pub fn set_Accessed(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Ignored0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u64) } + } + #[inline] + pub fn set__Ignored0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageSize(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageSize(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Ignored1(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 4u8) as u64) } + } + #[inline] + pub fn set__Ignored1(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 4u8, val as u64) + } + } + #[inline] + pub fn PhysicalAddress(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 38u8) as u64) } + } + #[inline] + pub fn set_PhysicalAddress(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 38u8, val as u64) + } + } + #[inline] + pub fn _Reserved0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(50usize, 2u8) as u64) } + } + #[inline] + pub fn set__Reserved0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(50usize, 2u8, val as u64) + } + } + #[inline] + pub fn _Ignored2(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(52usize, 11u8) as u64) } + } + #[inline] + pub fn set__Ignored2(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(52usize, 11u8, val as u64) + } + } + #[inline] + pub fn ExecuteDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(63usize, 1u8) as u64) } + } + #[inline] + pub fn set_ExecuteDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(63usize, 1u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + Present: u64, + ReadWrite: u64, + UserSupervisor: u64, + PageWriteThrough: u64, + PageCacheDisable: u64, + Accessed: u64, + _Ignored0: u64, + PageSize: u64, + _Ignored1: u64, + PhysicalAddress: u64, + _Reserved0: u64, + _Ignored2: u64, + ExecuteDisable: u64, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 1u8, { + let Present: u64 = unsafe { ::std::mem::transmute(Present) }; + Present as u64 + }); + __bindgen_bitfield_unit.set(1usize, 1u8, { + let ReadWrite: u64 = unsafe { ::std::mem::transmute(ReadWrite) }; + ReadWrite as u64 + }); + __bindgen_bitfield_unit.set(2usize, 1u8, { + let UserSupervisor: u64 = unsafe { ::std::mem::transmute(UserSupervisor) }; + UserSupervisor as u64 + }); + __bindgen_bitfield_unit.set(3usize, 1u8, { + let PageWriteThrough: u64 = unsafe { ::std::mem::transmute(PageWriteThrough) }; + PageWriteThrough as u64 + }); + __bindgen_bitfield_unit.set(4usize, 1u8, { + let PageCacheDisable: u64 = unsafe { ::std::mem::transmute(PageCacheDisable) }; + PageCacheDisable as u64 + }); + __bindgen_bitfield_unit.set(5usize, 1u8, { + let Accessed: u64 = unsafe { ::std::mem::transmute(Accessed) }; + Accessed as u64 + }); + __bindgen_bitfield_unit.set(6usize, 1u8, { + let _Ignored0: u64 = unsafe { ::std::mem::transmute(_Ignored0) }; + _Ignored0 as u64 + }); + __bindgen_bitfield_unit.set(7usize, 1u8, { + let PageSize: u64 = unsafe { ::std::mem::transmute(PageSize) }; + PageSize as u64 + }); + __bindgen_bitfield_unit.set(8usize, 4u8, { + let _Ignored1: u64 = unsafe { ::std::mem::transmute(_Ignored1) }; + _Ignored1 as u64 + }); + __bindgen_bitfield_unit.set(12usize, 38u8, { + let PhysicalAddress: u64 = unsafe { ::std::mem::transmute(PhysicalAddress) }; + PhysicalAddress as u64 + }); + __bindgen_bitfield_unit.set(50usize, 2u8, { + let _Reserved0: u64 = unsafe { ::std::mem::transmute(_Reserved0) }; + _Reserved0 as u64 + }); + __bindgen_bitfield_unit.set(52usize, 11u8, { + let _Ignored2: u64 = unsafe { ::std::mem::transmute(_Ignored2) }; + _Ignored2 as u64 + }); + __bindgen_bitfield_unit.set(63usize, 1u8, { + let ExecuteDisable: u64 = unsafe { ::std::mem::transmute(ExecuteDisable) }; + ExecuteDisable as u64 + }); + __bindgen_bitfield_unit + } +} +impl Default for _PD_ENTRY { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for _PD_ENTRY { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "_PD_ENTRY {{ union }}") + } +} +pub type PDE = _PD_ENTRY; +#[repr(C)] +#[derive(Copy, Clone)] +pub union _PT_ENTRY { + pub Bits: _PT_ENTRY__bindgen_ty_1, + pub All: u64, +} +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct _PT_ENTRY__bindgen_ty_1 { + pub _bitfield_align_1: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +impl _PT_ENTRY__bindgen_ty_1 { + #[inline] + pub fn Present(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u64) } + } + #[inline] + pub fn set_Present(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub fn ReadWrite(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u64) } + } + #[inline] + pub fn set_ReadWrite(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub fn UserSupervisor(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u64) } + } + #[inline] + pub fn set_UserSupervisor(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageWriteThrough(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageWriteThrough(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageCacheDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageCacheDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub fn Accessed(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u64) } + } + #[inline] + pub fn set_Accessed(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub fn Dirty(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u64) } + } + #[inline] + pub fn set_Dirty(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageAttributeTable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u64) } + } + #[inline] + pub fn set_PageAttributeTable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub fn Global(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u64) } + } + #[inline] + pub fn set_Global(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 1u8, val as u64) + } + } + #[inline] + pub fn _Ignored0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 3u8) as u64) } + } + #[inline] + pub fn set__Ignored0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 3u8, val as u64) + } + } + #[inline] + pub fn PhysicalAddress(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 38u8) as u64) } + } + #[inline] + pub fn set_PhysicalAddress(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 38u8, val as u64) + } + } + #[inline] + pub fn _Reserved0(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(50usize, 2u8) as u64) } + } + #[inline] + pub fn set__Reserved0(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(50usize, 2u8, val as u64) + } + } + #[inline] + pub fn _Ignored1(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(52usize, 7u8) as u64) } + } + #[inline] + pub fn set__Ignored1(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(52usize, 7u8, val as u64) + } + } + #[inline] + pub fn ProtectionKey(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(59usize, 4u8) as u64) } + } + #[inline] + pub fn set_ProtectionKey(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(59usize, 4u8, val as u64) + } + } + #[inline] + pub fn ExecuteDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(63usize, 1u8) as u64) } + } + #[inline] + pub fn set_ExecuteDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(63usize, 1u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + Present: u64, + ReadWrite: u64, + UserSupervisor: u64, + PageWriteThrough: u64, + PageCacheDisable: u64, + Accessed: u64, + Dirty: u64, + PageAttributeTable: u64, + Global: u64, + _Ignored0: u64, + PhysicalAddress: u64, + _Reserved0: u64, + _Ignored1: u64, + ProtectionKey: u64, + ExecuteDisable: u64, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 1u8, { + let Present: u64 = unsafe { ::std::mem::transmute(Present) }; + Present as u64 + }); + __bindgen_bitfield_unit.set(1usize, 1u8, { + let ReadWrite: u64 = unsafe { ::std::mem::transmute(ReadWrite) }; + ReadWrite as u64 + }); + __bindgen_bitfield_unit.set(2usize, 1u8, { + let UserSupervisor: u64 = unsafe { ::std::mem::transmute(UserSupervisor) }; + UserSupervisor as u64 + }); + __bindgen_bitfield_unit.set(3usize, 1u8, { + let PageWriteThrough: u64 = unsafe { ::std::mem::transmute(PageWriteThrough) }; + PageWriteThrough as u64 + }); + __bindgen_bitfield_unit.set(4usize, 1u8, { + let PageCacheDisable: u64 = unsafe { ::std::mem::transmute(PageCacheDisable) }; + PageCacheDisable as u64 + }); + __bindgen_bitfield_unit.set(5usize, 1u8, { + let Accessed: u64 = unsafe { ::std::mem::transmute(Accessed) }; + Accessed as u64 + }); + __bindgen_bitfield_unit.set(6usize, 1u8, { + let Dirty: u64 = unsafe { ::std::mem::transmute(Dirty) }; + Dirty as u64 + }); + __bindgen_bitfield_unit.set(7usize, 1u8, { + let PageAttributeTable: u64 = unsafe { ::std::mem::transmute(PageAttributeTable) }; + PageAttributeTable as u64 + }); + __bindgen_bitfield_unit.set(8usize, 1u8, { + let Global: u64 = unsafe { ::std::mem::transmute(Global) }; + Global as u64 + }); + __bindgen_bitfield_unit.set(9usize, 3u8, { + let _Ignored0: u64 = unsafe { ::std::mem::transmute(_Ignored0) }; + _Ignored0 as u64 + }); + __bindgen_bitfield_unit.set(12usize, 38u8, { + let PhysicalAddress: u64 = unsafe { ::std::mem::transmute(PhysicalAddress) }; + PhysicalAddress as u64 + }); + __bindgen_bitfield_unit.set(50usize, 2u8, { + let _Reserved0: u64 = unsafe { ::std::mem::transmute(_Reserved0) }; + _Reserved0 as u64 + }); + __bindgen_bitfield_unit.set(52usize, 7u8, { + let _Ignored1: u64 = unsafe { ::std::mem::transmute(_Ignored1) }; + _Ignored1 as u64 + }); + __bindgen_bitfield_unit.set(59usize, 4u8, { + let ProtectionKey: u64 = unsafe { ::std::mem::transmute(ProtectionKey) }; + ProtectionKey as u64 + }); + __bindgen_bitfield_unit.set(63usize, 1u8, { + let ExecuteDisable: u64 = unsafe { ::std::mem::transmute(ExecuteDisable) }; + ExecuteDisable as u64 + }); + __bindgen_bitfield_unit + } +} +impl Default for _PT_ENTRY { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for _PT_ENTRY { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "_PT_ENTRY {{ union }}") + } +} +pub type PTE = _PT_ENTRY; +#[repr(C)] +#[derive(Copy, Clone)] +pub union _MMPTE_HARDWARE { + pub Bits: _MMPTE_HARDWARE__bindgen_ty_1, + pub All: u64, +} +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct _MMPTE_HARDWARE__bindgen_ty_1 { + pub _bitfield_align_1: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +impl _MMPTE_HARDWARE__bindgen_ty_1 { + #[inline] + pub fn Valid(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u64) } + } + #[inline] + pub fn set_Valid(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub fn Dirty1(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u64) } + } + #[inline] + pub fn set_Dirty1(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub fn Owner(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u64) } + } + #[inline] + pub fn set_Owner(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub fn WriteThrough(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u64) } + } + #[inline] + pub fn set_WriteThrough(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub fn CacheDisable(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u64) } + } + #[inline] + pub fn set_CacheDisable(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub fn Accessed(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u64) } + } + #[inline] + pub fn set_Accessed(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub fn Dirty(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u64) } + } + #[inline] + pub fn set_Dirty(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub fn LargePage(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u64) } + } + #[inline] + pub fn set_LargePage(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub fn Global(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u64) } + } + #[inline] + pub fn set_Global(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 1u8, val as u64) + } + } + #[inline] + pub fn CopyOnWrite(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u64) } + } + #[inline] + pub fn set_CopyOnWrite(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 1u8, val as u64) + } + } + #[inline] + pub fn Unused(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u64) } + } + #[inline] + pub fn set_Unused(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(10usize, 1u8, val as u64) + } + } + #[inline] + pub fn Write(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 1u8) as u64) } + } + #[inline] + pub fn set_Write(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(11usize, 1u8, val as u64) + } + } + #[inline] + pub fn PageFrameNumber(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 36u8) as u64) } + } + #[inline] + pub fn set_PageFrameNumber(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 36u8, val as u64) + } + } + #[inline] + pub fn ReservedForHardware(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(48usize, 4u8) as u64) } + } + #[inline] + pub fn set_ReservedForHardware(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(48usize, 4u8, val as u64) + } + } + #[inline] + pub fn ReservedForSoftware(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(52usize, 4u8) as u64) } + } + #[inline] + pub fn set_ReservedForSoftware(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(52usize, 4u8, val as u64) + } + } + #[inline] + pub fn WsleAge(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(56usize, 4u8) as u64) } + } + #[inline] + pub fn set_WsleAge(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(56usize, 4u8, val as u64) + } + } + #[inline] + pub fn WsleProtection(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(60usize, 3u8) as u64) } + } + #[inline] + pub fn set_WsleProtection(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(60usize, 3u8, val as u64) + } + } + #[inline] + pub fn NoExecute(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(63usize, 1u8) as u64) } + } + #[inline] + pub fn set_NoExecute(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(63usize, 1u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + Valid: u64, + Dirty1: u64, + Owner: u64, + WriteThrough: u64, + CacheDisable: u64, + Accessed: u64, + Dirty: u64, + LargePage: u64, + Global: u64, + CopyOnWrite: u64, + Unused: u64, + Write: u64, + PageFrameNumber: u64, + ReservedForHardware: u64, + ReservedForSoftware: u64, + WsleAge: u64, + WsleProtection: u64, + NoExecute: u64, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 1u8, { + let Valid: u64 = unsafe { ::std::mem::transmute(Valid) }; + Valid as u64 + }); + __bindgen_bitfield_unit.set(1usize, 1u8, { + let Dirty1: u64 = unsafe { ::std::mem::transmute(Dirty1) }; + Dirty1 as u64 + }); + __bindgen_bitfield_unit.set(2usize, 1u8, { + let Owner: u64 = unsafe { ::std::mem::transmute(Owner) }; + Owner as u64 + }); + __bindgen_bitfield_unit.set(3usize, 1u8, { + let WriteThrough: u64 = unsafe { ::std::mem::transmute(WriteThrough) }; + WriteThrough as u64 + }); + __bindgen_bitfield_unit.set(4usize, 1u8, { + let CacheDisable: u64 = unsafe { ::std::mem::transmute(CacheDisable) }; + CacheDisable as u64 + }); + __bindgen_bitfield_unit.set(5usize, 1u8, { + let Accessed: u64 = unsafe { ::std::mem::transmute(Accessed) }; + Accessed as u64 + }); + __bindgen_bitfield_unit.set(6usize, 1u8, { + let Dirty: u64 = unsafe { ::std::mem::transmute(Dirty) }; + Dirty as u64 + }); + __bindgen_bitfield_unit.set(7usize, 1u8, { + let LargePage: u64 = unsafe { ::std::mem::transmute(LargePage) }; + LargePage as u64 + }); + __bindgen_bitfield_unit.set(8usize, 1u8, { + let Global: u64 = unsafe { ::std::mem::transmute(Global) }; + Global as u64 + }); + __bindgen_bitfield_unit.set(9usize, 1u8, { + let CopyOnWrite: u64 = unsafe { ::std::mem::transmute(CopyOnWrite) }; + CopyOnWrite as u64 + }); + __bindgen_bitfield_unit.set(10usize, 1u8, { + let Unused: u64 = unsafe { ::std::mem::transmute(Unused) }; + Unused as u64 + }); + __bindgen_bitfield_unit.set(11usize, 1u8, { + let Write: u64 = unsafe { ::std::mem::transmute(Write) }; + Write as u64 + }); + __bindgen_bitfield_unit.set(12usize, 36u8, { + let PageFrameNumber: u64 = unsafe { ::std::mem::transmute(PageFrameNumber) }; + PageFrameNumber as u64 + }); + __bindgen_bitfield_unit.set(48usize, 4u8, { + let ReservedForHardware: u64 = unsafe { ::std::mem::transmute(ReservedForHardware) }; + ReservedForHardware as u64 + }); + __bindgen_bitfield_unit.set(52usize, 4u8, { + let ReservedForSoftware: u64 = unsafe { ::std::mem::transmute(ReservedForSoftware) }; + ReservedForSoftware as u64 + }); + __bindgen_bitfield_unit.set(56usize, 4u8, { + let WsleAge: u64 = unsafe { ::std::mem::transmute(WsleAge) }; + WsleAge as u64 + }); + __bindgen_bitfield_unit.set(60usize, 3u8, { + let WsleProtection: u64 = unsafe { ::std::mem::transmute(WsleProtection) }; + WsleProtection as u64 + }); + __bindgen_bitfield_unit.set(63usize, 1u8, { + let NoExecute: u64 = unsafe { ::std::mem::transmute(NoExecute) }; + NoExecute as u64 + }); + __bindgen_bitfield_unit + } +} +impl Default for _MMPTE_HARDWARE { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for _MMPTE_HARDWARE { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "_MMPTE_HARDWARE {{ union }}") + } +} +pub type MMPTE_HARDWARE = _MMPTE_HARDWARE; diff --git a/src/os/windows/pdb.rs b/src/os/windows/pdb.rs new file mode 100644 index 00000000..9d6f2563 --- /dev/null +++ b/src/os/windows/pdb.rs @@ -0,0 +1,135 @@ +use anyhow::{ensure, Result}; +use simics::ConfObject; + +use crate::os::windows::util::{ + read_nul_terminated_string, read_nul_terminated_string_dtb, read_virtual, read_virtual_dtb, +}; + +#[derive(Debug, Clone)] +#[repr(C)] +/// The GUID structure in a CV 7.0 header +pub struct Guid { + pub data0: u32, + pub data1: u16, + pub data2: u16, + pub data3: u64, +} + +#[derive(Debug, Clone)] +/// The header of a CV (coreview) 7.0 file +pub struct CvInfoPdb70 { + pub cv_signature: u32, + pub signature: Guid, + pub age: u32, + pub file_name: String, +} + +impl CvInfoPdb70 { + /// Parse a CV 7.0 header from a given address + pub fn new(processor: *mut ConfObject, address: u64) -> Result { + let cv_signature = read_virtual::(processor, address)?; + let signature = + read_virtual::(processor, address + std::mem::size_of::() as u64)?; + let age = read_virtual::( + processor, + address + std::mem::size_of::() as u64 + std::mem::size_of::() as u64, + )?; + let file_name = read_nul_terminated_string( + processor, + address + + std::mem::size_of::() as u64 + + std::mem::size_of::() as u64 + + std::mem::size_of::() as u64, + )?; + + ensure!(cv_signature == 0x53445352, "Invalid CV signature"); + + Ok(Self { + cv_signature, + signature, + age, + file_name, + }) + } + + /// Parse a CV 7.0 header from a given address with a DTB + pub fn new_dtb( + processor: *mut ConfObject, + directory_table_base: u64, + address: u64, + ) -> Result { + let cv_signature = read_virtual_dtb::(processor, directory_table_base, address)?; + let signature = read_virtual_dtb::( + processor, + directory_table_base, + address + std::mem::size_of::() as u64, + )?; + let age = read_virtual_dtb::( + processor, + directory_table_base, + address + std::mem::size_of::() as u64 + std::mem::size_of::() as u64, + )?; + let file_name = read_nul_terminated_string_dtb( + processor, + directory_table_base, + address + + std::mem::size_of::() as u64 + + std::mem::size_of::() as u64 + + std::mem::size_of::() as u64, + )?; + + ensure!(cv_signature == 0x53445352, "Invalid CV signature"); + + Ok(Self { + cv_signature, + signature, + age, + file_name, + }) + } + + pub fn guid(&self) -> String { + // Reverse the order of data3 + let data3 = u64::from_be_bytes(self.signature.data3.to_le_bytes()); + + format!( + "{:08X}{:04X}{:04X}{:016X}{:01X}", + self.signature.data0, self.signature.data1, self.signature.data2, data3, self.age + ) + } + + pub fn file_name(&self) -> &str { + &self.file_name + } +} + +#[derive(Debug, Clone)] +/// An export from a PE file +pub struct Export { + pub name: Option, + pub offset: Option, + pub rva: usize, + pub size: usize, +} + +impl From> for Export { + fn from(export: goblin::pe::export::Export) -> Self { + Self { + name: export.name.map(|s| s.to_string()), + offset: export.offset, + rva: export.rva, + size: export.size, + } + } +} + +impl From<&goblin::pe::export::Export<'_>> for Export { + fn from(export: &goblin::pe::export::Export) -> Self { + Self { + name: export.name.map(|s| s.to_string()), + offset: export.offset, + rva: export.rva, + size: export.size, + } + } +} diff --git a/src/os/windows/structs.rs b/src/os/windows/structs.rs new file mode 100644 index 00000000..31dfcaa1 --- /dev/null +++ b/src/os/windows/structs.rs @@ -0,0 +1,3080 @@ +use std::{ + cmp::max, + collections::{HashMap, HashSet}, + path::{Path, PathBuf}, +}; + +use anyhow::{anyhow, bail, ensure, Result}; +use raw_cstr::AsRawCstr; +use simics::{ + debug, get_attribute, get_interface, get_object, info, ConfObject, IntRegisterInterface, +}; +use vergilius::bindings::*; +use windows_sys::Win32::{Foundation::UNICODE_STRING, System::Kernel::LIST_ENTRY}; + +use crate::os::{ + windows::{debug_info::DebugInfo, util::read_virtual}, + DebugInfoConfig, +}; + +use super::{ + debug_info::ProcessModule, + util::{read_unicode_string, read_unicode_string_dtb, read_virtual_dtb}, +}; + +pub enum WindowsKpcr { + Windows10_0_10240_16384 { + kpcr: windows_10_0_10240_16384_x64::_KPCR, + }, + Windows10_0_10586_0 { + kpcr: windows_10_0_10586_0_x64::_KPCR, + }, + Windows10_0_14393_0 { + kpcr: windows_10_0_14393_0_x64::_KPCR, + }, + Windows10_0_15063_0 { + kpcr: windows_10_0_15063_0_x64::_KPCR, + }, + Windows10_0_16299_15 { + kpcr: windows_10_0_16299_15_x64::_KPCR, + }, + Windows10_0_17134_1 { + kpcr: windows_10_0_17134_1_x64::_KPCR, + }, + Windows10_0_17763_107 { + kpcr: windows_10_0_17763_107_x64::_KPCR, + }, + Windows10_0_18362_418 { + kpcr: windows_10_0_18362_418_x64::_KPCR, + }, + Windows10_0_19041_1288 { + kpcr: windows_10_0_19041_1288_x64::_KPCR, + }, + Windows10_0_19045_2965 { + kpcr: windows_10_0_19045_2965_x64::_KPCR, + }, + Windows10_0_22000_194 { + kpcr: windows_10_0_22000_194_x64::_KPCR, + }, + Windows10_0_22621_382 { + kpcr: windows_10_0_22621_382_x64::_KPCR, + }, + Windows10_0_22631_2428 { + kpcr: windows_10_0_22631_2428_x64::_KPCR, + }, +} + +impl WindowsKpcr { + pub fn new(processor: *mut ConfObject, maj: u32, min: u32, build: u32) -> Result { + let mut int_register = get_interface::(processor)?; + let ia32_kernel_gs_base_nr = + int_register.get_number("ia32_kernel_gs_base".as_raw_cstr()?)?; + let ia32_gs_base_nr = int_register.get_number("ia32_gs_base".as_raw_cstr()?)?; + let ia32_kernel_gs_base = int_register.read(ia32_kernel_gs_base_nr)?; + let ia32_gs_base = int_register.read(ia32_gs_base_nr)?; + let sim_idtr_base: u64 = get_attribute(processor, "idtr_base")?.try_into()?; + + let kpcr_address = max(ia32_gs_base, ia32_kernel_gs_base); + + match (maj, min, build) { + (10, 0, 10240) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_10240_16384 { kpcr }) + } + (10, 0, 10586) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_10586_0 { kpcr }) + } + (10, 0, 14393) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_14393_0 { kpcr }) + } + (10, 0, 15063) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_15063_0 { kpcr }) + } + (10, 0, 16299) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_16299_15 { kpcr }) + } + (10, 0, 17134) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_17134_1 { kpcr }) + } + (10, 0, 17763) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_17763_107 { kpcr }) + } + (10, 0, 18362) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_18362_418 { kpcr }) + } + (10, 0, 19041) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_19041_1288 { kpcr }) + } + (10, 0, 19045) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_19045_2965 { kpcr }) + } + (10, 0, 22000) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_22000_194 { kpcr }) + } + (10, 0, 22621) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_22621_382 { kpcr }) + } + (10, 0, 22631) => { + let kpcr = + read_virtual::(processor, kpcr_address)?; + ensure!( + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.Self_ + == kpcr_address as *mut _, + "Invalid KPCR: Self != KPCR address" + ); + ensure!( + kpcr.IdtBase == sim_idtr_base as *mut _, + "Invalid KPCR: IdtBase != IDTR base" + ); + + Ok(WindowsKpcr::Windows10_0_22631_2428 { kpcr }) + } + (_, _, _) => bail!("Unsupported Windows version"), + } + } + + pub fn kpcrb_address(&self) -> u64 { + match self { + WindowsKpcr::Windows10_0_10240_16384 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_10586_0 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_14393_0 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_15063_0 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_16299_15 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_17134_1 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_17763_107 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_18362_418 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_19041_1288 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_19045_2965 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_22000_194 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_22621_382 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + WindowsKpcr::Windows10_0_22631_2428 { kpcr } => { + unsafe { kpcr.__bindgen_anon_1.__bindgen_anon_1 }.CurrentPrcb as u64 + } + } + } +} + +pub enum WindowsKprcb { + Windows10_0_10240_16384 { + kprcb: windows_10_0_10240_16384_x64::_KPRCB, + }, + Windows10_0_10586_0 { + kprcb: windows_10_0_10586_0_x64::_KPRCB, + }, + Windows10_0_14393_0 { + kprcb: windows_10_0_14393_0_x64::_KPRCB, + }, + Windows10_0_15063_0 { + kprcb: windows_10_0_15063_0_x64::_KPRCB, + }, + Windows10_0_16299_15 { + kprcb: windows_10_0_16299_15_x64::_KPRCB, + }, + Windows10_0_17134_1 { + kprcb: windows_10_0_17134_1_x64::_KPRCB, + }, + Windows10_0_17763_107 { + kprcb: windows_10_0_17763_107_x64::_KPRCB, + }, + Windows10_0_18362_418 { + kprcb: windows_10_0_18362_418_x64::_KPRCB, + }, + Windows10_0_19041_1288 { + kprcb: windows_10_0_19041_1288_x64::_KPRCB, + }, + Windows10_0_19045_2965 { + kprcb: windows_10_0_19045_2965_x64::_KPRCB, + }, + Windows10_0_22000_194 { + kprcb: windows_10_0_22000_194_x64::_KPRCB, + }, + Windows10_0_22621_382 { + kprcb: windows_10_0_22621_382_x64::_KPRCB, + }, + Windows10_0_22631_2428 { + kprcb: windows_10_0_22631_2428_x64::_KPRCB, + }, +} + +impl WindowsKprcb { + pub fn new( + processor: *mut ConfObject, + maj: u32, + min: u32, + build: u32, + kpcrb_address: u64, + ) -> Result { + match (maj, min, build) { + (10, 0, 10240) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_10240_16384 { kprcb }) + } + (10, 0, 10586) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_10586_0 { kprcb }) + } + (10, 0, 14393) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_14393_0 { kprcb }) + } + (10, 0, 15063) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_15063_0 { kprcb }) + } + (10, 0, 16299) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_16299_15 { kprcb }) + } + (10, 0, 17134) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_17134_1 { kprcb }) + } + (10, 0, 17763) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_17763_107 { kprcb }) + } + (10, 0, 18362) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_18362_418 { kprcb }) + } + (10, 0, 19041) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_19041_1288 { kprcb }) + } + (10, 0, 19045) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_19045_2965 { kprcb }) + } + (10, 0, 22000) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_22000_194 { kprcb }) + } + (10, 0, 22621) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_22621_382 { kprcb }) + } + (10, 0, 22631) => { + let kprcb = + read_virtual::(processor, kpcrb_address)?; + + Ok(WindowsKprcb::Windows10_0_22631_2428 { kprcb }) + } + (_, _, _) => bail!("Unsupported Windows version"), + } + } + + pub fn current_thread(&self) -> u64 { + match self { + WindowsKprcb::Windows10_0_10240_16384 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_10586_0 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_14393_0 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_15063_0 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_16299_15 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_17134_1 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_17763_107 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_18362_418 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_19041_1288 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_19045_2965 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_22000_194 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_22621_382 { kprcb } => kprcb.CurrentThread as u64, + WindowsKprcb::Windows10_0_22631_2428 { kprcb } => kprcb.CurrentThread as u64, + } + } +} + +pub enum WindowsLdrDataTableEntry { + Windows10_0_10240_16384 { + ldr_data_table_entry: windows_10_0_10240_16384_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_10586_0 { + ldr_data_table_entry: windows_10_0_10586_0_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_14393_0 { + ldr_data_table_entry: windows_10_0_14393_0_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_15063_0 { + ldr_data_table_entry: windows_10_0_15063_0_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_16299_15 { + ldr_data_table_entry: windows_10_0_16299_15_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_17134_1 { + ldr_data_table_entry: windows_10_0_17134_1_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_17763_107 { + ldr_data_table_entry: windows_10_0_17763_107_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_18362_418 { + ldr_data_table_entry: windows_10_0_18362_418_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_19041_1288 { + ldr_data_table_entry: windows_10_0_19041_1288_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_19045_2965 { + ldr_data_table_entry: windows_10_0_19045_2965_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_22000_194 { + ldr_data_table_entry: windows_10_0_22000_194_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_22621_382 { + ldr_data_table_entry: windows_10_0_22621_382_x64::_LDR_DATA_TABLE_ENTRY, + }, + Windows10_0_22631_2428 { + ldr_data_table_entry: windows_10_0_22631_2428_x64::_LDR_DATA_TABLE_ENTRY, + }, +} + +impl WindowsLdrDataTableEntry { + pub fn new( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + ldr_data_table_entry_address: u64, + ) -> Result { + match (major, minor, build) { + (10, 0, 10240) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_10240_16384_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_10240_16384 { + ldr_data_table_entry, + }) + } + (10, 0, 10586) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_10586_0_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_10586_0 { + ldr_data_table_entry, + }) + } + (10, 0, 14393) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_14393_0_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_14393_0 { + ldr_data_table_entry, + }) + } + (10, 0, 15063) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_15063_0_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_15063_0 { + ldr_data_table_entry, + }) + } + (10, 0, 16299) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_16299_15_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_16299_15 { + ldr_data_table_entry, + }) + } + (10, 0, 17134) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_17134_1_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_17134_1 { + ldr_data_table_entry, + }) + } + (10, 0, 17763) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_17763_107_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_17763_107 { + ldr_data_table_entry, + }) + } + (10, 0, 18362) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_18362_418_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_18362_418 { + ldr_data_table_entry, + }) + } + (10, 0, 19041) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_19041_1288_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_19041_1288 { + ldr_data_table_entry, + }) + } + (10, 0, 19045) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_19045_2965_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_19045_2965 { + ldr_data_table_entry, + }) + } + (10, 0, 22000) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_22000_194_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_22000_194 { + ldr_data_table_entry, + }) + } + (10, 0, 22621) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_22621_382_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_22621_382 { + ldr_data_table_entry, + }) + } + (10, 0, 22631) => { + let ldr_data_table_entry = read_virtual::< + windows_10_0_22631_2428_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, ldr_data_table_entry_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_22631_2428 { + ldr_data_table_entry, + }) + } + (_, _, _) => bail!("Unsupported Windows version"), + } + } + + pub fn new_dtb( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + directory_table_base: u64, + virtual_address: u64, + ) -> Result { + match (major, minor, build) { + (10, 0, 10240) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_10240_16384_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_10240_16384 { + ldr_data_table_entry, + }) + } + (10, 0, 10586) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_10586_0_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_10586_0 { + ldr_data_table_entry, + }) + } + (10, 0, 14393) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_14393_0_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_14393_0 { + ldr_data_table_entry, + }) + } + (10, 0, 15063) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_15063_0_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_15063_0 { + ldr_data_table_entry, + }) + } + (10, 0, 16299) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_16299_15_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_16299_15 { + ldr_data_table_entry, + }) + } + (10, 0, 17134) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_17134_1_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_17134_1 { + ldr_data_table_entry, + }) + } + (10, 0, 17763) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_17763_107_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_17763_107 { + ldr_data_table_entry, + }) + } + (10, 0, 18362) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_18362_418_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_18362_418 { + ldr_data_table_entry, + }) + } + (10, 0, 19041) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_19041_1288_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_19041_1288 { + ldr_data_table_entry, + }) + } + (10, 0, 19045) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_19045_2965_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_19045_2965 { + ldr_data_table_entry, + }) + } + (10, 0, 22000) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_22000_194_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_22000_194 { + ldr_data_table_entry, + }) + } + (10, 0, 22621) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_22621_382_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_22621_382 { + ldr_data_table_entry, + }) + } + (10, 0, 22631) => { + let ldr_data_table_entry = read_virtual_dtb::< + windows_10_0_22631_2428_x64::_LDR_DATA_TABLE_ENTRY, + >( + processor, directory_table_base, virtual_address + )?; + Ok(WindowsLdrDataTableEntry::Windows10_0_22631_2428 { + ldr_data_table_entry, + }) + } + (_, _, _) => bail!("Unsupported Windows version"), + } + } + + pub fn new_from_in_memory_order_links( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + in_memory_order_links_address: u64, + ) -> Result { + let in_memory_order_links_offset = match (major, minor, build) { + (10, 0, 10240) => { + std::mem::offset_of!( + windows_10_0_10240_16384_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 10586) => { + std::mem::offset_of!( + windows_10_0_10586_0_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 14393) => { + std::mem::offset_of!( + windows_10_0_14393_0_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 15063) => { + std::mem::offset_of!( + windows_10_0_15063_0_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 16299) => { + std::mem::offset_of!( + windows_10_0_16299_15_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 17134) => { + std::mem::offset_of!( + windows_10_0_17134_1_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 17763) => { + std::mem::offset_of!( + windows_10_0_17763_107_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 18362) => { + std::mem::offset_of!( + windows_10_0_18362_418_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 19041) => { + std::mem::offset_of!( + windows_10_0_19041_1288_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 19045) => { + std::mem::offset_of!( + windows_10_0_19045_2965_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 22000) => { + std::mem::offset_of!( + windows_10_0_22000_194_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 22621) => { + std::mem::offset_of!( + windows_10_0_22621_382_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (10, 0, 22631) => { + std::mem::offset_of!( + windows_10_0_22631_2428_x64::_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks + ) + } + (_, _, _) => bail!("Unsupported Windows version"), + }; + + let ldr_data_table_entry_address = + in_memory_order_links_address - in_memory_order_links_offset as u64; + + Self::new(processor, major, minor, build, ldr_data_table_entry_address) + } + + pub fn dll_base(&self) -> u64 { + match self { + WindowsLdrDataTableEntry::Windows10_0_10240_16384 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_10586_0 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_14393_0 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_15063_0 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_16299_15 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_17134_1 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_17763_107 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_18362_418 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_19041_1288 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_19045_2965 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_22000_194 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_22621_382 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + WindowsLdrDataTableEntry::Windows10_0_22631_2428 { + ldr_data_table_entry, + } => ldr_data_table_entry.DllBase as u64, + } + } + + pub fn entry_point(&self) -> u64 { + match self { + WindowsLdrDataTableEntry::Windows10_0_10240_16384 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_10586_0 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_14393_0 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_15063_0 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_16299_15 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_17134_1 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_17763_107 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_18362_418 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_19041_1288 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_19045_2965 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_22000_194 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_22621_382 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + WindowsLdrDataTableEntry::Windows10_0_22631_2428 { + ldr_data_table_entry, + } => ldr_data_table_entry.EntryPoint as u64, + } + } + + pub fn size_of_image(&self) -> u64 { + match self { + WindowsLdrDataTableEntry::Windows10_0_10240_16384 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_10586_0 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_14393_0 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_15063_0 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_16299_15 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_17134_1 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_17763_107 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_18362_418 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_19041_1288 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_19045_2965 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_22000_194 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_22621_382 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + WindowsLdrDataTableEntry::Windows10_0_22631_2428 { + ldr_data_table_entry, + } => ldr_data_table_entry.SizeOfImage as u64, + } + } + + pub fn full_name(&self, processor: *mut ConfObject) -> Result { + match self { + WindowsLdrDataTableEntry::Windows10_0_10240_16384 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_10586_0 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_14393_0 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_15063_0 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_16299_15 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_17134_1 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_17763_107 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_18362_418 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_19041_1288 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_19045_2965 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_22000_194 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_22621_382 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_22631_2428 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + ), + } + } + + pub fn full_name_dtb( + &self, + processor: *mut ConfObject, + directory_table_base: u64, + ) -> Result { + match self { + WindowsLdrDataTableEntry::Windows10_0_10240_16384 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_10586_0 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_14393_0 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_15063_0 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_16299_15 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_17134_1 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_17763_107 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_18362_418 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_19041_1288 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_19045_2965 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_22000_194 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_22621_382 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_22631_2428 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.FullDllName.Length as usize, + ldr_data_table_entry.FullDllName.Buffer, + directory_table_base, + ), + } + } + + pub fn base_name(&self, processor: *mut ConfObject) -> Result { + match self { + WindowsLdrDataTableEntry::Windows10_0_10240_16384 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_10586_0 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_14393_0 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_15063_0 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_16299_15 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_17134_1 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_17763_107 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_18362_418 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_19041_1288 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_19045_2965 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_22000_194 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_22621_382 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + WindowsLdrDataTableEntry::Windows10_0_22631_2428 { + ldr_data_table_entry, + } => read_unicode_string( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + ), + } + } + + pub fn base_name_dtb( + &self, + processor: *mut ConfObject, + directory_table_base: u64, + ) -> Result { + match self { + WindowsLdrDataTableEntry::Windows10_0_10240_16384 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_10586_0 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_14393_0 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_15063_0 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_16299_15 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_17134_1 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_17763_107 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_18362_418 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_19041_1288 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_19045_2965 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_22000_194 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_22621_382 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + WindowsLdrDataTableEntry::Windows10_0_22631_2428 { + ldr_data_table_entry, + } => read_unicode_string_dtb( + processor, + ldr_data_table_entry.BaseDllName.Length as usize, + ldr_data_table_entry.BaseDllName.Buffer, + directory_table_base, + ), + } + } + + pub fn in_load_order_links(&self) -> LIST_ENTRY { + match self { + WindowsLdrDataTableEntry::Windows10_0_10240_16384 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_10240_16384_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_10586_0 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_10586_0_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_14393_0 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_14393_0_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_15063_0 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_15063_0_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_16299_15 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_16299_15_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_17134_1 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_17134_1_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_17763_107 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_17763_107_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_18362_418 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_18362_418_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_19041_1288 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_19041_1288_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_19045_2965 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_19045_2965_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_22000_194 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_22000_194_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_22621_382 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_22621_382_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + WindowsLdrDataTableEntry::Windows10_0_22631_2428 { + ldr_data_table_entry, + } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_22631_2428_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data_table_entry.InLoadOrderLinks) + }, + } + } +} + +pub enum WindowsPebLdrData { + Windows10_0_10240_16384 { + ldr_data: windows_10_0_10240_16384_x64::_PEB_LDR_DATA, + }, + Windows10_0_10586_0 { + ldr_data: windows_10_0_10586_0_x64::_PEB_LDR_DATA, + }, + Windows10_0_14393_0 { + ldr_data: windows_10_0_14393_0_x64::_PEB_LDR_DATA, + }, + Windows10_0_15063_0 { + ldr_data: windows_10_0_15063_0_x64::_PEB_LDR_DATA, + }, + Windows10_0_16299_15 { + ldr_data: windows_10_0_16299_15_x64::_PEB_LDR_DATA, + }, + Windows10_0_17134_1 { + ldr_data: windows_10_0_17134_1_x64::_PEB_LDR_DATA, + }, + Windows10_0_17763_107 { + ldr_data: windows_10_0_17763_107_x64::_PEB_LDR_DATA, + }, + Windows10_0_18362_418 { + ldr_data: windows_10_0_18362_418_x64::_PEB_LDR_DATA, + }, + Windows10_0_19041_1288 { + ldr_data: windows_10_0_19041_1288_x64::_PEB_LDR_DATA, + }, + Windows10_0_19045_2965 { + ldr_data: windows_10_0_19045_2965_x64::_PEB_LDR_DATA, + }, + Windows10_0_22000_194 { + ldr_data: windows_10_0_22000_194_x64::_PEB_LDR_DATA, + }, + Windows10_0_22621_382 { + ldr_data: windows_10_0_22621_382_x64::_PEB_LDR_DATA, + }, + Windows10_0_22631_2428 { + ldr_data: windows_10_0_22631_2428_x64::_PEB_LDR_DATA, + }, +} + +impl WindowsPebLdrData { + pub fn new( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + ldr_data_address: u64, + ) -> Result { + match (major, minor, build) { + (10, 0, 10240) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_10240_16384 { ldr_data }) + } + (10, 0, 10586) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_10586_0 { ldr_data }) + } + (10, 0, 14393) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_14393_0 { ldr_data }) + } + (10, 0, 15063) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_15063_0 { ldr_data }) + } + (10, 0, 16299) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_16299_15 { ldr_data }) + } + (10, 0, 17134) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_17134_1 { ldr_data }) + } + (10, 0, 17763) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_17763_107 { ldr_data }) + } + (10, 0, 18362) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_18362_418 { ldr_data }) + } + (10, 0, 19041) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_19041_1288 { ldr_data }) + } + (10, 0, 19045) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_19045_2965 { ldr_data }) + } + (10, 0, 22000) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_22000_194 { ldr_data }) + } + (10, 0, 22621) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_22621_382 { ldr_data }) + } + (10, 0, 22631) => { + let ldr_data = read_virtual::( + processor, + ldr_data_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_22631_2428 { ldr_data }) + } + (_, _, _) => bail!("Unsupported Windows version"), + } + } + + pub fn new_dtb( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + directory_table_base: u64, + virtual_address: u64, + ) -> Result { + match (major, minor, build) { + (10, 0, 10240) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_10240_16384 { ldr_data }) + } + (10, 0, 10586) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_10586_0 { ldr_data }) + } + (10, 0, 14393) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_14393_0 { ldr_data }) + } + (10, 0, 15063) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_15063_0 { ldr_data }) + } + (10, 0, 16299) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_16299_15 { ldr_data }) + } + (10, 0, 17134) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_17134_1 { ldr_data }) + } + (10, 0, 17763) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_17763_107 { ldr_data }) + } + (10, 0, 18362) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_18362_418 { ldr_data }) + } + (10, 0, 19041) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_19041_1288 { ldr_data }) + } + (10, 0, 19045) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_19045_2965 { ldr_data }) + } + (10, 0, 22000) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_22000_194 { ldr_data }) + } + (10, 0, 22621) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_22621_382 { ldr_data }) + } + (10, 0, 22631) => { + let ldr_data = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPebLdrData::Windows10_0_22631_2428 { ldr_data }) + } + (_, _, _) => bail!("Unsupported Windows version"), + } + } + + pub fn length(&self) -> usize { + match self { + WindowsPebLdrData::Windows10_0_10240_16384 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_10586_0 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_14393_0 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_15063_0 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_16299_15 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_17134_1 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_17763_107 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_18362_418 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_19041_1288 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_19045_2965 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_22000_194 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_22621_382 { ldr_data } => ldr_data.Length as usize, + WindowsPebLdrData::Windows10_0_22631_2428 { ldr_data } => ldr_data.Length as usize, + } + } + + pub fn in_load_order_module_list(&self) -> LIST_ENTRY { + match self { + WindowsPebLdrData::Windows10_0_10240_16384 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_10240_16384_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_10586_0 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_10586_0_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_14393_0 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_14393_0_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_15063_0 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_15063_0_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_16299_15 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_16299_15_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_17134_1 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_17134_1_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_17763_107 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_17763_107_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_18362_418 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_18362_418_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_19041_1288 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_19041_1288_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_19045_2965 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_19045_2965_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_22000_194 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_22000_194_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_22621_382 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_22621_382_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + WindowsPebLdrData::Windows10_0_22631_2428 { ldr_data } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_22631_2428_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(ldr_data.InLoadOrderModuleList) + }, + } + } +} + +pub enum WindowsPeb { + Windows10_0_10240_16384 { + peb: windows_10_0_10240_16384_x64::_PEB, + }, + Windows10_0_10586_0 { + peb: windows_10_0_10586_0_x64::_PEB, + }, + Windows10_0_14393_0 { + peb: windows_10_0_14393_0_x64::_PEB, + }, + Windows10_0_15063_0 { + peb: windows_10_0_15063_0_x64::_PEB, + }, + Windows10_0_16299_15 { + peb: windows_10_0_16299_15_x64::_PEB, + }, + Windows10_0_17134_1 { + peb: windows_10_0_17134_1_x64::_PEB, + }, + Windows10_0_17763_107 { + peb: windows_10_0_17763_107_x64::_PEB, + }, + Windows10_0_18362_418 { + peb: windows_10_0_18362_418_x64::_PEB, + }, + Windows10_0_19041_1288 { + peb: windows_10_0_19041_1288_x64::_PEB, + }, + Windows10_0_19045_2965 { + peb: windows_10_0_19045_2965_x64::_PEB, + }, + Windows10_0_22000_194 { + peb: windows_10_0_22000_194_x64::_PEB, + }, + Windows10_0_22621_382 { + peb: windows_10_0_22621_382_x64::_PEB, + }, + Windows10_0_22631_2428 { + peb: windows_10_0_22631_2428_x64::_PEB, + }, +} + +impl WindowsPeb { + pub fn new( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + peb_address: u64, + ) -> Result { + match (major, minor, build) { + (10, 0, 10240) => { + let peb = + read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_10240_16384 { peb }) + } + (10, 0, 10586) => { + let peb = read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_10586_0 { peb }) + } + (10, 0, 14393) => { + let peb = read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_14393_0 { peb }) + } + (10, 0, 15063) => { + let peb = read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_15063_0 { peb }) + } + (10, 0, 16299) => { + let peb = read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_16299_15 { peb }) + } + (10, 0, 17134) => { + let peb = read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_17134_1 { peb }) + } + (10, 0, 17763) => { + let peb = read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_17763_107 { peb }) + } + (10, 0, 18362) => { + let peb = read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_18362_418 { peb }) + } + (10, 0, 19041) => { + let peb = + read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_19041_1288 { peb }) + } + (10, 0, 19045) => { + let peb = + read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_19045_2965 { peb }) + } + (10, 0, 22000) => { + let peb = read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_22000_194 { peb }) + } + (10, 0, 22621) => { + let peb = read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_22621_382 { peb }) + } + (10, 0, 22631) => { + let peb = + read_virtual::(processor, peb_address)?; + Ok(WindowsPeb::Windows10_0_22631_2428 { peb }) + } + (_, _, _) => { + bail!("Unsupported Windows version") + } + } + } + + pub fn new_dtb( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + directory_table_base: u64, + virtual_address: u64, + ) -> Result { + match (major, minor, build) { + (10, 0, 10240) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_10240_16384 { peb }) + } + (10, 0, 10586) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_10586_0 { peb }) + } + (10, 0, 14393) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_14393_0 { peb }) + } + (10, 0, 15063) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_15063_0 { peb }) + } + (10, 0, 16299) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_16299_15 { peb }) + } + (10, 0, 17134) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_17134_1 { peb }) + } + (10, 0, 17763) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_17763_107 { peb }) + } + (10, 0, 18362) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_18362_418 { peb }) + } + (10, 0, 19041) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_19041_1288 { peb }) + } + (10, 0, 19045) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_19045_2965 { peb }) + } + (10, 0, 22000) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_22000_194 { peb }) + } + (10, 0, 22621) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_22621_382 { peb }) + } + (10, 0, 22631) => { + let peb = read_virtual_dtb::( + processor, + directory_table_base, + virtual_address, + )?; + Ok(WindowsPeb::Windows10_0_22631_2428 { peb }) + } + (_, _, _) => { + bail!("Unsupported Windows version") + } + } + } + + pub fn base(&self) -> u64 { + match self { + WindowsPeb::Windows10_0_10240_16384 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_10586_0 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_14393_0 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_15063_0 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_16299_15 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_17134_1 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_17763_107 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_18362_418 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_19041_1288 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_19045_2965 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_22000_194 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_22621_382 { peb } => peb.ImageBaseAddress as u64, + WindowsPeb::Windows10_0_22631_2428 { peb } => peb.ImageBaseAddress as u64, + } + } + + pub fn ldr_address(&self) -> u64 { + match self { + WindowsPeb::Windows10_0_10240_16384 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_10586_0 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_14393_0 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_15063_0 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_16299_15 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_17134_1 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_17763_107 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_18362_418 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_19041_1288 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_19045_2965 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_22000_194 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_22621_382 { peb } => peb.Ldr as u64, + WindowsPeb::Windows10_0_22631_2428 { peb } => peb.Ldr as u64, + } + } +} + +pub enum WindowsTeb { + Windows10_0_10240_16384 { + teb: windows_10_0_10240_16384_x64::_TEB, + }, + Windows10_0_10586_0 { + teb: windows_10_0_10586_0_x64::_TEB, + }, + Windows10_0_14393_0 { + teb: windows_10_0_14393_0_x64::_TEB, + }, + Windows10_0_15063_0 { + teb: windows_10_0_15063_0_x64::_TEB, + }, + Windows10_0_16299_15 { + teb: windows_10_0_16299_15_x64::_TEB, + }, + Windows10_0_17134_1 { + teb: windows_10_0_17134_1_x64::_TEB, + }, + Windows10_0_17763_107 { + teb: windows_10_0_17763_107_x64::_TEB, + }, + Windows10_0_18362_418 { + teb: windows_10_0_18362_418_x64::_TEB, + }, + Windows10_0_19041_1288 { + teb: windows_10_0_19041_1288_x64::_TEB, + }, + Windows10_0_19045_2965 { + teb: windows_10_0_19045_2965_x64::_TEB, + }, + Windows10_0_22000_194 { + teb: windows_10_0_22000_194_x64::_TEB, + }, + Windows10_0_22621_382 { + teb: windows_10_0_22621_382_x64::_TEB, + }, + Windows10_0_22631_2428 { + teb: windows_10_0_22631_2428_x64::_TEB, + }, +} + +impl WindowsTeb { + pub fn new( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + teb_address: u64, + ) -> Result { + match (major, minor, build) { + (10, 0, 10240) => { + let teb = + read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_10240_16384 { teb }) + } + (10, 0, 10586) => { + let teb = read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_10586_0 { teb }) + } + (10, 0, 14393) => { + let teb = read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_14393_0 { teb }) + } + (10, 0, 15063) => { + let teb = read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_15063_0 { teb }) + } + (10, 0, 16299) => { + let teb = read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_16299_15 { teb }) + } + (10, 0, 17134) => { + let teb = read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_17134_1 { teb }) + } + (10, 0, 17763) => { + let teb = read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_17763_107 { teb }) + } + (10, 0, 18362) => { + let teb = read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_18362_418 { teb }) + } + (10, 0, 19041) => { + let teb = + read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_19041_1288 { teb }) + } + (10, 0, 19045) => { + let teb = + read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_19045_2965 { teb }) + } + (10, 0, 22000) => { + let teb = read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_22000_194 { teb }) + } + (10, 0, 22621) => { + let teb = read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_22621_382 { teb }) + } + (10, 0, 22631) => { + let teb = + read_virtual::(processor, teb_address)?; + Ok(WindowsTeb::Windows10_0_22631_2428 { teb }) + } + (_, _, _) => { + bail!("Unsupported Windows version") + } + } + } + + pub fn peb( + &self, + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + ) -> Result { + let peb_address = match self { + WindowsTeb::Windows10_0_10240_16384 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_10586_0 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_14393_0 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_15063_0 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_16299_15 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_17134_1 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_17763_107 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_18362_418 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_19041_1288 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_19045_2965 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_22000_194 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_22621_382 { teb } => teb.ProcessEnvironmentBlock as u64, + WindowsTeb::Windows10_0_22631_2428 { teb } => teb.ProcessEnvironmentBlock as u64, + }; + WindowsPeb::new(processor, major, minor, build, peb_address) + } +} + +pub enum WindowsEProcess { + Windows10_0_10240_16384 { + eprocess: windows_10_0_10240_16384_x64::_EPROCESS, + }, + Windows10_0_10586_0 { + eprocess: windows_10_0_10586_0_x64::_EPROCESS, + }, + Windows10_0_14393_0 { + eprocess: windows_10_0_14393_0_x64::_EPROCESS, + }, + Windows10_0_15063_0 { + eprocess: windows_10_0_15063_0_x64::_EPROCESS, + }, + Windows10_0_16299_15 { + eprocess: windows_10_0_16299_15_x64::_EPROCESS, + }, + Windows10_0_17134_1 { + eprocess: windows_10_0_17134_1_x64::_EPROCESS, + }, + Windows10_0_17763_107 { + eprocess: windows_10_0_17763_107_x64::_EPROCESS, + }, + Windows10_0_18362_418 { + eprocess: windows_10_0_18362_418_x64::_EPROCESS, + }, + Windows10_0_19041_1288 { + eprocess: windows_10_0_19041_1288_x64::_EPROCESS, + }, + Windows10_0_19045_2965 { + eprocess: windows_10_0_19045_2965_x64::_EPROCESS, + }, + Windows10_0_22000_194 { + eprocess: windows_10_0_22000_194_x64::_EPROCESS, + }, + Windows10_0_22621_382 { + eprocess: windows_10_0_22621_382_x64::_EPROCESS, + }, + Windows10_0_22631_2428 { + eprocess: windows_10_0_22631_2428_x64::_EPROCESS, + }, +} + +impl WindowsEProcess { + pub fn new( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + eprocess_address: u64, + ) -> Result { + match (major, minor, build) { + (10, 0, 10240) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_10240_16384 { eprocess }) + } + (10, 0, 10586) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_10586_0 { eprocess }) + } + (10, 0, 14393) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_14393_0 { eprocess }) + } + (10, 0, 15063) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_15063_0 { eprocess }) + } + (10, 0, 16299) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_16299_15 { eprocess }) + } + (10, 0, 17134) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_17134_1 { eprocess }) + } + (10, 0, 17763) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_17763_107 { eprocess }) + } + (10, 0, 18362) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_18362_418 { eprocess }) + } + (10, 0, 19041) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_19041_1288 { eprocess }) + } + (10, 0, 19045) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_19045_2965 { eprocess }) + } + (10, 0, 22000) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_22000_194 { eprocess }) + } + (10, 0, 22621) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_22621_382 { eprocess }) + } + (10, 0, 22631) => { + let eprocess = read_virtual::( + processor, + eprocess_address, + )?; + Ok(WindowsEProcess::Windows10_0_22631_2428 { eprocess }) + } + (_, _, _) => { + bail!("Unsupported Windows version") + } + } + } + + pub fn new_from_active_process_links_address( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + active_process_links_address: u64, + ) -> Result { + let active_process_links_offset = match (major, minor, build) { + (10, 0, 10240) => { + std::mem::offset_of!(windows_10_0_10240_16384_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 10586) => { + std::mem::offset_of!(windows_10_0_10586_0_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 14393) => { + std::mem::offset_of!(windows_10_0_14393_0_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 15063) => { + std::mem::offset_of!(windows_10_0_15063_0_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 16299) => { + std::mem::offset_of!(windows_10_0_16299_15_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 17134) => { + std::mem::offset_of!(windows_10_0_17134_1_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 17763) => { + std::mem::offset_of!(windows_10_0_17763_107_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 18362) => { + std::mem::offset_of!(windows_10_0_18362_418_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 19041) => { + std::mem::offset_of!(windows_10_0_19041_1288_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 19045) => { + std::mem::offset_of!(windows_10_0_19045_2965_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 22000) => { + std::mem::offset_of!(windows_10_0_22000_194_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 22621) => { + std::mem::offset_of!(windows_10_0_22621_382_x64::_EPROCESS, ActiveProcessLinks) + } + (10, 0, 22631) => { + std::mem::offset_of!(windows_10_0_22631_2428_x64::_EPROCESS, ActiveProcessLinks) + } + (_, _, _) => { + bail!("Unsupported Windows version") + } + }; + let eprocess_address = active_process_links_address - active_process_links_offset as u64; + + Self::new(processor, major, minor, build, eprocess_address) + } + + pub fn active_process_links(&self) -> LIST_ENTRY { + match self { + WindowsEProcess::Windows10_0_10240_16384 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_10240_16384_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_10586_0 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_10586_0_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_14393_0 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_14393_0_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_15063_0 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_15063_0_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_16299_15 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_16299_15_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_17134_1 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_17134_1_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_17763_107 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_17763_107_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_18362_418 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_18362_418_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_19041_1288 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_19041_1288_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_19045_2965 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_19045_2965_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_22000_194 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_22000_194_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_22621_382 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_22621_382_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + WindowsEProcess::Windows10_0_22631_2428 { eprocess } => unsafe { + std::mem::transmute::< + vergilius::windows_10_0_22631_2428_x64::_LIST_ENTRY, + windows_sys::Win32::System::Kernel::LIST_ENTRY, + >(eprocess.ActiveProcessLinks) + }, + } + } + + pub fn pid(&self) -> u64 { + match self { + WindowsEProcess::Windows10_0_10240_16384 { eprocess } => { + eprocess.UniqueProcessId as u64 + } + WindowsEProcess::Windows10_0_10586_0 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_14393_0 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_15063_0 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_16299_15 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_17134_1 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_17763_107 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_18362_418 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_19041_1288 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_19045_2965 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_22000_194 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_22621_382 { eprocess } => eprocess.UniqueProcessId as u64, + WindowsEProcess::Windows10_0_22631_2428 { eprocess } => eprocess.UniqueProcessId as u64, + } + } + + pub fn file_name(&self, processor: *mut ConfObject) -> Result { + // 1. Read _EPROCESS.SeAuditProcessCreationInfo.ImageFileName + let object_name_information_addr = match self { + WindowsEProcess::Windows10_0_10240_16384 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_10586_0 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_14393_0 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_15063_0 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_16299_15 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_17134_1 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_17763_107 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_18362_418 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_19041_1288 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_19045_2965 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_22000_194 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_22621_382 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + WindowsEProcess::Windows10_0_22631_2428 { eprocess } => { + eprocess.SeAuditProcessCreationInfo.ImageFileName as u64 + } + }; + + if object_name_information_addr == 0 { + return Ok("".to_string()); + } + + let object_name_information = + read_virtual::(processor, object_name_information_addr)?; + + read_unicode_string( + processor, + object_name_information.Length as usize, + object_name_information.Buffer, + ) + } + + pub fn base_address( + &self, + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + ) -> Result { + let peb_address = match self { + WindowsEProcess::Windows10_0_10240_16384 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_10586_0 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_14393_0 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_15063_0 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_16299_15 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_17134_1 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_17763_107 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_18362_418 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_19041_1288 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_19045_2965 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_22000_194 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_22621_382 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_22631_2428 { eprocess } => eprocess.Peb as u64, + }; + let peb = WindowsPeb::new(processor, major, minor, build, peb_address)?; + Ok(peb.base()) + } + + #[allow(clippy::too_many_arguments)] + pub fn modules

( + &self, + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + download_directory: P, + not_found_full_name_cache: &mut HashSet, + user_debug_info: &DebugInfoConfig, + ) -> Result> + where + P: AsRef, + { + let peb_address = match self { + WindowsEProcess::Windows10_0_10240_16384 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_10586_0 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_14393_0 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_15063_0 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_16299_15 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_17134_1 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_17763_107 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_18362_418 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_19041_1288 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_19045_2965 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_22000_194 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_22621_382 { eprocess } => eprocess.Peb as u64, + WindowsEProcess::Windows10_0_22631_2428 { eprocess } => eprocess.Peb as u64, + }; + let mut directory_table_base = match self { + WindowsEProcess::Windows10_0_10240_16384 { eprocess } => { + eprocess.Pcb.DirectoryTableBase + } + WindowsEProcess::Windows10_0_10586_0 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_14393_0 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_15063_0 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_16299_15 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_17134_1 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_17763_107 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_18362_418 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_19041_1288 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_19045_2965 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_22000_194 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_22621_382 { eprocess } => eprocess.Pcb.DirectoryTableBase, + WindowsEProcess::Windows10_0_22631_2428 { eprocess } => eprocess.Pcb.DirectoryTableBase, + }; + + if directory_table_base == 0 { + directory_table_base = match self { + WindowsEProcess::Windows10_0_10240_16384 { .. } => { + bail!("No UserDirectoryTableBase before 1803"); + } + WindowsEProcess::Windows10_0_10586_0 { .. } => { + bail!("No UserDirectoryTableBase before 1803") + } + WindowsEProcess::Windows10_0_14393_0 { .. } => { + bail!("No UserDirectoryTableBase before 1803") + } + WindowsEProcess::Windows10_0_15063_0 { .. } => { + bail!("No UserDirectoryTableBase before 1803") + } + WindowsEProcess::Windows10_0_16299_15 { .. } => { + bail!("No UserDirectoryTableBase before 1803") + } + WindowsEProcess::Windows10_0_17134_1 { eprocess } => { + eprocess.Pcb.UserDirectoryTableBase + } + WindowsEProcess::Windows10_0_17763_107 { eprocess } => { + eprocess.Pcb.UserDirectoryTableBase + } + WindowsEProcess::Windows10_0_18362_418 { eprocess } => { + eprocess.Pcb.UserDirectoryTableBase + } + WindowsEProcess::Windows10_0_19041_1288 { eprocess } => { + eprocess.Pcb.UserDirectoryTableBase + } + WindowsEProcess::Windows10_0_19045_2965 { eprocess } => { + eprocess.Pcb.UserDirectoryTableBase + } + WindowsEProcess::Windows10_0_22000_194 { eprocess } => { + eprocess.Pcb.UserDirectoryTableBase + } + WindowsEProcess::Windows10_0_22621_382 { eprocess } => { + eprocess.Pcb.UserDirectoryTableBase + } + WindowsEProcess::Windows10_0_22631_2428 { eprocess } => { + eprocess.Pcb.UserDirectoryTableBase + } + }; + } + + let mut modules = Vec::new(); + + if peb_address != 0 { + let peb = WindowsPeb::new_dtb( + processor, + major, + minor, + build, + directory_table_base, + peb_address, + )?; + let ldr_address = peb.ldr_address(); + let ldr = WindowsPebLdrData::new_dtb( + processor, + major, + minor, + build, + directory_table_base, + ldr_address, + )?; + let mut list_entry = ldr.in_load_order_module_list(); + let last_entry = list_entry.Blink; + + while !list_entry.Flink.is_null() { + let ldr_data_entry = WindowsLdrDataTableEntry::new_dtb( + processor, + major, + minor, + build, + directory_table_base, + list_entry.Flink as u64, + )?; + + let base = ldr_data_entry.dll_base(); + let size = ldr_data_entry.size_of_image(); + let full_name = ldr_data_entry.full_name_dtb(processor, directory_table_base)?; + let base_name = ldr_data_entry.base_name_dtb(processor, directory_table_base)?; + let debug_info = full_name + .split('\\') + .last() + .ok_or_else(|| anyhow!("Failed to get file name")) + .and_then(|fname| { + // No need for DTB version because kernel is always mapped + DebugInfo::new( + processor, + fname, + base, + download_directory.as_ref(), + not_found_full_name_cache, + user_debug_info, + ) + }) + .ok() + .flatten(); + + debug!(get_object("tsffs")?, "Found module: {}", full_name); + + modules.push(ProcessModule { + base, + size, + full_name, + base_name, + debug_info, + }); + + list_entry = ldr_data_entry.in_load_order_links(); + + if list_entry.Flink == last_entry { + break; + } + } + } + + Ok(modules) + } +} + +pub enum WindowsKThread { + Windows10_0_10240_16384 { + kthread: windows_10_0_10240_16384_x64::_KTHREAD, + }, + Windows10_0_10586_0 { + kthread: windows_10_0_10586_0_x64::_KTHREAD, + }, + Windows10_0_14393_0 { + kthread: windows_10_0_14393_0_x64::_KTHREAD, + }, + Windows10_0_15063_0 { + kthread: windows_10_0_15063_0_x64::_KTHREAD, + }, + Windows10_0_16299_15 { + kthread: windows_10_0_16299_15_x64::_KTHREAD, + }, + Windows10_0_17134_1 { + kthread: windows_10_0_17134_1_x64::_KTHREAD, + }, + Windows10_0_17763_107 { + kthread: windows_10_0_17763_107_x64::_KTHREAD, + }, + Windows10_0_18362_418 { + kthread: windows_10_0_18362_418_x64::_KTHREAD, + }, + Windows10_0_19041_1288 { + kthread: windows_10_0_19041_1288_x64::_KTHREAD, + }, + Windows10_0_19045_2965 { + kthread: windows_10_0_19045_2965_x64::_KTHREAD, + }, + Windows10_0_22000_194 { + kthread: windows_10_0_22000_194_x64::_KTHREAD, + }, + Windows10_0_22621_382 { + kthread: windows_10_0_22621_382_x64::_KTHREAD, + }, + Windows10_0_22631_2428 { + kthread: windows_10_0_22631_2428_x64::_KTHREAD, + }, +} + +impl WindowsKThread { + pub fn new( + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + kthread_address: u64, + ) -> Result { + match (major, minor, build) { + (10, 0, 10240) => { + let kthread = read_virtual::( + processor, + kthread_address, + )?; + Ok(WindowsKThread::Windows10_0_10240_16384 { kthread }) + } + (10, 0, 10586) => { + let kthread = + read_virtual::(processor, kthread_address)?; + Ok(WindowsKThread::Windows10_0_10586_0 { kthread }) + } + (10, 0, 14393) => { + let kthread = + read_virtual::(processor, kthread_address)?; + Ok(WindowsKThread::Windows10_0_14393_0 { kthread }) + } + (10, 0, 15063) => { + let kthread = + read_virtual::(processor, kthread_address)?; + Ok(WindowsKThread::Windows10_0_15063_0 { kthread }) + } + (10, 0, 16299) => { + let kthread = read_virtual::( + processor, + kthread_address, + )?; + Ok(WindowsKThread::Windows10_0_16299_15 { kthread }) + } + (10, 0, 17134) => { + let kthread = + read_virtual::(processor, kthread_address)?; + Ok(WindowsKThread::Windows10_0_17134_1 { kthread }) + } + (10, 0, 17763) => { + let kthread = read_virtual::( + processor, + kthread_address, + )?; + Ok(WindowsKThread::Windows10_0_17763_107 { kthread }) + } + (10, 0, 18362) => { + let kthread = read_virtual::( + processor, + kthread_address, + )?; + Ok(WindowsKThread::Windows10_0_18362_418 { kthread }) + } + (10, 0, 19041) => { + let kthread = read_virtual::( + processor, + kthread_address, + )?; + Ok(WindowsKThread::Windows10_0_19041_1288 { kthread }) + } + (10, 0, 19045) => { + let kthread = read_virtual::( + processor, + kthread_address, + )?; + Ok(WindowsKThread::Windows10_0_19045_2965 { kthread }) + } + (10, 0, 22000) => { + let kthread = read_virtual::( + processor, + kthread_address, + )?; + Ok(WindowsKThread::Windows10_0_22000_194 { kthread }) + } + (10, 0, 22621) => { + let kthread = read_virtual::( + processor, + kthread_address, + )?; + Ok(WindowsKThread::Windows10_0_22621_382 { kthread }) + } + (10, 0, 22631) => { + let kthread = read_virtual::( + processor, + kthread_address, + )?; + Ok(WindowsKThread::Windows10_0_22631_2428 { kthread }) + } + (_, _, _) => { + bail!("Unsupported Windows version") + } + } + } + + pub fn process( + &self, + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + ) -> Result { + let process_address = match self { + WindowsKThread::Windows10_0_10240_16384 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_10586_0 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_14393_0 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_15063_0 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_16299_15 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_17134_1 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_17763_107 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_18362_418 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_19041_1288 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_19045_2965 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_22000_194 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_22621_382 { kthread } => kthread.Process as u64, + WindowsKThread::Windows10_0_22631_2428 { kthread } => kthread.Process as u64, + }; + WindowsEProcess::new(processor, major, minor, build, process_address) + } + + pub fn teb( + &self, + processor: *mut ConfObject, + major: u32, + minor: u32, + build: u32, + ) -> Result { + let teb_address = match self { + WindowsKThread::Windows10_0_10240_16384 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_10586_0 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_14393_0 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_15063_0 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_16299_15 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_17134_1 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_17763_107 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_18362_418 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_19041_1288 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_19045_2965 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_22000_194 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_22621_382 { kthread } => kthread.Teb as u64, + WindowsKThread::Windows10_0_22631_2428 { kthread } => kthread.Teb as u64, + }; + WindowsTeb::new(processor, major, minor, build, teb_address) + } +} diff --git a/src/os/windows/util.rs b/src/os/windows/util.rs new file mode 100644 index 00000000..83cf3a92 --- /dev/null +++ b/src/os/windows/util.rs @@ -0,0 +1,245 @@ +use std::mem::MaybeUninit; + +use anyhow::{anyhow, bail, Result}; +use simics::{get_interface, read_byte, Access, ConfObject, ProcessorInfoV2Interface}; + +use super::paging::{ + DIR_TABLE_BASE, PAGE_1GB_SHIFT, PAGE_2MB_SHIFT, PAGE_4KB_SHIFT, PDE, PDPTE, PDPTE_LARGE, PML4E, + PTE, VIRTUAL_ADDRESS, +}; + +/// Read from a virtual address +pub fn read_virtual(processor: *mut ConfObject, virtual_address: u64) -> Result +where + T: Sized, +{ + let mut processor_info_v2: ProcessorInfoV2Interface = get_interface(processor)?; + + let size = std::mem::size_of::(); + + let mut t = MaybeUninit::::uninit(); + + let memory = processor_info_v2.get_physical_memory()?; + + let contents = (0..size) + .map(|i| { + processor_info_v2 + .logical_to_physical(virtual_address + i as u64, Access::Sim_Access_Read) + .and_then(|b| read_byte(memory, b.address)) + .map_err(|e| anyhow!("Failed to read memory: {}", e)) + }) + .collect::>>()?; + + unsafe { + std::ptr::copy_nonoverlapping(contents.as_ptr(), t.as_mut_ptr() as *mut u8, size); + Ok(t.assume_init()) + } +} + +/// Read from a physical address +pub fn read_physical(processor: *mut ConfObject, physical_address: u64) -> Result { + let mut processor_info_v2: ProcessorInfoV2Interface = get_interface(processor)?; + + let size = std::mem::size_of::(); + + let mut t = MaybeUninit::::uninit(); + + let memory = processor_info_v2.get_physical_memory()?; + + let contents = (0..size) + .map(|i| { + read_byte(memory, physical_address + i as u64) + .map_err(|e| anyhow!("Failed to read memory: {}", e)) + }) + .collect::>>()?; + + unsafe { + std::ptr::copy_nonoverlapping(contents.as_ptr(), t.as_mut_ptr() as *mut u8, size); + Ok(t.assume_init()) + } +} + +/// Read from a virtual address with a specific directory table base +pub fn read_virtual_dtb( + processor: *mut ConfObject, + directory_table_base: u64, + virtual_address: u64, +) -> Result { + let physical_address = virtual_to_physical(processor, directory_table_base, virtual_address)?; + read_physical(processor, physical_address) +} + +/// Translate a virtual to physical address using a directory table base +pub fn virtual_to_physical( + processor: *mut ConfObject, + directory_table_base: u64, + virtual_address: u64, + // build: u32, +) -> Result { + let virtual_address = VIRTUAL_ADDRESS { + All: virtual_address, + }; + let dir_table_base = DIR_TABLE_BASE { + All: directory_table_base, + }; + let pml4e = read_physical::( + processor, + (unsafe { dir_table_base.Bits }.PhysicalAddress() << PAGE_4KB_SHIFT as u64) + + (unsafe { virtual_address.Bits }.Pml4Index() * 8), + )?; + + if unsafe { pml4e.Bits }.Present() == 0 { + bail!("PML4E not present"); + } + + let pdpte = read_physical::( + processor, + (unsafe { pml4e.Bits }.PhysicalAddress() << PAGE_4KB_SHIFT) + + (unsafe { virtual_address.Bits }.PdptIndex() * 8), + )?; + + if unsafe { pdpte.Bits }.Present() == 0 { + bail!("PDPTE not present"); + } + + if (unsafe { pdpte.All } >> 7) & 1 != 0 { + let pdpte_large = PDPTE_LARGE { + All: unsafe { pdpte.All }, + }; + return Ok( + ((unsafe { pdpte_large.Bits }.PhysicalAddress()) << PAGE_1GB_SHIFT) + + (unsafe { virtual_address.All } & (!(u64::MAX << PAGE_1GB_SHIFT))), + ); + } + + let pde = read_physical::( + processor, + (unsafe { pdpte.Bits }.PhysicalAddress() << PAGE_4KB_SHIFT) + + (unsafe { virtual_address.Bits }.PdIndex() * 8), + )?; + + if unsafe { pde.Bits }.Present() == 0 { + bail!("PDE not present"); + } + + if (unsafe { pde.All } >> 7) & 1 != 0 { + let pde_large = PDPTE_LARGE { + All: unsafe { pde.All }, + }; + return Ok( + ((unsafe { pde_large.Bits }.PhysicalAddress()) << PAGE_2MB_SHIFT) + + (unsafe { virtual_address.All } & (!(u64::MAX << PAGE_2MB_SHIFT))), + ); + } + + let pte = read_physical::( + processor, + (unsafe { pde.Bits }.PhysicalAddress() << PAGE_4KB_SHIFT) + + (unsafe { virtual_address.Bits }.PtIndex() * 8), + )?; + + if unsafe { pte.Bits }.Present() == 0 { + bail!("PTE not present"); + } + + Ok((unsafe { pte.Bits }.PhysicalAddress() << PAGE_4KB_SHIFT) + + unsafe { virtual_address.Bits }.PageIndex()) +} + +pub fn read_unicode_string( + processor: *mut ConfObject, + length: usize, + buffer: *const u16, +) -> Result { + if length == 0 || buffer.is_null() { + return Ok(String::new()); + } + + let mut string = Vec::new(); + let mut address = buffer as u64; + + for _ in 0..length { + let character = read_virtual::(processor, address)?; + + if character == 0 { + break; + } + + string.push(character); + address += 2; + } + + String::from_utf16(&string).map_err(|e| anyhow!("Failed to convert string: {}", e)) +} + +pub fn read_unicode_string_dtb( + processor: *mut ConfObject, + length: usize, + buffer: *const u16, + directory_table_base: u64, +) -> Result { + if length == 0 || buffer.is_null() { + return Ok(String::new()); + } + let mut string = Vec::new(); + let mut address = buffer as u64; + + for _ in 0..length { + let character = read_virtual_dtb::(processor, directory_table_base, address)?; + + if character == 0 { + break; + } + + string.push(character); + address += 2; + } + + String::from_utf16(&string).map_err(|e| anyhow!("Failed to convert string: {}", e)) +} + +pub fn read_nul_terminated_string(processor: *mut ConfObject, address: u64) -> Result { + if address == 0 { + return Ok(String::new()); + } + let mut string = String::new(); + let mut address = address; + + loop { + let character = read_virtual::(processor, address)?; + + if character == 0 { + break; + } + + string.push(character as char); + address += 1; + } + + Ok(string) +} + +pub fn read_nul_terminated_string_dtb( + processor: *mut ConfObject, + address: u64, + directory_table_base: u64, +) -> Result { + if address == 0 { + return Ok(String::new()); + } + let mut string = String::new(); + let mut address = address; + + loop { + let character = read_virtual_dtb::(processor, directory_table_base, address)?; + + if character == 0 { + break; + } + + string.push(character as char); + address += 1; + } + + Ok(string) +} diff --git a/src/source_cov/mod.rs b/src/source_cov/mod.rs new file mode 100644 index 00000000..6bdcb87a --- /dev/null +++ b/src/source_cov/mod.rs @@ -0,0 +1,133 @@ +use std::{ + collections::HashMap, + fs::read, + path::{Path, PathBuf}, +}; + +use anyhow::Result; +use md5::compute; +use pdb::{FileChecksum, FileInfo}; +use sha1::{Digest, Sha1}; +use sha2::Sha256; +use simics::{debug, get_object}; +use typed_path::{TypedComponent, TypedPath, UnixComponent, WindowsComponent}; +use walkdir::WalkDir; + +#[derive(Debug, Clone, Default)] +pub struct SourceCache { + prefix_lookup: HashMap, PathBuf>, + md5_lookup: HashMap, PathBuf>, + sha1_lookup: HashMap, PathBuf>, + sha256_lookup: HashMap, PathBuf>, +} + +impl SourceCache { + pub fn new

(src_dir: P) -> Result + where + P: AsRef, + { + let mut prefix_lookup = HashMap::new(); + let mut md5_lookup = HashMap::new(); + let mut sha1_lookup = HashMap::new(); + let mut sha256_lookup = HashMap::new(); + + let file_paths = WalkDir::new(src_dir) + .into_iter() + .filter_map(|entry| entry.ok()) + .filter(|entry| entry.file_type().is_file()) + .map(|entry| entry.path().to_path_buf()) + .collect::>(); + + for path in &file_paths { + let contents = read(path)?; + let md5 = compute(&contents).0.to_vec(); + let sha1 = Sha1::digest(&contents).to_vec(); + let sha256 = Sha256::digest(&contents).to_vec(); + md5_lookup.insert(md5, path.clone()); + sha1_lookup.insert(sha1, path.clone()); + sha256_lookup.insert(sha256, path.clone()); + let mut components = path + .components() + .filter_map(|c| { + if let std::path::Component::Normal(c) = c { + Some(c.to_string_lossy().to_string()) + } else { + None + } + }) + .collect::>(); + + // Create a list of component lists starting from the full path, then the full path + // minus the first component, then the full path minus the first two components, etc. + // This is used to create a lookup table for the source files. + while !components.is_empty() { + prefix_lookup.insert(components.clone(), path.clone()); + components.remove(0); + } + } + + if let Ok(o) = get_object("tsffs") { + debug!(o, "Cached {} source files", file_paths.len()); + } + + Ok(Self { + prefix_lookup, + md5_lookup, + sha1_lookup, + sha256_lookup, + }) + } + + pub fn lookup_file_name_components(&self, file_name: &str) -> Option<&Path> { + let mut file_name_components = TypedPath::derive(&file_name.to_string().to_string()) + .components() + .filter_map(|c| match c { + TypedComponent::Unix(u) => { + if let UnixComponent::Normal(c) = u { + String::from_utf8(c.to_vec()).ok() + } else { + None + } + } + TypedComponent::Windows(w) => { + if let WindowsComponent::Normal(c) = w { + String::from_utf8(c.to_vec()).ok() + } else { + None + } + } + }) + .collect::>(); + + while !file_name_components.is_empty() { + if let Some(file_path) = self.prefix_lookup.get(&file_name_components) { + return Some(file_path); + } + + file_name_components.remove(0); + } + + None + } + + pub fn lookup_pdb(&self, file_info: &FileInfo, file_name: &str) -> Result> { + Ok(match file_info.checksum { + FileChecksum::None => self.lookup_file_name_components(file_name), + FileChecksum::Md5(m) => self + .md5_lookup + .get(m) + .map(|p| p.as_path()) + .or_else(|| self.lookup_file_name_components(file_name)), + FileChecksum::Sha1(s1) => self + .sha1_lookup + .get(s1) + .map(|p| p.as_path()) + .or_else(|| self.lookup_file_name_components(file_name)), + FileChecksum::Sha256(s256) => self + .sha256_lookup + .get(s256) + .map(|p| p.as_path()) + .or_else(|| self.lookup_file_name_components(file_name)), + }) + } +} diff --git a/src/tracer/mod.rs b/src/tracer/mod.rs index c08c125c..9f0f16e3 100644 --- a/src/tracer/mod.rs +++ b/src/tracer/mod.rs @@ -2,17 +2,19 @@ // SPDX-License-Identifier: Apache-2.0 use anyhow::{anyhow, bail, Error, Result}; +use cpp_demangle::{DemangleOptions, Symbol}; use ffi::ffi; use libafl::prelude::CmpValues; use libafl_bolts::{AsMutSlice, AsSlice}; use libafl_targets::{AFLppCmpLogOperands, AFL_CMP_TYPE_INS, CMPLOG_MAP_H}; +use rustc_demangle::try_demangle; use serde::{Deserialize, Serialize}; use simics::{ api::{ get_processor_number, sys::instruction_handle_t, AsConfObject, AttrValue, AttrValueType, ConfObject, }, - trace, + get_interface, trace, ProcessorInfoV2Interface, }; use std::{ collections::HashMap, ffi::c_void, fmt::Display, hash::Hash, num::Wrapping, @@ -22,7 +24,19 @@ use typed_builder::TypedBuilder; use crate::{arch::ArchitectureOperations, Tsffs}; -#[derive(Deserialize, Serialize, Debug, Default)] +#[derive(Clone, Deserialize, Serialize, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct ExecutionTraceSymbol { + /// The symbol name + pub symbol: String, + /// The demangled symbol name, if it demangles correctly + pub symbol_demangled: Option, + /// The offset into the symbol + pub offset: u64, + /// The containing module's name (usually the path to the executable or dll) + pub module: String, +} + +#[derive(Clone, Deserialize, Serialize, Debug, Default)] pub(crate) struct ExecutionTrace(pub HashMap>); impl Hash for ExecutionTrace { @@ -36,13 +50,17 @@ impl Hash for ExecutionTrace { } } -#[derive(TypedBuilder, Deserialize, Serialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive( + Clone, TypedBuilder, Deserialize, Serialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, +)] pub(crate) struct ExecutionTraceEntry { pc: u64, #[builder(default, setter(into, strip_option))] insn: Option, #[builder(default, setter(into, strip_option))] insn_bytes: Option>, + #[builder(default, setter(into))] + symbol: Option, } #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -356,7 +374,7 @@ impl Tsffs { ) -> Result<()> { let processor_number = get_processor_number(cpu)?; - if self.cmplog && self.cmplog_enabled { + if self.coverage_enabled && self.cmplog && self.cmplog_enabled { if let Some(arch) = self.processors.get_mut(&processor_number) { match arch.trace_cmp(handle) { Ok(r) => { @@ -373,6 +391,110 @@ impl Tsffs { } } + let symcov = if self.coverage_enabled + && self.windows + && self.symbolic_coverage + && (self.save_all_execution_traces + || self.save_interesting_execution_traces + || self.save_solution_execution_traces) + { + // Get the current instruction address + let mut processor_information_v2 = get_interface::(cpu)?; + let pc = processor_information_v2.get_program_counter()?; + self.windows_os_info + .symbol_lookup_trees + .get(&processor_number) + .and_then(|lookup_tree| { + lookup_tree + .query(pc..pc + 1) + .next() + .map(|symbol_for_query| { + let offset = + pc - symbol_for_query.value.base + symbol_for_query.value.rva; + let symbol_demangled = try_demangle(&symbol_for_query.value.name) + .map(|d| d.to_string()) + .ok() + .or_else(|| { + Symbol::new(&symbol_for_query.value.name) + .ok() + .and_then(|s| s.demangle(&DemangleOptions::new()).ok()) + }); + + if let Some(function_start_line) = symbol_for_query.value.lines.first() + { + let record = self + .coverage + .get_or_insert_mut(&function_start_line.file_path); + let pc_lines = symbol_for_query + .value + .lines + .iter() + .filter(|line_info| { + pc - symbol_for_query.value.base >= line_info.rva + && pc - symbol_for_query.value.base + < line_info.rva + line_info.size as u64 + }) + .flat_map(|l| (l.start_line..=l.end_line).map(|i| i as usize)) + .collect::>(); + + if pc_lines.contains(&(function_start_line.start_line as usize)) { + // Increment function hit counter if we just hit the fn + record.increment_function_data(&symbol_for_query.value.name); + } + + pc_lines.iter().for_each(|line| { + record.increment_line(*line); + }); + } + ExecutionTraceSymbol { + symbol: symbol_for_query.value.name.clone(), + symbol_demangled, + offset, + module: symbol_for_query.value.module.clone(), + } + }) + }) + } else if self.coverage_enabled && self.symbolic_coverage { + let mut processor_information_v2 = get_interface::(cpu)?; + let pc = processor_information_v2.get_program_counter()?; + if let Some(lookup_tree) = self + .windows_os_info + .symbol_lookup_trees + .get(&processor_number) + { + if let Some(symbol_for_query) = lookup_tree.query(pc..pc + 1).next() { + if let Some(function_start_line) = symbol_for_query.value.lines.first() { + let record = self + .coverage + .get_or_insert_mut(&function_start_line.file_path); + let pc_lines = symbol_for_query + .value + .lines + .iter() + .filter(|line_info| { + pc - symbol_for_query.value.base >= line_info.rva + && pc - symbol_for_query.value.base + < line_info.rva + line_info.size as u64 + }) + .flat_map(|l| (l.start_line..=l.end_line).map(|i| i as usize)) + .collect::>(); + + if pc_lines.contains(&(function_start_line.start_line as usize)) { + // Increment function hit counter if we just hit the fn + record.increment_function_data(&symbol_for_query.value.name); + } + + pc_lines.iter().for_each(|line| { + record.increment_line(*line); + }); + } + } + } + None + } else { + None + }; + if self.coverage_enabled && (self.save_all_execution_traces || self.save_interesting_execution_traces @@ -401,12 +523,14 @@ impl Tsffs { .pc(arch.processor_info_v2().get_program_counter()?) .insn(disassembly_string) .insn_bytes(instruction_bytes.to_vec()) + .symbol(symcov) .build() } else { ExecutionTraceEntry::builder() .pc(arch.processor_info_v2().get_program_counter()?) .insn("(unknown)".to_string()) .insn_bytes(instruction_bytes.to_vec()) + .symbol(symcov) .build() } }); diff --git a/tests/rsrc/test-lcov/html/home/index.html b/tests/rsrc/test-lcov/html/home/index.html new file mode 100644 index 00000000..413545a9 --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/index.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - html - home
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines87.50%2421
Functions100.00%44
File/DirectoryLine CoverageTotal LinesHit LinesFunction CoverageTotal FunctionsHit Functions
rhart87.50%2421100.00%44
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/index.html b/tests/rsrc/test-lcov/html/home/rhart/hub/index.html new file mode 100644 index 00000000..6d9fbba5 --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/index.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - rhart - hub
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines87.50%2421
Functions100.00%44
File/DirectoryLine CoverageTotal LinesHit LinesFunction CoverageTotal FunctionsHit Functions
tsffs87.50%2421100.00%44
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/index.html b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/index.html new file mode 100644 index 00000000..95441d45 --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/index.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - hub - tsffs
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines87.50%2421
Functions100.00%44
File/DirectoryLine CoverageTotal LinesHit LinesFunction CoverageTotal FunctionsHit Functions
tests87.50%2421100.00%44
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/index.html b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/index.html new file mode 100644 index 00000000..03c96589 --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/index.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - tsffs - tests
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines87.50%2421
Functions100.00%44
File/DirectoryLine CoverageTotal LinesHit LinesFunction CoverageTotal FunctionsHit Functions
rsrc87.50%2421100.00%44
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/index.html b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/index.html new file mode 100644 index 00000000..9e774b97 --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/index.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - tests - rsrc
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines87.50%2421
Functions100.00%44
File/DirectoryLine CoverageTotal LinesHit LinesFunction CoverageTotal FunctionsHit Functions
test-lcov87.50%2421100.00%44
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/index.html b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/index.html new file mode 100644 index 00000000..0b050eb0 --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/index.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - rsrc - test-lcov
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines87.50%2421
Functions100.00%44
File/DirectoryLine CoverageTotal LinesHit LinesFunction CoverageTotal FunctionsHit Functions
subdir285.71%76100.00%11
subdir185.71%76100.00%11
test.c85.71%76100.00%11
test2.c100.00%33100.00%11
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir1/index.html b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir1/index.html new file mode 100644 index 00000000..da06410a --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir1/index.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - test-lcov - subdir1
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines85.71%76
Functions100.00%11
File/DirectoryLine CoverageTotal LinesHit LinesFunction CoverageTotal FunctionsHit Functions
test.c85.71%76100.00%11
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir1/test.c.html b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir1/test.c.html new file mode 100644 index 00000000..8f899fa4 --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir1/test.c.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - subdir1 - test.c
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines85.71%76
Functions100.00%11
LineHitsSource Code
1-#include <stdio.h>
2-extern int x(int);
3-
41int main() {
51  int a = 0;
6-
71  a += 1;
8-
91  a = x(a);
10-
111  if (a == 15) {
120    printf("%s\n", "hello");
13-  } else {
141    printf("no\n");
15-  }
16-}
FunctionHits
main1
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir2/index.html b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir2/index.html new file mode 100644 index 00000000..a7930b14 --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir2/index.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - test-lcov - subdir2
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines85.71%76
Functions100.00%11
File/DirectoryLine CoverageTotal LinesHit LinesFunction CoverageTotal FunctionsHit Functions
test-subdir2.c85.71%76100.00%11
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir2/test-subdir2.c.html b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir2/test-subdir2.c.html new file mode 100644 index 00000000..d698687f --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/subdir2/test-subdir2.c.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - subdir2 - test-subdir2.c
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines85.71%76
Functions100.00%11
LineHitsSource Code
1-#include <stdio.h>
2-extern int x(int);
3-
41int main() {
51  int a = 0;
6-
71  a += 1;
8-
91  a = x(a);
10-
111  if (a == 15) {
120    printf("%s\n", "hello");
13-  } else {
141    printf("no\n");
15-  }
16-}
FunctionHits
main1
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/test.c.html b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/test.c.html new file mode 100644 index 00000000..998c846c --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/test.c.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - test-lcov - test.c
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines85.71%76
Functions100.00%11
LineHitsSource Code
1-#include <stdio.h>
2-extern int x(int);
3-
41int main() {
51    int a = 0;
6-
71    a += 1;
8-
91    a = x(a);
10-
111    if (a == 15) {
120        printf("%s\n", "hello");
13-    } else {
141        printf("no\n");
15-    }
16-}
FunctionHits
main1
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/test2.c.html b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/test2.c.html new file mode 100644 index 00000000..58a0e4e9 --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/hub/tsffs/tests/rsrc/test-lcov/test2.c.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - test-lcov - test2.c
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines100.00%33
Functions100.00%11
LineHitsSource Code
11int x(int a) {
21    return a;
31}
FunctionHits
x1
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/home/rhart/index.html b/tests/rsrc/test-lcov/html/home/rhart/index.html new file mode 100644 index 00000000..d2a302c8 --- /dev/null +++ b/tests/rsrc/test-lcov/html/home/rhart/index.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - home - rhart
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines87.50%2421
Functions100.00%44
File/DirectoryLine CoverageTotal LinesHit LinesFunction CoverageTotal FunctionsHit Functions
hub87.50%2421100.00%44
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/html/index.html b/tests/rsrc/test-lcov/html/index.html new file mode 100644 index 00000000..f4394731 --- /dev/null +++ b/tests/rsrc/test-lcov/html/index.html @@ -0,0 +1 @@ +TSFFS Coverage Report
TSFFS Code Coverage Report
Current view:Top Level - html
Generated On2024-07-16 17:40:25
CoverageTotalHit
Lines87.50%2421
Functions100.00%44
File/DirectoryLine CoverageTotal LinesHit LinesFunction CoverageTotal FunctionsHit Functions
home87.50%2421100.00%44
\ No newline at end of file diff --git a/tests/rsrc/test-lcov/subdir1/test.c b/tests/rsrc/test-lcov/subdir1/test.c new file mode 100644 index 00000000..1ff5b4fb --- /dev/null +++ b/tests/rsrc/test-lcov/subdir1/test.c @@ -0,0 +1,16 @@ +#include +extern int x(int); + +int main() { + int a = 0; + + a += 1; + + a = x(a); + + if (a == 15) { + printf("%s\n", "hello"); + } else { + printf("no\n"); + } +} diff --git a/tests/rsrc/test-lcov/subdir2/test-subdir2.c b/tests/rsrc/test-lcov/subdir2/test-subdir2.c new file mode 100644 index 00000000..1ff5b4fb --- /dev/null +++ b/tests/rsrc/test-lcov/subdir2/test-subdir2.c @@ -0,0 +1,16 @@ +#include +extern int x(int); + +int main() { + int a = 0; + + a += 1; + + a = x(a); + + if (a == 15) { + printf("%s\n", "hello"); + } else { + printf("no\n"); + } +} diff --git a/tests/rsrc/test-lcov/test.c b/tests/rsrc/test-lcov/test.c new file mode 100644 index 00000000..a1c3a8d0 --- /dev/null +++ b/tests/rsrc/test-lcov/test.c @@ -0,0 +1,16 @@ +#include +extern int x(int); + +int main() { + int a = 0; + + a += 1; + + a = x(a); + + if (a == 15) { + printf("%s\n", "hello"); + } else { + printf("no\n"); + } +} diff --git a/tests/rsrc/test-lcov/test2.c b/tests/rsrc/test-lcov/test2.c new file mode 100644 index 00000000..e8492f41 --- /dev/null +++ b/tests/rsrc/test-lcov/test2.c @@ -0,0 +1,3 @@ +int x(int a) { + return a; +}